From a70afcb170bb2543ff7ec56fed7dde1ef8a0ab85 Mon Sep 17 00:00:00 2001 From: amonemi Date: Tue, 28 Jan 2025 19:37:07 +0100 Subject: [PATCH 001/107] add parameter explanation comment to Noc configuration file --- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 2937 +++++++++--------- mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl | 9 + 2 files changed, 1484 insertions(+), 1462 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index a628f8b..b82ffde 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -25,6 +25,7 @@ require "diagram.pl"; require "orcc.pl"; +my %noc_param_comment; sub initial_default_param{ my $mpsoc=shift; @@ -90,14 +91,14 @@ sub get_soc_list { } sub copy_back_custom_soc_param{ - my ($new,$old)=@_; - my @tiles = $old->top_get_custom_tile_list(); - foreach my $tile (@tiles){ - my %l =$old->top_get_custom_soc_param($tile); - $new->top_add_custom_soc_param (\%l,$tile); - } - -} + my ($new,$old)=@_; + my @tiles = $old->top_get_custom_tile_list(); + foreach my $tile (@tiles){ + my %l =$old->top_get_custom_soc_param($tile); + $new->top_add_custom_soc_param (\%l,$tile); + } + +} sub get_NI_instance_list { my $top=shift; @@ -236,12 +237,12 @@ sub check_inserted_ip_nums{ }else { #save the entered ips if( scalar @all_num>0){ - $mpsoc->mpsoc_add_soc_tiles_num($name,\@all_num); - return \@all_num; + $mpsoc->mpsoc_add_soc_tiles_num($name,\@all_num); + return \@all_num; } else { - $mpsoc->mpsoc_add_soc_tiles_num($name,undef); - return undef; + $mpsoc->mpsoc_add_soc_tiles_num($name,undef); + return undef; } #set_gui_status($mpsoc,"ref",1); } @@ -262,8 +263,8 @@ sub get_soc_parameter_setting{ my $string = join (',',@tiles ); my $window = def_popwin_size(40,40,"Parameter setting for $soc_name mapped to tile( $string ) ",'percent'); my $table = get_soc_parameter_setting_table($mpsoc,$soc_name,$window,$tiles_ref); - $window->add($table); - $window->show_all; + $window->add($table); + $window->show_all; } @@ -291,9 +292,9 @@ sub get_soc_parameter_setting_table{ foreach my $p (@params){ my ($default,$type,$content,$info,$global_param,$redefine)=$top->top_get_parameter($inst,$p); my $show = ($type ne "Fixed"); - $default= $param_value{$p} if(defined $param_value{$p}); - ($row,$column)=add_param_widget($mpsoc,$p,$p, $default,$type,$content,$info, $table,$row,$column,$show,'current_tile_param',undef,undef,'vertical'); - } + $default= $param_value{$p} if(defined $param_value{$p}); + ($row,$column)=add_param_widget($mpsoc,$p,$p, $default,$type,$content,$info, $table,$row,$column,$show,'current_tile_param',undef,undef,'vertical'); + } # if ($type eq "Entry"){ @@ -355,14 +356,14 @@ sub get_soc_parameter_setting_table{ $window->destroy if(defined $window); #save new values my $ref=$mpsoc->object_get_attribute('current_tile_param'); - %param_value=%{$ref}; + %param_value=%{$ref}; # if(!defined $tile ) { # $top->top_add_default_soc_param(\%param_value); # $mpsoc->object_add_attribute('soc_param',"default",\%param_value); # } # else { - foreach my $tile (@tiles){ + foreach my $tile (@tiles){ $top->top_add_custom_soc_param(\%param_value,$tile); $mpsoc->object_add_attribute('soc_param',"custom_${soc_name}",\%param_value); } @@ -401,8 +402,8 @@ sub tile_set_widget{ my $data=$entry->get_text(); my $r=check_inserted_ip_nums($mpsoc,$soc_name,$data); if(defined $r){ - my @all_num = @{$r}; - get_soc_parameter_setting($mpsoc,$soc_name,\@all_num); + my @all_num = @{$r}; + get_soc_parameter_setting($mpsoc,$soc_name,\@all_num); } }); @@ -456,19 +457,19 @@ sub defualt_tilles_setting { if(defined $file){$entry->set_text($file);} - $browse->signal_connect("clicked"=> sub{ - my $entry_ref=$_[1]; - my $file; - my $dialog = gen_folder_dialog('Select tile directory'); - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; + $browse->signal_connect("clicked"=> sub{ + my $entry_ref=$_[1]; + my $file; + my $dialog = gen_folder_dialog('Select tile directory'); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; $$entry_ref->set_text($file); $mpsoc->object_add_attribute('setting','soc_path',$file); $mpsoc->mpsoc_remove_all_soc(); set_gui_status($mpsoc,"ref",1); #check_input_file($file,$socgen,$info); #print "file = $file\n"; - } + } $dialog->destroy; } , \$entry); @@ -535,34 +536,37 @@ sub defualt_tilles_setting { sub noc_topology_setting_gui { - my ($mpsoc,$table,$txview,$row,$show_noc,$noc_id)=@_; + my ($mpsoc,$table,$txview,$row,$show_noc,$noc_id)=@_; my $noc_param="noc_param$noc_id"; - my $coltmp=0; - # topology - my $label='Topology'; - my $param='TOPOLOGY'; - my $default='"MESH"'; - my $content='"MESH","FMESH","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM"'; - my $type='Combo-box'; - my $info="NoC topology"; - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); + my $coltmp=0; + # topology + my $label='Topology'; + my $param='TOPOLOGY'; + my $default='"MESH"'; + my $content='"MESH","FMESH","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM"'; + my $type='Combo-box'; + my $info="Specifies the NoC topology. + Options include $content"; + $noc_param_comment{$param}="$info"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); my $topology=$mpsoc->object_get_attribute($noc_param,'TOPOLOGY'); - if($topology ne '"CUSTOM"' ){ + if($topology ne '"CUSTOM"' ){ #topology T1 parameter - $label= - ($topology eq '"FATTREE"' || $topology eq '"TREE"')? 'K' : - ($topology eq '"STAR"')? "Total Endpoint number" : 'Routers per row'; - $param= 'T1'; - $default= '2'; - $content= - ($topology eq '"MESH"' || $topology eq '"TORUS"') ? '2,16,1': - ($topology eq '"FMESH"')? '1,16,1': - ($topology eq '"FATTREE"' || $topology eq '"TREE"' )? '2,6,1':'2,64,1'; - $info= ($topology eq '"FATTREE"' || $topology eq '"TREE"' )? 'number of last level individual router`s endpoints.' :'Number of NoC routers in row (X dimension)'; - $type= 'Spin-button'; - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); + $label= + ($topology eq '"FATTREE"' || $topology eq '"TREE"')? 'K' : + ($topology eq '"STAR"')? "Total Endpoint number" : 'Routers per row'; + $param= 'T1'; + $default= '2'; + $content= + ($topology eq '"MESH"' || $topology eq '"TORUS"') ? '2,16,1': + ($topology eq '"FMESH"')? '1,16,1': + ($topology eq '"FATTREE"' || $topology eq '"TREE"' )? '2,6,1':'2,64,1'; + $info= ($topology eq '"FATTREE"' || $topology eq '"TREE"' )? 'number of last level individual router`s endpoints.' :'Number of NoC routers in row (X dimension)'; + $type= 'Spin-button'; + $noc_param_comment{$param}="$info"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); #Topology T2 parameter @@ -572,7 +576,8 @@ sub noc_topology_setting_gui { $default='2'; $content= ($topology eq '"FMESH"')? '1,16,1': '2,16,1'; $info= ($topology eq '"FATTREE"' || $topology eq '"TREE"')? 'Fattree layer number (The height of FT)':'Number of NoC routers in column (Y dimension)'; - $type= 'Spin-button'; + $type= 'Spin-button'; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); } else { $mpsoc->object_add_attribute($noc_param,'T2',1); @@ -580,22 +585,22 @@ sub noc_topology_setting_gui { #Topology T3 parameter if($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"TORUS"' || $topology eq '"RING"' || $topology eq '"LINE"') { - $label="Router's endpoint number"; - $param= 'T3'; + $label="Router's endpoint number"; + $param= 'T3'; $default='1'; $content='1,4,1'; - $info= "In $topology topology, each router can have up to 4 endpoint processing tile."; - $type= 'Spin-button'; + $info= "Number of endpoints per router. In $topology topology, each router + can have up to 4 endpoint processing tile."; + $type= 'Spin-button'; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); } - - - }else{#its a custom Topology - ($row,$coltmp)=config_custom_topology_gui($mpsoc,$table,$txview,$row,$noc_id); - } - return ($row,$coltmp); + }else{#its a custom Topology + ($row,$coltmp)=config_custom_topology_gui($mpsoc,$table,$txview,$row,$noc_id); + } + return ($row,$coltmp); } @@ -611,16 +616,17 @@ sub noc_config{ my $row=0; my $title=gen_label_in_center("NoC Configuration"); $table->attach ($title , 0, 4, $row, $row+1,'expand','shrink',2,2); $row++; - add_Hsep_to_table ($table,0,4,$row); $row++; - + add_Hsep_to_table ($table,0,4,$row); $row++; + my $label; my $param; my $default; my $type; my $content; my $info; + - + #parameter start my $b1; my $show_noc=$mpsoc->object_get_attribute('setting','show_noc_setting'); @@ -652,8 +658,8 @@ sub noc_config{ ($row,$coltmp) =noc_topology_setting_gui($mpsoc,$table,$txview,$row,$show_noc,$noc_id); - my $topology=$mpsoc->object_get_attribute($noc_param,'TOPOLOGY'); - + my $topology=$mpsoc->object_get_attribute($noc_param,'TOPOLOGY'); + #VC number per port if($router_type eq '"VC_BASED"'){ my $v=$mpsoc->object_get_attribute($noc_param,'V'); @@ -664,8 +670,10 @@ sub noc_config{ $type='Spin-button'; $content='2,16,1'; $info='Number of Virtual chanel per each router port'; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); } else { + $noc_param_comment{'V'}="Number of Virtual chanel per each router port. V is equal to 1 means there is no VC."; $mpsoc->object_add_attribute($noc_param,'V',1); $mpsoc->object_add_attribute($noc_param,'C',0); } @@ -677,6 +685,7 @@ sub noc_config{ $content='2,256,1'; $type='Spin-button'; $info=($router_type eq '"VC_BASED"')? 'Buffer queue size per VC in flits' : 'Buffer queue size in flits'; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,undef); @@ -686,16 +695,16 @@ sub noc_config{ $default='4'; $content='2,256,1'; $type='Spin-button'; - $info = "The Local router ports buffer width (LB) is the width of the ports connected to the endpoints and can take different buffer sizes than other routers ports buffer width (B) connected to neighboring routers .It is valid only for MESH,FMESH, TORUS,LINE and RING topologies. In FMESH topology, this parameter does not affect the width of extra endpoints connected to edge routers."; - + $info = "Buffer width for local router ports connected to endpoints. + May differ from B, which is for neighboring router ports. + Applicable to MESH, FMESH, TORUS, LINE, and RING topologies. + In FMESH, LB does not affect extra endpoints on edge routers."; + $noc_param_comment{$param}="$info"; if ($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"TORUS"' || $topology eq '"RING"' || $topology eq '"LINE"'){ - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,undef); + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,undef); }else{ - $mpsoc->object_add_attribute($noc_param,'LB','B'); - } - - - + $mpsoc->object_add_attribute($noc_param,'LB','B'); + } #packet payload width $label='Payload width'; @@ -704,6 +713,7 @@ sub noc_config{ $content='32,256,32'; $type='Spin-button'; $info="The packet payload width in bits"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info,$table,$row,undef,$show_noc,$noc_param,undef); if($topology ne '"CUSTOM"' ){ @@ -722,137 +732,137 @@ sub noc_config{ $content=($topology eq '"MESH"' || $topology eq '"FMESH"')? '"XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN"' : ($topology eq '"TORUS"')? '"TRANC_XY","TRANC_WEST_FIRST","TRANC_NORTH_LAST","TRANC_NEGETIVE_FIRST"': ($topology eq '"RING"')? '"TRANC_XY"' : - ($topology eq '"LINE"')? '"XY"': + ($topology eq '"LINE"')? '"XY"': ($topology eq '"FATTREE"')? '"NCA_RND_UP","NCA_STRAIGHT_UP","NCA_DST_UP"' : - ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; - + ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; } $default=($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"LINE"' )? '"XY"': - ($topology eq '"TORUS"'|| $topology eq '"RING"')? '"TRANC_XY"' : - ($topology eq '"FATTREE"')? '"NCA_STRAIGHT_UP"' : - ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; - + ($topology eq '"TORUS"'|| $topology eq '"RING"')? '"TRANC_XY"' : + ($topology eq '"FATTREE"')? '"NCA_STRAIGHT_UP"' : + ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; + my $info_mesh="Select the routing algorithm: XY(DoR) , partially adaptive (Turn models). Fully adaptive (Duato) "; - my $info_fat="Nearest common ancestor (NCA) where the up port is selected randomly (RND), based on destination endpoint address (DST) or it is the top port that is located in front of the port which has received the packet (STRAIGHT) "; + my $info_fat="Nearest common ancestor (NCA) where the up port is selected randomly (RND), + based on destination endpoint address (DST) or it is the top port that is located in front + of the port which has received the packet (STRAIGHT) "; $info=($topology eq '"FATTREE"')? $info_fat : - ($topology eq '"TREE"') ? "Nearest common ancestor": $info_mesh; + ($topology eq '"TREE"') ? "Nearest common ancestor": $info_mesh; + $noc_param_comment{$param}="$info + options are $content"; my $show_routing =($topology eq '"STAR"' )? 0 : $show_noc; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_routing,$noc_param,1); - } - #PCK_TYPE - $label='Packet type'; + #PCK_TYPE + $label='Packet type'; $param='PCK_TYPE'; $default='"MULTI_FLIT"'; $content='"MULTI_FLIT","SINGLE_FLIT"'; $type="Combo-box"; - $info="Define packet type: SINGLE_FLIT: all packets send to NoC are single-flit sized. - Multi-flit: packets can be consists of one or several flits. A multi-flit packet can be - a)single-flit sized : both headr and tail flag must be asserted for this flit, - b)two-flit sized: a header flit and a tail flit, or - c)more than 2 fits: start with a headr flit, continued with one or more body flits and end up with a tail flit - For MULTI-FLIT packet you need to defin ethe minum size of a paket that can be injecte to the NoC. - "; - + $info="Packet type. + - SINGLE_FLIT: All packets are single-flit sized. + - MULTI_FLIT: Packets can be single-flit, two-flit, or multi-flit sized: + a) Single-flit: Head and tail flags set on one flit. + b) Two-flit: Separate header and tail flits. + c) Multi-flit: Header, one or more body flits, and a tail flit."; + $noc_param_comment{$param}="$info"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); - - my $pck_type=$mpsoc->object_get_attribute($noc_param,'PCK_TYPE'); - - if($pck_type eq '"MULTI_FLIT"'){ - - #MIN_PCK_SIZE - # 2 //minimum packet size in flits. The minimum value is 1. - $label='Minimum packet size'; - $param='MIN_PCK_SIZE'; - $default='2'; - $content='1,65535,1'; - $type='Spin-button'; - $info="The minimum packet size in flits. In atomic VC re-allocation, it is just important to define if the single-flit sized packets are allowed to be injected to the NoC by defining this parameter value as one. Setting any larger value than one results in the same architecture and the NoC works correctly even if it receives smaller packets size as while as they are not single flit -sized packets. However, for non-atomic VC reallocation NoCs, you have to define the exact value as it defines the NoC control registers' internal buffers. The NoC may crash once it receives packets having smaler size than the defined minimum packet size."; - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,undef); - }else{ - $mpsoc->object_add_attribute($noc_param,'MIN_PCK_SIZE',1); - } + + my $pck_type=$mpsoc->object_get_attribute($noc_param,'PCK_TYPE'); + + if($pck_type eq '"MULTI_FLIT"'){ + + #MIN_PCK_SIZE + # 2 //minimum packet size in flits. The minimum value is 1. + $label='Minimum packet size'; + $param='MIN_PCK_SIZE'; + $default='2'; + $content='1,65535,1'; + $type='Spin-button'; + $info="Minimum packet size in flits. + - For atomic VC reallocation, any value ≥1 is valid. + - For non-atomic VC reallocation, this value defines buffer behavior. + Note: Setting a value smaller than received packet size may cause crashes."; + $noc_param_comment{$param}="$info"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,undef); + }else{ + $mpsoc->object_add_attribute($noc_param,'MIN_PCK_SIZE',1); + } # BYTE_EN $label='Byte Enable'; $param='BYTE_EN'; $default= 0; - $info='0:disable, 1: enable. Add byte enable (BE) filed to header flit which shows the location of last valid byte in tail flit. It is needed once the send data unit is smaller than Fpay.'; + $info='0 - Disable, 1 - Enable. + Adds a Byte Enable (BE) field to the header flit, indicating the location of + the last valid byte in the tail flit. This is required when the data unit being + sent is smaller than the Fpay value.'; $content='0,1'; $type="Combo-box"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param); - - - - #CAST_TYPE $label='Casting Type'; $param='CAST_TYPE'; $default= '"UNICAST"'; - $info='Configure a NoC as Unicast, Multicast, or Broadcast NoC. In Unicast NoC, a packet can be sent to only one destination. In Multicast, a single packet can have multiple target destination nodes, whereas, Broadcast packets are sent to all other destination nodes. For Multicast and Broadcast NoC, only one copy of a packet must be injected into the source router. The routers in the path then fork the packets to different output ports when necessary. Multicast and Broadcast can be selected as FULL, where all destinations can be included in packet destination list, or as PARTIAL where a user-defined subset of nodes (defined with MCAST_ENDP_LIST parameter) can be targeted in destination lists. The other nodes not marked in MCAST_ENDP_LIST can only receive unicast packets. '; $content='"UNICAST","MULTICAST_PARTIAL","MULTICAST_FULL","BROADCAST_PARTIAL","BROADCAST_FULL"'; + $info="Specifies NoC communication type. + - UNICAST: A packet targets a single destination. + - MULTICAST/BROADCAST: A single packet targets multiple/all destinations. + Options: FULL (all nodes) or PARTIAL (defined by MCAST_ENDP_LIST). + Select one of $content"; + $type="Combo-box"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); - my $cast_type=$mpsoc->object_get_attribute($noc_param,'CAST_TYPE'); my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); - my $cast = $mpsoc->object_get_attribute($noc_param,"MCAST_ENDP_LIST"); + my $cast = $mpsoc->object_get_attribute($noc_param,"MCAST_ENDP_LIST"); if(!defined $cast){ - my $h=0; - my $n=""; - for (my $i=0; $i<$NE; $i++){ - $h+= (1<<$i%4); - if(($i+1) % 4==0){ - $n="$h".$n if($h<10); - $n=chr($h-10+97).$n if($h>9); - $h=0; - } - } - $n="$h".$n if($h!=0); - $n="'h".$n; - $mpsoc->object_add_attribute($noc_param,"MCAST_ENDP_LIST",$n); - $mpsoc->object_add_attribute_order($noc_param,"MCAST_ENDP_LIST"); - # $mpsoc->object_add_attribute($noc_param,"MCAST_PRTLw",$NE); - # $mpsoc->object_add_attribute_order($noc_param,"MCAST_PRTLw"); - $cast=$n; + my $h=0; + my $n=""; + for (my $i=0; $i<$NE; $i++){ + $h+= (1<<$i%4); + if(($i+1) % 4==0){ + $n="$h".$n if($h<10); + $n=chr($h-10+97).$n if($h>9); + $h=0; + } + } + $n="$h".$n if($h!=0); + $n="'h".$n; + $mpsoc->object_add_attribute($noc_param,"MCAST_ENDP_LIST",$n); + $mpsoc->object_add_attribute_order($noc_param,"MCAST_ENDP_LIST"); + # $mpsoc->object_add_attribute($noc_param,"MCAST_PRTLw",$NE); + # $mpsoc->object_add_attribute_order($noc_param,"MCAST_PRTLw"); + $cast=$n; } if($cast_type eq '"MULTICAST_PARTIAL"' || $cast_type eq '"BROADCAST_PARTIAL"') { - #$table->attach ( gen_label_help($info,"Muticast Node list"),0 , 2, $row,$row+1,'fill','shrink',2,2); - $info='MCAST_ENDP_LIST is a one-hot coded number where the asserted bit indicates that the corresponding destination ID can be targeted in multicast/broadcast packets. The corresponding destinations with zero bit can only receive unicast packets.'; - - my $b1= def_image_button("icons/setting.png","Set"); - my $bb= def_pack_hbox(FALSE,0,gen_label_in_left("$cast"),$b1); - my $label=gen_label_in_left("Muticast Node list"); - my $inf_bt= (defined $info)? gen_button_message ($info,"icons/help.png"):gen_label_in_left(" "); - attach_widget_to_table ($table,$row,$label,$inf_bt,$bb,0); - - - # $table->attach ( $bb , 2, 3, $row,$row+1,'fill','shrink',2,2); + #$table->attach ( gen_label_help($info,"Muticast Node list"),0 , 2, $row,$row+1,'fill','shrink',2,2); + $info='A one-hot encoded value where each asserted bit indicates that the corresponding destination ID + can be targeted in multicast or broadcast packets. Destinations represented by bits set to zero are restricted + to receiving only unicast packets.'; + $noc_param_comment{$param}="$info"; + my $b1= def_image_button("icons/setting.png","Set"); + my $bb= def_pack_hbox(FALSE,0,gen_label_in_left("$cast"),$b1); + my $label=gen_label_in_left("Muticast Node list"); + my $inf_bt= (defined $info)? gen_button_message ($info,"icons/help.png"):gen_label_in_left(" "); + attach_widget_to_table ($table,$row,$label,$inf_bt,$bb,0); + + + # $table->attach ( $bb , 2, 3, $row,$row+1,'fill','shrink',2,2); $row++; - $b1->signal_connect("clicked" => sub{ - set_multicast_list($mpsoc,$noc_id); - - }); - } - - - - #advance parameter start - # my $advc; - # my $adv_set=$mpsoc->object_get_attribute('setting','show_adv_setting'); - # - # if($adv_set == 0){ - # $advc= def_image_button("icons/down.png","Advance Parameters"); - # $table->attach ( $advc , 0, 2, $row,$row+1,'fill','shrink',2,2); - # $row++; - # } + $b1->signal_connect("clicked" => sub{ + set_multicast_list($mpsoc,$noc_id); + }); + } my $adv_set= $show_noc; #SSA @@ -861,7 +871,9 @@ sub noc_config{ $default='"NO"'; $content='"YES","NO"'; $type='Combo-box'; - $info="Enable single cycle latency on packets traversing in the same direction using static straight allocator (SSA)"; + $info="Enable single cycle latency on packets traversing in the same direction using + static straight allocator (SSA)"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); #SMART @@ -870,21 +882,23 @@ sub noc_config{ $default='0'; $content="0,1,2,3,4,5,6,7,8,9"; $type='Combo-box'; - $info="If Max Straight Bypass (SMART_MAX) is defined as n>0 then packets are allowed to bypass Maximum of n routers in Straight direction in single cycle."; + $info="Maximum number of routers a packet can bypass in a straight direction + in a single cycle (0 = no bypass)"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); - - - + #Fully and partially adaptive routing setting my $route=$mpsoc->object_get_attribute($noc_param,"ROUTE_NAME"); $label="Congestion index"; $param="CONGESTION_INDEX"; $type="Spin-button"; $content="0,12,1"; - $info="Congestion index determines how congestion information is collected from neighboring routers. Please refer to the usere manual for more information"; + $info="Congestion index determines how congestion information is collected + from neighboring routers. Please refer to the usere manual for more information"; + $noc_param_comment{$param}="$info"; $default=3; if($topology ne '"CUSTOM"' && $route ne '"XY"' && $route ne '"TRANC_XY"' ){ - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); } else { ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param,undef); } @@ -899,20 +913,24 @@ sub noc_config{ for (my $i=1; $i<=$v-1; $i++){$default= "${default}0";} $default= "${default}1"; $info="Select the escap VC for fully adaptive routing."; + $noc_param_comment{$param}="$info"; if( $route eq '"TRANC_DUATO"' or $route eq '"DUATO"' ){ - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set, $noc_param,undef); - } + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set, $noc_param,undef); + } else{ - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0, $noc_param,undef); + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0, $noc_param,undef); } # VC reallocation type $label=($router_type eq '"VC_BASED"')? 'VC reallocation type': 'Queue reallocation type'; $param='VC_REALLOCATION_TYPE'; - $info="VC reallocation type: If set as atomic only empty VCs can be allocated for new packets. Whereas, in non-atomic a non-empty VC which has received the last packet tail flit can accept a new packet"; + $info="VC reallocation policy. + - ATOMIC: Only empty VCs can be reallocated. + - NONATOMIC: Non-empty VCs with completed packets can accept new packets."; $default='"NONATOMIC"'; $content='"ATOMIC","NONATOMIC"'; $type='Combo-box'; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); @@ -920,13 +938,17 @@ sub noc_config{ $label = 'VC/SW combination type'; $param='COMBINATION_TYPE'; $default='"COMB_NONSPEC"'; - $content='"BASELINE","COMB_SPEC1","COMB_SPEC2","COMB_NONSPEC"'; + $content='"COMB_SPEC1","COMB_SPEC2","COMB_NONSPEC"'; $type='Combo-box'; - $info="The joint VC/ switch allocator type. using canonical combination is not recommended"; + $info="Specifies the joint VC/Switch allocator type as either speculative or non-speculative. +Options are: + - SPEC: Speculative allocation. + - NONSPEC: Non-speculative allocation."; + $noc_param_comment{$param}="$info"; if ($router_type eq '"VC_BASED"'){ ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); } else{ - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param,undef); + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param,undef); } # Crossbar mux type @@ -936,6 +958,7 @@ sub noc_config{ $content='"ONE_HOT","BINARY"'; $type='Combo-box'; $info="Crossbar multiplexer type"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); #class @@ -957,19 +980,17 @@ sub noc_config{ } #print "\$default=$default\n"; for (my $i=0; $i<=$class-1; $i++){ - - $label="Class $i Permitted VCs"; - $param="Cn_$i"; - $type="Check-box"; - $content=$v; - $info="Select the permitted VCs which the message class $i can be sent via them."; - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,'class_param',undef); + + $label="Class $i Permitted VCs"; + $param="Cn_$i"; + $type="Check-box"; + $content=$v; + $info="Select the permitted VCs which the message class $i can be sent via them."; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,'class_param',undef); } }#($router_type eq '"VC_BASED"') - - - + #simulation debuge enable $label='Debug enable'; $param='DEBUG_EN'; @@ -977,8 +998,8 @@ sub noc_config{ $default='0'; $content='0,1'; $type='Combo-box'; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param); - #pipeline reg $label="Add pipeline reg after crossbar"; @@ -987,44 +1008,34 @@ sub noc_config{ $content=1; $default="1\'b0"; $info="If is enabled it adds a pipeline register at the output port of the router."; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param); - - - #MAX_SMART_NUM = 4 // - $label="Number of multiple router bypassing "; - $param="MAX_SMART_NUM "; - $type='Spin-button'; - $content='0,1,1'; - $default=0; - $info="maximum number of routers which a packet can by pass during one clock cycle. Define it as zero will disable bypassing."; - #($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,$adv_set,$noc_param); - - + #FIRST_ARBITER_EXT_P_EN $label='Swich allocator first level arbiters external priority enable'; $param='FIRST_ARBITER_EXT_P_EN'; $default= 1; - $info='If set as 1 then the switch allocator\'s input (first) arbiters\' priority registers are enabled only when a request get both input and output arbiters\' grants'; + $info='Enables switch allocator\'s input priority registers + only when a request gets grants from both input and output arbiters.'; $content='0,1'; $type="Combo-box"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info,$table,$row,undef,$adv_set,$noc_param); - #Arbiter type $label='SW allocator arbitration type'; $param='SWA_ARBITER_TYPE'; $default='"RRA"'; - $content='"RRA","WRRA"'; #,"WRRA_CLASSIC"'; + $content='"RRA","WRRA"'; $type='Combo-box'; - $info="Switch allocator arbiter type: - RRA: Round robin arbiter. Only local fairness in a router. - WRRA: Weighted round robin arbiter. Results in global fairness in the NoC. - Switch allocation requests are grated according to their weight which increases due to contention"; + $info="Switch allocator arbitration type. + - RRA: Round Robin Arbiter (local fairness only). + - WRRA: Weighted Round Robin Arbiter (global fairness based on contention). +"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,1); - - my $arbiter=$mpsoc->object_get_attribute($noc_param,"SWA_ARBITER_TYPE"); my $wrra_show = ($arbiter ne '"RRA"' && $adv_set == 1 )? 1 : 0; # weight width @@ -1033,6 +1044,7 @@ sub noc_config{ $default='4'; $content='2,7,1'; $info= 'Maximum weight width'; + $noc_param_comment{$param}="$info"; $type= 'Spin-button'; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$wrra_show,$noc_param,undef); @@ -1043,11 +1055,11 @@ sub noc_config{ $default='"NO"'; $content='"NO","YES"'; $type='Combo-box'; - $info="If the self loop is enabled, it allows a router input port sends packet to its own output port. Enabling it allows a tile to be able to sent packet to itself too."; + $info="Allows a router input port to send packets to its own output port, + enabling self-communication for tiles."; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,1); - - #WRRA_CONFIG_INDEX $label='Weight configuration index'; $param='WRRA_CONFIG_INDEX'; @@ -1087,7 +1099,6 @@ sub noc_config{ #other fixed parameters - # AVC_ATOMIC_EN $label='AVC_ATOMIC_EN'; @@ -1096,6 +1107,7 @@ sub noc_config{ $info='AVC_ATOMIC_EN'; $content='0,1'; $type="Combo-box"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param); @@ -1107,6 +1119,7 @@ sub noc_config{ #$content='"XY"'; #$type="Combo-box"; #($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param); + $mpsoc->object_add_attribute('noc_param_comments',undef,\%noc_param_comment); return $row; } @@ -1115,160 +1128,160 @@ sub noc_config{ sub set_multicast_list{ - my($mpsoc,$noc_id)=@_; + my($mpsoc,$noc_id)=@_; my $noc_param="noc_param$noc_id"; - my $window = def_popwin_size(50,40,"Select nodes invlove in multicasting ",'percent'); - my $table= def_table(10,10,FALSE); - my $row=0; - my $col=0; - - my $init = $mpsoc->object_get_attribute($noc_param,"MCAST_ENDP_LIST"); - $init =~ s/'h//g; - my @arr= reverse split (//, $init); - - - my $label = "Multicast Node list (hex fromat)"; - my ($Ebox,$entry) = def_h_labeled_entry ($label); - $entry->set_sensitive (FALSE); - - my @sel_options= ("Select","All","None","2n","3n","4n","2n+1","3n+1","3n+2","4n+1","4n+2","4n+3"); - my $combo= gen_combo(\@sel_options, 0); - $table->attach ($combo , 0, 1, $row,$row+1,'fill','shrink',2,2); - #get the number of endpoints - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); - my @check; - - - - my $sel_val="Init"; - for (my $i=0; $i<$NE; $i++){ - if($i%10 == 0){ $row++;$col=0;} - my $box; - my $l=$NE -$i-1; - - my $char = $arr[$l/4]; - $char=0 if (!defined $char); - my $hex = hex($char); - my $bit = ($hex >> ($l%4)) & 1; - ($box,$check[$l])=def_h_labeled_checkbutton("$l"); - $table->attach ($box , $col, $col+1, $row,$row+1,'fill','shrink',2,2); - $col++; - - if($bit==1){ - $check[$l]->set_active(TRUE); - } - - $check[$l]-> signal_connect("toggled" => sub{ - get_multicast_val ($mpsoc,$entry,$NE,@check)if($sel_val eq "Select"); - }); - } - $row++; - $col=0; - - $sel_val="Select"; - get_multicast_val ($mpsoc,$entry,$NE,@check); - - $combo-> signal_connect("changed" => sub{ - $sel_val=$combo->get_active_text(); - my $n=1; - my $r=0; - return if ($sel_val eq "Select"); - if ($sel_val eq "None"){ - for (my $i=0; $i<$NE; $i++){$check[$i]->set_active(FALSE)}; - get_multicast_val ($mpsoc,$entry,$NE,@check); - $combo->set_active(0); - return; - } - ($n,$r)=sscanf("%dn+%d",$sel_val); - if(!defined $r){ - ($n,$r)=sscanf("%dn",$sel_val); - $r=0; - $n=1 if(!defined $n); - } - - for (my $i=0; $i<$NE; $i++){ - if($i % $n == $r){ $check[$i]->set_active(TRUE);} - } - $combo->set_active(0); - get_multicast_val ($mpsoc,$entry,$NE,@check); - - }); - - - - $table->attach ($Ebox , 0, 10, $row,$row+1,'fill','shrink',2,2);$row++; - - my $main_table=def_table(10,10,FALSE); - - my $ok = def_image_button('icons/select.png','OK'); - $main_table->attach_defaults ($table , 0, 12, 0,11); + my $window = def_popwin_size(50,40,"Select nodes invlove in multicasting ",'percent'); + my $table= def_table(10,10,FALSE); + my $row=0; + my $col=0; + + my $init = $mpsoc->object_get_attribute($noc_param,"MCAST_ENDP_LIST"); + $init =~ s/'h//g; + my @arr= reverse split (//, $init); + + + my $label = "Multicast Node list (hex fromat)"; + my ($Ebox,$entry) = def_h_labeled_entry ($label); + $entry->set_sensitive (FALSE); + + my @sel_options= ("Select","All","None","2n","3n","4n","2n+1","3n+1","3n+2","4n+1","4n+2","4n+3"); + my $combo= gen_combo(\@sel_options, 0); + $table->attach ($combo , 0, 1, $row,$row+1,'fill','shrink',2,2); + #get the number of endpoints + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); + my @check; + + + + my $sel_val="Init"; + for (my $i=0; $i<$NE; $i++){ + if($i%10 == 0){ $row++;$col=0;} + my $box; + my $l=$NE -$i-1; + + my $char = $arr[$l/4]; + $char=0 if (!defined $char); + my $hex = hex($char); + my $bit = ($hex >> ($l%4)) & 1; + ($box,$check[$l])=def_h_labeled_checkbutton("$l"); + $table->attach ($box , $col, $col+1, $row,$row+1,'fill','shrink',2,2); + $col++; + + if($bit==1){ + $check[$l]->set_active(TRUE); + } + + $check[$l]-> signal_connect("toggled" => sub{ + get_multicast_val ($mpsoc,$entry,$NE,@check)if($sel_val eq "Select"); + }); + } + $row++; + $col=0; + + $sel_val="Select"; + get_multicast_val ($mpsoc,$entry,$NE,@check); + + $combo-> signal_connect("changed" => sub{ + $sel_val=$combo->get_active_text(); + my $n=1; + my $r=0; + return if ($sel_val eq "Select"); + if ($sel_val eq "None"){ + for (my $i=0; $i<$NE; $i++){$check[$i]->set_active(FALSE)}; + get_multicast_val ($mpsoc,$entry,$NE,@check); + $combo->set_active(0); + return; + } + ($n,$r)=sscanf("%dn+%d",$sel_val); + if(!defined $r){ + ($n,$r)=sscanf("%dn",$sel_val); + $r=0; + $n=1 if(!defined $n); + } + + for (my $i=0; $i<$NE; $i++){ + if($i % $n == $r){ $check[$i]->set_active(TRUE);} + } + $combo->set_active(0); + get_multicast_val ($mpsoc,$entry,$NE,@check); + + }); + + + + $table->attach ($Ebox , 0, 10, $row,$row+1,'fill','shrink',2,2);$row++; + + my $main_table=def_table(10,10,FALSE); + + my $ok = def_image_button('icons/select.png','OK'); + $main_table->attach_defaults ($table , 0, 12, 0,11); $main_table->attach ($ok,5, 6, 11,12,'shrink','shrink',0,0); - - $ok->signal_connect('clicked', sub { - my $s=get_multicast_val ($mpsoc,$entry,$NE,@check); - my $n=$entry->get_text( ); - $mpsoc->object_add_attribute($noc_param,"MCAST_ENDP_LIST",$n); - # $mpsoc->object_add_attribute($noc_param,"MCAST_PRTLw",$s); - set_gui_status($mpsoc,"ref",1); - $window->destroy; - }); - - - - - my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_multicast'); - add_widget_to_scrolled_win($main_table,$scrolled_win); - $window->add($scrolled_win); - $window->show_all(); + + $ok->signal_connect('clicked', sub { + my $s=get_multicast_val ($mpsoc,$entry,$NE,@check); + my $n=$entry->get_text( ); + $mpsoc->object_add_attribute($noc_param,"MCAST_ENDP_LIST",$n); + # $mpsoc->object_add_attribute($noc_param,"MCAST_PRTLw",$s); + set_gui_status($mpsoc,"ref",1); + $window->destroy; + }); + + + + + my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_multicast'); + add_widget_to_scrolled_win($main_table,$scrolled_win); + $window->add($scrolled_win); + $window->show_all(); } sub get_multicast_val { - my ($mpsoc,$entry,$NE,@check)=@_; - my $n=""; - my $h=0; - my $s=0; - for (my $i=0; $i<$NE; $i++){ - if($check[$i]->get_active()){$h+= (1<<$i%4);$s++;} - if(($i+1) % 4==0){ - $n="$h".$n if($h<10); - $n=chr($h-10+97).$n if($h>9); - $h=0; - } - } - - $n="$h".$n if($NE%4!=0); - $n="'h".$n; - $entry->set_text("$n"); - return $s; - + my ($mpsoc,$entry,$NE,@check)=@_; + my $n=""; + my $h=0; + my $s=0; + for (my $i=0; $i<$NE; $i++){ + if($check[$i]->get_active()){$h+= (1<<$i%4);$s++;} + if(($i+1) % 4==0){ + $n="$h".$n if($h<10); + $n=chr($h-10+97).$n if($h>9); + $h=0; + } + } + + $n="$h".$n if($NE%4!=0); + $n="'h".$n; + $entry->set_text("$n"); + return $s; + } ############# # config_custom_topology_gui ############ sub config_custom_topology_gui{ - my($mpsoc,$table,$txview,$row,$noc_id)=@_; + my($mpsoc,$table,$txview,$row,$noc_id)=@_; my $noc_param="noc_param$noc_id"; my $coltmp=0; #read param.obj file to load cutom topology info - my $dir =get_project_dir()."/mpsoc/rtl/src_topology"; - my $file="$dir/param.obj"; - unless (-f $file){ - add_colored_info($txview,"No Custom topology find in $dir. You can define a Custom Topology using ProNoC Topology maker.\n",'red'); - return; - } - - my %param; + my $dir =get_project_dir()."/mpsoc/rtl/src_topology"; + my $file="$dir/param.obj"; + unless (-f $file){ + add_colored_info($txview,"No Custom topology find in $dir. You can define a Custom Topology using ProNoC Topology maker.\n",'red'); + return; + } + + my %param; my ($pp,$r,$err) = regen_object($file ); if ($r){ add_colored_info($txview,"Error: cannot open $file file: $err\n",'red'); return; - } - - %param=%{$pp}; - my @topologies=sort keys %param; - - my $label='Topology_name'; + } + + %param=%{$pp}; + my @topologies=sort keys %param; + + my $label='Topology_name'; my $param='CUSTOM_TOPOLOGY_NAME'; my $default=$topologies[0]; my $content= join(",", @topologies); @@ -1276,25 +1289,25 @@ sub config_custom_topology_gui{ my $info="Custom topology name"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,1,$noc_param,1); - my $topology_name=$mpsoc->object_get_attribute($noc_param,'CUSTOM_TOPOLOGY_NAME'); - - - $label='Routing Algorithm'; + my $topology_name=$mpsoc->object_get_attribute($noc_param,'CUSTOM_TOPOLOGY_NAME'); + + + $label='Routing Algorithm'; $param="ROUTE_NAME"; $type="Combo-box"; - $content=$param{$topology_name}{'ROUTE_NAME'}; + $content=$param{$topology_name}{'ROUTE_NAME'}; my @rr=split(/\s*,\s*/,$content); $default=$rr[0]; $info="Select the routing algorithm"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,1,$noc_param,1); - $mpsoc->object_add_attribute($noc_param,'T1',$param{$topology_name}{'T1'}); - $mpsoc->object_add_attribute($noc_param,'T2',$param{$topology_name}{'T2'}); - $mpsoc->object_add_attribute($noc_param,'T3',$param{$topology_name}{'T3'}); - $mpsoc->object_add_attribute('noc_connection','er_addr',$param{$topology_name}{'er_addr'}); - - - return ($row,$coltmp); + $mpsoc->object_add_attribute($noc_param,'T1',$param{$topology_name}{'T1'}); + $mpsoc->object_add_attribute($noc_param,'T2',$param{$topology_name}{'T2'}); + $mpsoc->object_add_attribute($noc_param,'T3',$param{$topology_name}{'T3'}); + $mpsoc->object_add_attribute('noc_connection','er_addr',$param{$topology_name}{'er_addr'}); + + + return ($row,$coltmp); } @@ -1343,8 +1356,8 @@ sub get_config{ }); my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'get_config_adj'); - add_widget_to_scrolled_win($table,$scrolled_win); - return $scrolled_win; + add_widget_to_scrolled_win($table,$scrolled_win); + return $scrolled_win; } @@ -1354,7 +1367,7 @@ sub get_config{ sub gen_all_tiles{ my ($mpsoc,$info, $hw_dir,$sw_dir)=@_; - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; my @generated_tiles; @@ -1367,7 +1380,7 @@ sub gen_all_tiles{ my $path=$mpsoc->object_get_attribute('setting','soc_path'); $path=~ s/ /\\ /g; my $p = "$path/$soc_name.SOC"; - my ($soc,$r,$err) = regen_object($p); + my ($soc,$r,$err) = regen_object($p); if ($r){ show_info($info,"**Error reading $p file: $err\n"); next; @@ -1383,9 +1396,9 @@ sub gen_all_tiles{ $soc->soc_add_instance_param($nis[0] ,$nocparam ); my %z; foreach my $p (sort keys %{$nocparam}){ - $z{$p}="Parameter"; - } - $soc->soc_add_instance_param_type($nis[0] ,\%z); + $z{$p}="Parameter"; + } + $soc->soc_add_instance_param_type($nis[0] ,\%z); #foreach my $p ( sort keys %nocparam ) { # print "$p = $nocparam{$p} \n"; @@ -1444,10 +1457,10 @@ sub generate_soc_files{ #copy hdl codes in src_verilog my ($hdl_ref,$warnings)= get_all_files_list($soc,"hdl_files"); my ($sim_ref,$warnings2)= get_all_files_list($soc,"hdl_files_ticked"); - #hdl_ref-sim_ref - my @n= get_diff_array($hdl_ref,$sim_ref); - $hdl_ref=\@n; - + #hdl_ref-sim_ref + my @n= get_diff_array($hdl_ref,$sim_ref); + $hdl_ref=\@n; + foreach my $f(@{$hdl_ref}){ my $n="$project_dir$f"; if (-f "$n") { @@ -1460,7 +1473,7 @@ sub generate_soc_files{ - foreach my $f(@{$sim_ref}){ + foreach my $f(@{$sim_ref}){ my $n="$project_dir$f"; if (-f "$n") { copy ("$n","$target_dir/src_sim"); @@ -1488,16 +1501,16 @@ sub generate_soc_files{ - move ("$dir/lib/verilog/$soc_name.sv","$target_dir/src_verilog/tiles/"); - copy_noc_files($project_dir,"$target_dir/src_verilog/lib"); + move ("$dir/lib/verilog/$soc_name.sv","$target_dir/src_verilog/tiles/"); + copy_noc_files($project_dir,"$target_dir/src_verilog/lib"); - # Write header file - generate_header_file($soc,$project_dir,$target_dir,$target_dir,$dir); - #use File::Copy::Recursive qw(dircopy); - #dircopy("$dir/../src_processor/aeMB/compiler","$target_dir/sw/") or die("$!\n"); - my $msg="SoC \"$soc_name\" has been created successfully at $target_dir/ "; - return $msg; + # Write header file + generate_header_file($soc,$project_dir,$target_dir,$target_dir,$dir); + #use File::Copy::Recursive qw(dircopy); + #dircopy("$dir/../src_processor/aeMB/compiler","$target_dir/sw/") or die("$!\n"); + my $msg="SoC \"$soc_name\" has been created successfully at $target_dir/ "; + return $msg; } @@ -1516,7 +1529,7 @@ sub generate_mpsoc_lib_file { } sub check_mpsoc_name { - my ($name,$info,$label)= @_; + my ($name,$info,$label)= @_; $label="MPSoC" if (!defined $label); my $error = check_verilog_identifier_syntax($name); if ( defined $error ){ @@ -1530,7 +1543,7 @@ sub check_mpsoc_name { message_dialog("Please define the $label filed!"); return 1; } - return 0; + return 0; } @@ -1550,7 +1563,7 @@ sub generate_mpsoc{ my $sw_dir = "$target_dir/sw"; # rmtree ($hw_dir); - mkpath("$hw_dir",1,01777); + mkpath("$hw_dir",1,01777); mkpath("$hw_dir/lib/",1,0755); mkpath("$hw_dir/tiles",1,0755); mkpath("$sw_dir",1,0755); @@ -1566,23 +1579,23 @@ sub generate_mpsoc{ gen_all_tiles($mpsoc,$info, $hw_dir,$sw_dir ); #copy clk setting hdl codes in src_verilog - my $project_dir = abs_path("$dir/../../"); + my $project_dir = abs_path("$dir/../../"); my $sc_soc =get_source_set_top($mpsoc,'mpsoc'); - my ($file_ref,$warnings)= get_all_files_list($sc_soc,"hdl_files"); - my ($sim_ref,$warnings2)= get_all_files_list($sc_soc,"hdl_files_ticked"); - #file_ref-sim_ref - my @n= get_diff_array($file_ref,$sim_ref); - $file_ref=\@n; - - copy_file_and_folders($file_ref,$project_dir,"$hw_dir/lib"); - show_colored_info($info,$warnings,'green') if(defined $warnings); - add_to_project_file_list($file_ref,"$hw_dir/lib/",$hw_dir); - - copy_file_and_folders($sim_ref,$project_dir,"$hw_dir/../src_sim"); - show_colored_info($info,$warnings2,'green') if(defined $warnings2); - add_to_project_file_list($sim_ref,"$hw_dir/../src_sim",$hw_dir); - - + my ($file_ref,$warnings)= get_all_files_list($sc_soc,"hdl_files"); + my ($sim_ref,$warnings2)= get_all_files_list($sc_soc,"hdl_files_ticked"); + #file_ref-sim_ref + my @n= get_diff_array($file_ref,$sim_ref); + $file_ref=\@n; + + copy_file_and_folders($file_ref,$project_dir,"$hw_dir/lib"); + show_colored_info($info,$warnings,'green') if(defined $warnings); + add_to_project_file_list($file_ref,"$hw_dir/lib/",$hw_dir); + + copy_file_and_folders($sim_ref,$project_dir,"$hw_dir/../src_sim"); + show_colored_info($info,$warnings2,'green') if(defined $warnings2); + add_to_project_file_list($sim_ref,"$hw_dir/../src_sim",$hw_dir); + + #generate header file containig the tiles physical addresses gen_tiles_physical_addrsses_header_file($mpsoc,"$sw_dir/phy_addr.h"); @@ -1595,22 +1608,22 @@ sub generate_mpsoc{ #if Topology is custom copy custom topology files my $topology=$mpsoc->object_get_attribute('noc_param','TOPOLOGY'); - if ($topology eq '"CUSTOM"'){ - my $Tname=$mpsoc->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); - $Tname=~s/["]//gs; - my $dir1= get_project_dir()."/mpsoc/rtl/src_topology/$Tname"; - my $dir2= get_project_dir()."/mpsoc/rtl/src_topology/common"; - my @files = File::Find::Rule->file() + if ($topology eq '"CUSTOM"'){ + my $Tname=$mpsoc->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); + $Tname=~s/["]//gs; + my $dir1= get_project_dir()."/mpsoc/rtl/src_topology/$Tname"; + my $dir2= get_project_dir()."/mpsoc/rtl/src_topology/common"; + my @files = File::Find::Rule->file() ->name( '*.v','*.V') ->in( "$dir1" ); - copy_file_and_folders (\@files,$project_dir,"$hw_dir/lib/"); - - @files = File::Find::Rule->file() + copy_file_and_folders (\@files,$project_dir,"$hw_dir/lib/"); + + @files = File::Find::Rule->file() ->name( '*.v','*.V') ->in( "$dir2" ); - copy_file_and_folders (\@files,$project_dir,"$hw_dir/lib/"); - } + copy_file_and_folders (\@files,$project_dir,"$hw_dir/lib/"); + } # Write object file @@ -1655,17 +1668,17 @@ sub generate_mpsoc{ add_to_project_file_list(\@ff,"$hw_dir/lib/",$hw_dir); #write perl_object_file - mkpath("$target_dir/perl_lib/",1,01777); - open(FILE, ">$target_dir/perl_lib/$name.MPSOC") || die "Can not open: $!"; - print FILE perl_file_header("$name.MPSOC"); - print FILE Data::Dumper->Dump([\%$mpsoc],['mpsoc']); + mkpath("$target_dir/perl_lib/",1,01777); + open(FILE, ">$target_dir/perl_lib/$name.MPSOC") || die "Can not open: $!"; + print FILE perl_file_header("$name.MPSOC"); + print FILE Data::Dumper->Dump([\%$mpsoc],['mpsoc']); #regenerate linker var file create_linker_var_file($mpsoc); - + message_dialog("MPSoC \"$name\" has been created successfully at $target_dir/ " ) if($show_sucess_msg); - return 1; + return 1; } sub mpsoc_sw_make { @@ -1677,7 +1690,7 @@ sub mpsoc_sw_make { .PHONY: \$(TOPTARGETS) \$(SUBDIRS) "; - return $make; + return $make; } @@ -1722,7 +1735,7 @@ sub mpsoc_mem_prog { # D:2:0 load jtag_enable data register with 0x0 reset=0 disable=0 # I:0 set jtag_enable in bypass mode "; - return $string; + return $string; } @@ -1779,8 +1792,8 @@ sub get_tile{ } sub define_empty_param_setting { - my ($mpsoc,$window)=@_; - my $ok = def_image_button('icons/select.png','OK'); + my ($mpsoc,$window)=@_; + my $ok = def_image_button('icons/select.png','OK'); my $okbox=def_hbox(TRUE,0); $okbox->pack_start($ok, FALSE, FALSE,0); $ok-> signal_connect("clicked" => sub{ @@ -1789,15 +1802,15 @@ sub define_empty_param_setting { }); my $param_table = def_table(1, 1, TRUE); - $param_table->attach_defaults($okbox,0,1,3,4); - return $param_table; - - + $param_table->attach_defaults($okbox,0,1,3,4); + return $param_table; + + } sub get_tile_setting { - my($mpsoc,$tile)=@_; - my $window = def_popwin_size(50,40,"Parameter setting for Tile $tile ",'percent'); + my($mpsoc,$tile)=@_; + my $window = def_popwin_size(50,40,"Parameter setting for Tile $tile ",'percent'); my $table = def_table(6, 2, FALSE); my $scrolled_win = add_widget_to_scrolled_win($table); @@ -1811,15 +1824,15 @@ sub get_tile_setting { my $label=gen_label_in_left(" Processing tile name:"); $table->attach($label,0,2,$row,$row+1,'shrink','shrink',2,2); $table->attach($combo,2,3,$row,$row+1,'shrink','shrink',2,2);$row++; - add_Hsep_to_table($table,0,3,$row);$row++; - $soc_name = ' ' if (!defined $soc_name); + add_Hsep_to_table($table,0,3,$row);$row++; + $soc_name = ' ' if (!defined $soc_name); my $param_table = ($soc_name eq ' ')? define_empty_param_setting($mpsoc,$window) : - get_soc_parameter_setting_table($mpsoc,$soc_name,$window,[$tile]); + get_soc_parameter_setting_table($mpsoc,$soc_name,$window,[$tile]); - $table->attach_defaults($param_table,0,3,2,3); - - - $combo->signal_connect('changed'=>sub{ + $table->attach_defaults($param_table,0,3,2,3); + + + $combo->signal_connect('changed'=>sub{ my $new_soc=$combo->get_active_text(); if ($new_soc eq ' '){ #unconnect tile @@ -1846,511 +1859,511 @@ sub get_tile_setting { ######### sub gen_tiles{ my ($mpsoc)=@_; - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); my $table; my $dim_y = floor(sqrt($NE)); - $table=def_table($NE%8,$NE/8,FALSE);# my ($row,$col,$homogeneous)=@_; - for (my $i=0; $i<$NE;$i++){ - my $tile=get_tile($mpsoc,$i); - my $y= int($i/$dim_y); - my $x= $i % $dim_y; + $table=def_table($NE%8,$NE/8,FALSE);# my ($row,$col,$homogeneous)=@_; + for (my $i=0; $i<$NE;$i++){ + my $tile=get_tile($mpsoc,$i); + my $y= int($i/$dim_y); + my $x= $i % $dim_y; $table->attach_defaults ($tile, $x, $x+1 , $y, $y+1); - } - - my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_tiles_adj'); - add_widget_to_scrolled_win($table,$scrolled_win); - return $scrolled_win; + } + + my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_tiles_adj'); + add_widget_to_scrolled_win($table,$scrolled_win); + return $scrolled_win; } sub get_elf_file_addr_range { - my ($file,$tview)=@_; - #my $command= "size -A $file"; - my $command= "nm $file"; - #add_info($tview,"$command\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); - if(length $stderr>1){ - add_colored_info($tview,"$stderr\n",'red'); - add_colored_info($tview,"$command was not run successfully!\n",'red'); - return ("Err","Err"); - } - if($exit){ - add_colored_info($tview,"$stdout\n",'red'); - add_colored_info($tview,"$command was not run successfully!\n",'red'); - return ("Err","Err"); - } - - my @lines = split ("\n" ,$stdout); - my $max_addr=0; - my $sec_name; - - foreach my $p (@lines ){ - $p =~ s/\s+/ /g; # remove extra spaces - $p =~ s/^\s+//; #ltrim - my ($addr,$type,$name)= sscanf("%x %s %s","$p"); - if(defined $addr && defined $name){ - if($max_addr < $addr) { - $max_addr = $addr; - $sec_name = $name; - } - } - } - return ($max_addr,$sec_name); + my ($file,$tview)=@_; + #my $command= "size -A $file"; + my $command= "nm $file"; + #add_info($tview,"$command\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); + if(length $stderr>1){ + add_colored_info($tview,"$stderr\n",'red'); + add_colored_info($tview,"$command was not run successfully!\n",'red'); + return ("Err","Err"); + } + if($exit){ + add_colored_info($tview,"$stdout\n",'red'); + add_colored_info($tview,"$command was not run successfully!\n",'red'); + return ("Err","Err"); + } + + my @lines = split ("\n" ,$stdout); + my $max_addr=0; + my $sec_name; + + foreach my $p (@lines ){ + $p =~ s/\s+/ /g; # remove extra spaces + $p =~ s/^\s+//; #ltrim + my ($addr,$type,$name)= sscanf("%x %s %s","$p"); + if(defined $addr && defined $name){ + if($max_addr < $addr) { + $max_addr = $addr; + $sec_name = $name; + } + } + } + return ($max_addr,$sec_name); } sub show_reqired_brams{ - my ($self,$tview)=@_; - my $win=def_popwin_size (50,50,"BRAM info", 'percent'); - my $sc_win = gen_scr_win_with_adjst($self,'liststore'); - my $table= def_table(10,10,FALSE); - add_widget_to_scrolled_win($table,$sc_win); - my $row=0; - my $col=0; - - my @clmns =('Tile#', 'Section located in Upper Bound Address (UBA) ','UBA in Bytes','UBA in Words','Minimum Memory Address Width'); - my $target_dir; - my @data; + my ($self,$tview)=@_; + my $win=def_popwin_size (50,50,"BRAM info", 'percent'); + my $sc_win = gen_scr_win_with_adjst($self,'liststore'); + my $table= def_table(10,10,FALSE); + add_widget_to_scrolled_win($table,$sc_win); + my $row=0; + my $col=0; + + my @clmns =('Tile#', 'Section located in Upper Bound Address (UBA) ','UBA in Bytes','UBA in Words','Minimum Memory Address Width'); + my $target_dir; + my @data; my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); - if(defined $mpsoc_name){#it is an soc + if(defined $mpsoc_name){#it is an soc - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my $ram_file = "$target_dir/sw/tile$tile_num/image"; - my ($size,$sec) = get_elf_file_addr_range($ram_file,$tview); - my %clmn; - $clmn{0}="tile$tile_num"; - $clmn{1}= "$sec"; - $clmn{2}="$size"; - my $w=$size/4; - $clmn{3}="$w"; - $clmn{4}=ceil(log($w)/log(2)); - push(@data,\%clmn); - - }#$tile_num - } - else - { - my $soc_name=$self->object_get_attribute('soc_name'); - $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$soc_name"; - my $ram_file = "$target_dir/sw/image"; - my ($size,$sec) = get_elf_file_addr_range($ram_file,$tview); - my %clmn; - $clmn{0}="$soc_name"; - $clmn{1}= "$sec"; - $clmn{2}="$size"; - my $w=$size/4; - $clmn{3}="$w"; - $clmn{4}=ceil(log($w)/log(2)); - push(@data,\%clmn); - } - - my @clmn_type = (#'Glib::Boolean', # => G_TYPE_BOOLEAN + $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + my $ram_file = "$target_dir/sw/tile$tile_num/image"; + my ($size,$sec) = get_elf_file_addr_range($ram_file,$tview); + my %clmn; + $clmn{0}="tile$tile_num"; + $clmn{1}= "$sec"; + $clmn{2}="$size"; + my $w=$size/4; + $clmn{3}="$w"; + $clmn{4}=ceil(log($w)/log(2)); + push(@data,\%clmn); + + }#$tile_num + } + else + { + my $soc_name=$self->object_get_attribute('soc_name'); + $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$soc_name"; + my $ram_file = "$target_dir/sw/image"; + my ($size,$sec) = get_elf_file_addr_range($ram_file,$tview); + my %clmn; + $clmn{0}="$soc_name"; + $clmn{1}= "$sec"; + $clmn{2}="$size"; + my $w=$size/4; + $clmn{3}="$w"; + $clmn{4}=ceil(log($w)/log(2)); + push(@data,\%clmn); + } + + my @clmn_type = (#'Glib::Boolean', # => G_TYPE_BOOLEAN #'Glib::Uint', # => G_TYPE_UINT 'Glib::String', # => G_TYPE_STRING 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String'); # you get the idea - - my $list= gen_list_store (\@data,\@clmn_type,\@clmns); - $table-> attach ($list, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $row++; - - $win->add($sc_win); - $win->show_all(); + + my $list= gen_list_store (\@data,\@clmn_type,\@clmns); + $table-> attach ($list, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $row++; + + $win->add($sc_win); + $win->show_all(); } sub check_conflict { - my ($self,$tile_num,$label)=@_; - - my $r1 =$self->object_get_attribute("ROM$tile_num",'end'); - my $r2 =$self->object_get_attribute("RAM$tile_num",'start'); - - if(defined $r1 && defined $r2){ - if(hex($r1)> hex($r2)){ - $label->set_markup("RAM-ROM range Conflict"); - - }else { - $label->set_label(" "); - - } - }else { - $label->set_label(" "); - - } + my ($self,$tile_num,$label)=@_; + + my $r1 =$self->object_get_attribute("ROM$tile_num",'end'); + my $r2 =$self->object_get_attribute("RAM$tile_num",'start'); + + if(defined $r1 && defined $r2){ + if(hex($r1)> hex($r2)){ + $label->set_markup("RAM-ROM range Conflict"); + + }else { + $label->set_label(" "); + + } + }else { + $label->set_label(" "); + + } } sub update_ram_rom_size { - my ($self,$tile_num,$name,$label,$start,$end,$conflict)=@_; - my $s = $start->get_value(); - my $e = $end->get_value(); - - $self->object_add_attribute($name.$tile_num,'start',$start->get_value()); - $self->object_add_attribute($name.$tile_num,'end',$end->get_value()); - if($e <= $s){ - #$label->set_label("Invalid range" ); - $label->set_markup("Invalid range"); - - }else { - $label->set_label( metric_conversion($e - $s) . "B"); - - } - - check_conflict($self,$tile_num,$conflict); - - - + my ($self,$tile_num,$name,$label,$start,$end,$conflict)=@_; + my $s = $start->get_value(); + my $e = $end->get_value(); + + $self->object_add_attribute($name.$tile_num,'start',$start->get_value()); + $self->object_add_attribute($name.$tile_num,'end',$end->get_value()); + if($e <= $s){ + #$label->set_label("Invalid range" ); + $label->set_markup("Invalid range"); + + }else { + $label->set_label( metric_conversion($e - $s) . "B"); + + } + + check_conflict($self,$tile_num,$conflict); + + + } sub get_tile_peripheral_patameter { - my ($mpsoc,$tile_num,$peripheral,$param_name)=@_; - my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); - if(defined $soc_name) { - my $top=$mpsoc->mpsoc_get_soc($soc_name); - my @insts=$top->top_get_all_instances(); - foreach my $id (@insts){ - if ($id =~/$peripheral[0-9]/){ - my $name=$top->top_get_def_of_instance($id,'instance'); - - my %params; - my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); - #if ($setting eq 'Custom'){ - %params= $top->top_get_custom_soc_param($tile_num); - #}else{ - # %params=$top->top_get_default_soc_param(); - #} - return $params{"${name}_$param_name"}; - } - } - } - return undef; - + my ($mpsoc,$tile_num,$peripheral,$param_name)=@_; + my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); + if(defined $soc_name) { + my $top=$mpsoc->mpsoc_get_soc($soc_name); + my @insts=$top->top_get_all_instances(); + foreach my $id (@insts){ + if ($id =~/$peripheral[0-9]/){ + my $name=$top->top_get_def_of_instance($id,'instance'); + + my %params; + my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); + #if ($setting eq 'Custom'){ + %params= $top->top_get_custom_soc_param($tile_num); + #}else{ + # %params=$top->top_get_default_soc_param(); + #} + return $params{"${name}_$param_name"}; + } + } + } + return undef; + } sub get_soc_peripheral_parameter { - my ($soc,$peripheral,$param_nam)=@_; - my @instances=$soc->soc_get_all_instances(); - foreach my $id (@instances){ - if ($id =~/$peripheral[0-9]/){ - return $soc->soc_get_module_param_value ($id,$param_nam) if (defined $param_nam); - } - } - return undef; + my ($soc,$peripheral,$param_nam)=@_; + my @instances=$soc->soc_get_all_instances(); + foreach my $id (@instances){ + if ($id =~/$peripheral[0-9]/){ + return $soc->soc_get_module_param_value ($id,$param_nam) if (defined $param_nam); + } + } + return undef; } sub linker_initial_setting { - my ($self,$tview)=@_; - my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); + my ($self,$tview)=@_; + my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); my $tnum; my $target_dir; - if(defined $mpsoc_name){#it is an mpsoc - - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - - $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - - my $v=get_tile_peripheral_patameter($self,$tile_num,"_ram","Aw"); - $v = 13 if (!defined $v); - $self->object_add_attribute('MEM'.$tile_num,'width',$v); - $self->object_add_attribute('MEM'.$tile_num,'percent',75); - - my $s =(1 << ($v+2)) ; - my $p = 75; - - my $rom_start = 0; - my $rom_end= int ( ($s*$p)/100); - my $ram_start= int (($s*$p)/100); - my $ram_end= $s; - - $self->object_add_attribute('ROM'.$tile_num,'start',$rom_start); - $self->object_add_attribute('ROM'.$tile_num,'end',$rom_end); - $self->object_add_attribute('RAM'.$tile_num,'start',$ram_start); - $self->object_add_attribute('RAM'.$tile_num,'end',$ram_end); - - - } - - - } - else - { - my $v=get_soc_peripheral_parameter ($self,"_ram","Aw"); - $v = 13 if (!defined $v); - $self->object_add_attribute('MEM0','width',$v); - $self->object_add_attribute('MEM0','percent',75); - my $s =(1 << ($v+2)) ; - my $p = 75; - - my $rom_start = 0; - my $rom_end= int ( ($s*$p)/100); - my $ram_start= int (($s*$p)/100); - my $ram_end= $s; - - $self->object_add_attribute('ROM0','start',$rom_start); - $self->object_add_attribute('ROM0','end',$rom_end); - $self->object_add_attribute('RAM0','start',$ram_start); - $self->object_add_attribute('RAM0','end',$ram_end); - } - - + if(defined $mpsoc_name){#it is an mpsoc + + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + + $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + + my $v=get_tile_peripheral_patameter($self,$tile_num,"_ram","Aw"); + $v = 13 if (!defined $v); + $self->object_add_attribute('MEM'.$tile_num,'width',$v); + $self->object_add_attribute('MEM'.$tile_num,'percent',75); + + my $s =(1 << ($v+2)) ; + my $p = 75; + + my $rom_start = 0; + my $rom_end= int ( ($s*$p)/100); + my $ram_start= int (($s*$p)/100); + my $ram_end= $s; + + $self->object_add_attribute('ROM'.$tile_num,'start',$rom_start); + $self->object_add_attribute('ROM'.$tile_num,'end',$rom_end); + $self->object_add_attribute('RAM'.$tile_num,'start',$ram_start); + $self->object_add_attribute('RAM'.$tile_num,'end',$ram_end); + + + } + + + } + else + { + my $v=get_soc_peripheral_parameter ($self,"_ram","Aw"); + $v = 13 if (!defined $v); + $self->object_add_attribute('MEM0','width',$v); + $self->object_add_attribute('MEM0','percent',75); + my $s =(1 << ($v+2)) ; + my $p = 75; + + my $rom_start = 0; + my $rom_end= int ( ($s*$p)/100); + my $ram_start= int (($s*$p)/100); + my $ram_end= $s; + + $self->object_add_attribute('ROM0','start',$rom_start); + $self->object_add_attribute('ROM0','end',$rom_end); + $self->object_add_attribute('RAM0','start',$ram_start); + $self->object_add_attribute('RAM0','end',$ram_end); + } + + } sub linker_setting{ - my ($self,$tview)=@_; - my $win=def_popwin_size (80,50,"BRAM info", 'percent'); - my $sc_win = gen_scr_win_with_adjst($self,'liststore'); - my $table= def_table(10,10,FALSE); - - - my $row=0; - my $col=0; - - $table-> attach (gen_label_in_center("Tile"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; - $table-> attach (gen_label_in_center("Memory Addr"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; - $table-> attach (gen_label_in_center("ROM/(ROM+RAM)"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; - - $table-> attach (gen_label_in_center("ROM index addr (hex)"), $col, $col+2, $row, $row+1,'shrink','shrink',2,2); $col+=3; - $table-> attach (gen_label_in_center("RAM index addr (hex)"), $col, $col+2, $row, $row+1,'shrink','shrink',2,2); $col+=3; - - - $col=0;$row++; - $table-> attach (gen_label_in_center("#"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_center("Width"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_center("(%)"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - $table-> attach (gen_label_in_center("Beginning"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; - $table-> attach (gen_label_in_center("End"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_center("Size"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - $table-> attach (gen_label_in_center("Beginning"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; - $table-> attach (gen_label_in_center("End"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_center("Size"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - $col=0;$row++; - - my $target_dir; - my @data; + my ($self,$tview)=@_; + my $win=def_popwin_size (80,50,"BRAM info", 'percent'); + my $sc_win = gen_scr_win_with_adjst($self,'liststore'); + my $table= def_table(10,10,FALSE); + + + my $row=0; + my $col=0; + + $table-> attach (gen_label_in_center("Tile"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; + $table-> attach (gen_label_in_center("Memory Addr"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; + $table-> attach (gen_label_in_center("ROM/(ROM+RAM)"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; + + $table-> attach (gen_label_in_center("ROM index addr (hex)"), $col, $col+2, $row, $row+1,'shrink','shrink',2,2); $col+=3; + $table-> attach (gen_label_in_center("RAM index addr (hex)"), $col, $col+2, $row, $row+1,'shrink','shrink',2,2); $col+=3; + + + $col=0;$row++; + $table-> attach (gen_label_in_center("#"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_center("Width"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_center("(%)"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + $table-> attach (gen_label_in_center("Beginning"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; + $table-> attach (gen_label_in_center("End"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_center("Size"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + $table-> attach (gen_label_in_center("Beginning"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; + $table-> attach (gen_label_in_center("End"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_center("Size"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + + $col=0;$row++; + + my $target_dir; + my @data; my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); my $tnum; - if(defined $mpsoc_name){#it is an mpsoc - - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - $tnum=$NE; - $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - } - else - { - my $soc_name=$self->object_get_attribute('soc_name'); - $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$soc_name"; - $tnum=1; - } - for (my $j=0;$j<$tnum;$j++){ - my $tile_num=$j; - my $conflict =gen_label_in_center(" ") ; - - $table-> attach (gen_label_in_center("$tile_num"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col++; - my $ram_width = gen_spin(2,64,1); - my $width = $self->object_get_attribute('MEM'.$tile_num,'width'); - if(!defined $width){ - linker_initial_setting ($self,$tview); - $width = $self->object_get_attribute('MEM'.$tile_num,'width'); - } - $ram_width->set_value($width); - my $size =gen_label_in_center(metric_conversion(1 << 15). "B") ; - - - $table-> attach (def_pack_hbox('FALSE',0,$ram_width,$size), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - - my $percent = gen_spin_float(6.25,93.75,6.25,2); - my $p=$self->object_get_attribute('MEM'.$tile_num,'percent'); - $percent->set_value($p); - - my $enter= def_image_button("icons/enter.png"); - $table-> attach (def_pack_hbox('FALSE',0,$percent,$enter), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - my $rom_start_v =$self->object_get_attribute('ROM'.$tile_num,'start'); - my $rom_end_v = $self->object_get_attribute('ROM'.$tile_num,'end'); - my $ram_start_v = $self->object_get_attribute('RAM'.$tile_num,'start'); - my $ram_end_v = $self->object_get_attribute('RAM'.$tile_num,'end'); - - - - my $rom_start = HexSpin->new ( $rom_start_v, 0, 0xffffffff ,4); - $rom_start->set_digits(8); - $table-> attach ($rom_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - my $rom_end = HexSpin->new ( $rom_end_v, 0, 0xffffffff ,4); - $rom_end->set_digits(8); - $table-> attach ($rom_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - my $rom_size =gen_label_in_center(" ") ; - $table-> attach ($rom_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict); - $rom_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); - $rom_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); - - my $ram_start = HexSpin->new ( $ram_start_v, 0, 0xffffffff ,4); - $ram_start->set_digits(8); - $table-> attach ($ram_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - my $ram_end = HexSpin->new ( $ram_end_v, 0, 0xffffffff ,4); - $ram_end->set_digits(8); - $table-> attach ($ram_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - my $ram_size =gen_label_in_center(" ") ; - $table-> attach ($ram_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - - update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict); - - $ram_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); - $ram_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); - - $ram_width->signal_connect("value_changed" => sub{ - my $w=$ram_width->get_value(); - $self->object_add_attribute('MEM'.$tile_num,'width',$w); - $size->set_label (metric_conversion(1 << ($w+2)). "B") ; - $size->show_all; - $enter->clicked; - }); - $percent->signal_connect("value_changed" => sub{ - $self->object_add_attribute('MEM'.$tile_num,'percent',$percent->get_value()); - }); - - $table-> attach ($conflict, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - - $enter-> signal_connect ( 'clicked' , sub { - my $w=$ram_width->get_value(); - my $s =(1 << ($w+2)); - my $p = $percent->get_value(); - - my $rom_start_v = 0; - my $rom_end_v= int ( ($s*$p)/100); - my $ram_start_v= int (($s*$p)/100); - my $ram_end_v= $s; - - $rom_start->set_value($rom_start_v); - $rom_end->set_value($rom_end_v); - $ram_start->set_value($ram_start_v); - $ram_end->set_value($ram_end_v); - update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict); - update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict); - - }); - - $col=0; $row++; - - }#$tile_num - - my $main_table=def_table(10,10,FALSE); - - my $ok = def_image_button('icons/select.png','OK'); - $main_table->attach_defaults ($table , 0, 12, 0,11); + if(defined $mpsoc_name){#it is an mpsoc + + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + $tnum=$NE; + $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + } + else + { + my $soc_name=$self->object_get_attribute('soc_name'); + $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$soc_name"; + $tnum=1; + } + for (my $j=0;$j<$tnum;$j++){ + my $tile_num=$j; + my $conflict =gen_label_in_center(" ") ; + + $table-> attach (gen_label_in_center("$tile_num"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col++; + my $ram_width = gen_spin(2,64,1); + my $width = $self->object_get_attribute('MEM'.$tile_num,'width'); + if(!defined $width){ + linker_initial_setting ($self,$tview); + $width = $self->object_get_attribute('MEM'.$tile_num,'width'); + } + $ram_width->set_value($width); + my $size =gen_label_in_center(metric_conversion(1 << 15). "B") ; + + + $table-> attach (def_pack_hbox('FALSE',0,$ram_width,$size), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + + + + my $percent = gen_spin_float(6.25,93.75,6.25,2); + my $p=$self->object_get_attribute('MEM'.$tile_num,'percent'); + $percent->set_value($p); + + my $enter= def_image_button("icons/enter.png"); + $table-> attach (def_pack_hbox('FALSE',0,$percent,$enter), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + my $rom_start_v =$self->object_get_attribute('ROM'.$tile_num,'start'); + my $rom_end_v = $self->object_get_attribute('ROM'.$tile_num,'end'); + my $ram_start_v = $self->object_get_attribute('RAM'.$tile_num,'start'); + my $ram_end_v = $self->object_get_attribute('RAM'.$tile_num,'end'); + + + + my $rom_start = HexSpin->new ( $rom_start_v, 0, 0xffffffff ,4); + $rom_start->set_digits(8); + $table-> attach ($rom_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + + + my $rom_end = HexSpin->new ( $rom_end_v, 0, 0xffffffff ,4); + $rom_end->set_digits(8); + $table-> attach ($rom_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + my $rom_size =gen_label_in_center(" ") ; + $table-> attach ($rom_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict); + $rom_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); + $rom_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); + + my $ram_start = HexSpin->new ( $ram_start_v, 0, 0xffffffff ,4); + $ram_start->set_digits(8); + $table-> attach ($ram_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + + my $ram_end = HexSpin->new ( $ram_end_v, 0, 0xffffffff ,4); + $ram_end->set_digits(8); + $table-> attach ($ram_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + my $ram_size =gen_label_in_center(" ") ; + $table-> attach ($ram_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + + + + update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict); + + $ram_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); + $ram_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); + + $ram_width->signal_connect("value_changed" => sub{ + my $w=$ram_width->get_value(); + $self->object_add_attribute('MEM'.$tile_num,'width',$w); + $size->set_label (metric_conversion(1 << ($w+2)). "B") ; + $size->show_all; + $enter->clicked; + }); + $percent->signal_connect("value_changed" => sub{ + $self->object_add_attribute('MEM'.$tile_num,'percent',$percent->get_value()); + }); + + $table-> attach ($conflict, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + + + + + $enter-> signal_connect ( 'clicked' , sub { + my $w=$ram_width->get_value(); + my $s =(1 << ($w+2)); + my $p = $percent->get_value(); + + my $rom_start_v = 0; + my $rom_end_v= int ( ($s*$p)/100); + my $ram_start_v= int (($s*$p)/100); + my $ram_end_v= $s; + + $rom_start->set_value($rom_start_v); + $rom_end->set_value($rom_end_v); + $ram_start->set_value($ram_start_v); + $ram_end->set_value($ram_end_v); + update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict); + update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict); + + }); + + $col=0; $row++; + + }#$tile_num + + my $main_table=def_table(10,10,FALSE); + + my $ok = def_image_button('icons/select.png','OK'); + $main_table->attach_defaults ($table , 0, 12, 0,11); $main_table->attach ($ok,5, 6, 11,12,'shrink','shrink',0,0); - - $ok->signal_connect('clicked', sub { - for (my $t=0;$t<$tnum;$t++){ - my $r0 =$self->object_get_attribute("ROM$t",'start'); - my $r1 =$self->object_get_attribute("ROM$t",'end'); - my $r2 =$self->object_get_attribute("RAM$t",'start'); - my $r3 =$self->object_get_attribute("RAM$t",'end'); - if(hex($r1) hex($r2) ){ - message_dialog("Please fix tile $t conflict range !"); - return ; - - } - - - - } - create_linker_var_file($self); - $win->destroy(); - - - }); - - - add_widget_to_scrolled_win($main_table,$sc_win); - $win->add($sc_win); - $win->show_all(); - + + $ok->signal_connect('clicked', sub { + for (my $t=0;$t<$tnum;$t++){ + my $r0 =$self->object_get_attribute("ROM$t",'start'); + my $r1 =$self->object_get_attribute("ROM$t",'end'); + my $r2 =$self->object_get_attribute("RAM$t",'start'); + my $r3 =$self->object_get_attribute("RAM$t",'end'); + if(hex($r1) hex($r2) ){ + message_dialog("Please fix tile $t conflict range !"); + return ; + + } + + + + } + create_linker_var_file($self); + $win->destroy(); + + + }); + + + add_widget_to_scrolled_win($main_table,$sc_win); + $win->add($sc_win); + $win->show_all(); + } sub create_linker_var_file{ - my ($self)=@_; - my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); + my ($self)=@_; + my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); my $tnum; my $width = $self->object_get_attribute('MEM0','width'); - if(!defined $width){ + if(!defined $width){ linker_initial_setting ($self); - } - - if(defined $mpsoc_name){#it is an mpsoc - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - $tnum=$NE; - } - else - { - - $tnum=1; - } - - for (my $t=0;$t<$tnum;$t++){ - my $r0 =$self->object_get_attribute("ROM$t",'start'); - my $r1 =$self->object_get_attribute("ROM$t",'end'); - my $r2 =$self->object_get_attribute("RAM$t",'start'); - my $r3 =$self->object_get_attribute("RAM$t",'end'); - - my $file=sprintf(" - + } + + if(defined $mpsoc_name){#it is an mpsoc + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + $tnum=$NE; + } + else + { + + $tnum=1; + } + + for (my $t=0;$t<$tnum;$t++){ + my $r0 =$self->object_get_attribute("ROM$t",'start'); + my $r1 =$self->object_get_attribute("ROM$t",'end'); + my $r2 =$self->object_get_attribute("RAM$t",'start'); + my $r3 =$self->object_get_attribute("RAM$t",'end'); + + my $file=sprintf(" + MEMORY -{ - rom (rx) : ORIGIN = 0x%x , LENGTH = 0x%x /* %s B- Rom space */ - ram (wrx) : ORIGIN = 0x%x , LENGTH = 0x%x /* %s B- Ram space */ -} - - ",$r0,$r1 - $r0, metric_conversion($r1 - $r0),$r2,$r3- $r2,metric_conversion($r3 - $r2)); - - if(defined $mpsoc_name){ - save_file ("$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name/sw/tile$t/linkvar.ld",$file) if(-d "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name/sw/tile$t/"); - }else{ - my $soc_name=$self->object_get_attribute('soc_name'); - my $p1="$ENV{'PRONOC_WORK'}/SOC/$soc_name/sw/"; - mkpath("$p1",1,0755) unless (-d "$p1"); - save_file ("$p1/linkvar.ld",$file) - } - } - +{ + rom (rx) : ORIGIN = 0x%x , LENGTH = 0x%x /* %s B- Rom space */ + ram (wrx) : ORIGIN = 0x%x , LENGTH = 0x%x /* %s B- Ram space */ +} + + ",$r0,$r1 - $r0, metric_conversion($r1 - $r0),$r2,$r3- $r2,metric_conversion($r3 - $r2)); + + if(defined $mpsoc_name){ + save_file ("$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name/sw/tile$t/linkvar.ld",$file) if(-d "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name/sw/tile$t/"); + }else{ + my $soc_name=$self->object_get_attribute('soc_name'); + my $p1="$ENV{'PRONOC_WORK'}/SOC/$soc_name/sw/"; + mkpath("$p1",1,0755) unless (-d "$p1"); + save_file ("$p1/linkvar.ld",$file) + } + } + } @@ -2370,7 +2383,7 @@ sub software_edit_mpsoc { my @pages_lables=($orcc_lable); my ($app,$table,$tview) = software_main($sw,undef,\@pages,\@pages_lables); - my $prog= def_image_button('icons/write.png','Program FPGA\'s BRAMs'); + my $prog= def_image_button('icons/write.png','Program FPGA\'s BRAMs'); my $linker = def_image_button('icons/setting.png','LD Linker',FALSE,1); my $make = def_image_button('icons/gen.png','_Compile',FALSE,1); my $ram = def_image_button('icons/info.png',"Required BRAMs\' size",FALSE,1); @@ -2380,12 +2393,12 @@ sub software_edit_mpsoc { $table->attach ($make,5, 6, 1,2,'shrink','shrink',0,0); $table->attach ($prog,9, 10, 1,2,'shrink','shrink',0,0); - $ram -> signal_connect("clicked" => sub{ - show_reqired_brams($self,$tview); - }); - - my $load; - + $ram -> signal_connect("clicked" => sub{ + show_reqired_brams($self,$tview); + }); + + my $load; + $make -> signal_connect("clicked" => sub{ $load->destroy if(defined $load); $load= show_gif("icons/load.gif"); @@ -2394,18 +2407,18 @@ sub software_edit_mpsoc { $app->ask_to_save_changes(); add_info($tview,' '); unless (run_make_file($sw,$tview,'clean')){ - $load->destroy; - $load=def_icon("icons/cancel.png"); - $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); - $load->show_all; - return; + $load->destroy; + $load=def_icon("icons/cancel.png"); + $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); + $load->show_all; + return; }; unless (run_make_file($sw,$tview)){ - $load->destroy; - $load=def_icon("icons/cancel.png"); - $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); - $load->show_all; - return; + $load->destroy; + $load=def_icon("icons/cancel.png"); + $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); + $load->show_all; + return; } $load->destroy; $load=def_icon("icons/button_ok.png"); @@ -2456,8 +2469,8 @@ sub software_edit_mpsoc { $linker -> signal_connect("clicked" => sub{ - linker_setting($self,$tview); - }); + linker_setting($self,$tview); + }); } @@ -2470,7 +2483,7 @@ sub software_edit_mpsoc { sub load_mpsoc{ my ($mpsoc,$info)=@_; my $file; - my $dialog = gen_file_dialog (undef, 'MPSOC'); + my $dialog = gen_file_dialog (undef, 'MPSOC'); my $dir = Cwd::getcwd(); $dialog->set_current_folder ("$dir/lib/mpsoc") ; my @newsocs=$mpsoc->mpsoc_get_soc_list(); @@ -2516,389 +2529,389 @@ sub load_mpsoc{ } ####### -# CLK setting +# CLK setting ####### sub clk_setting_win1{ - my ($self,$info,$type)=@_; + my ($self,$info,$type)=@_; - my $window = def_popwin_size(80,80,"CLK setting",'percent'); + my $window = def_popwin_size(80,80,"CLK setting",'percent'); - my $next=def_image_button('icons/right.png','Next'); - my $mtable = def_table(10, 1, FALSE); - #get the list of all tiles clk sources - - my @sources=('clk','reset'); - - my $table = def_table(10, 7, FALSE); - my $notebook = gen_notebook(); - $notebook->set_scrollable(TRUE); - #$notebook->can_focus(FALSE); - $notebook->set_tab_pos ('left'); - - - - my($row,$column)=(0,0); - - my %all = ($type eq 'mpsoc') ? get_all_tiles_clk_sources_list($self): get_soc_clk_source_list($self) ; - foreach my $s (@sources){ - my $spin; - ($row,$column,$spin)= add_param_widget($self,"$s number","${s}_number", 1,'Spin-button',"1,1024,1","Define total number of ${s} input ports mpsoc", $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); - - my $w=get_source_assignment_win($self,$s,$all{$s},$type); - my $box=def_hbox(FALSE,0); - $box->pack_start($w, TRUE, TRUE, 0); - $notebook->append_page ($box,gen_label_in_center ($s)); - $spin->signal_connect("value_changed" => sub{ - $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",1); - $w->destroy; - $w=get_source_assignment_win($self,$s,$all{$s},$type); - $box->pack_start($w, TRUE, TRUE, 0); - $box->show_all; - - }); - - } - - $mtable->attach_defaults($table,0,1,0,1); - $mtable->attach_defaults( $notebook,0,1,1,20); - $mtable->attach($next,0,1,20,21,'expand','fill',2,2); - $window->add ($mtable); - $window->show_all(); - $next-> signal_connect("clicked" => sub{ - clk_setting_win2($self,$info,$type); - $window->destroy; - - }); + my $next=def_image_button('icons/right.png','Next'); + my $mtable = def_table(10, 1, FALSE); + #get the list of all tiles clk sources + + my @sources=('clk','reset'); + + my $table = def_table(10, 7, FALSE); + my $notebook = gen_notebook(); + $notebook->set_scrollable(TRUE); + #$notebook->can_focus(FALSE); + $notebook->set_tab_pos ('left'); + + + + my($row,$column)=(0,0); + + my %all = ($type eq 'mpsoc') ? get_all_tiles_clk_sources_list($self): get_soc_clk_source_list($self) ; + foreach my $s (@sources){ + my $spin; + ($row,$column,$spin)= add_param_widget($self,"$s number","${s}_number", 1,'Spin-button',"1,1024,1","Define total number of ${s} input ports mpsoc", $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); + + my $w=get_source_assignment_win($self,$s,$all{$s},$type); + my $box=def_hbox(FALSE,0); + $box->pack_start($w, TRUE, TRUE, 0); + $notebook->append_page ($box,gen_label_in_center ($s)); + $spin->signal_connect("value_changed" => sub{ + $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",1); + $w->destroy; + $w=get_source_assignment_win($self,$s,$all{$s},$type); + $box->pack_start($w, TRUE, TRUE, 0); + $box->show_all; + + }); + + } + + $mtable->attach_defaults($table,0,1,0,1); + $mtable->attach_defaults( $notebook,0,1,1,20); + $mtable->attach($next,0,1,20,21,'expand','fill',2,2); + $window->add ($mtable); + $window->show_all(); + $next-> signal_connect("clicked" => sub{ + clk_setting_win2($self,$info,$type); + $window->destroy; + + }); } sub update_wave_form { - my ($period,$rise,$fall,$r_lab,$f_lab)=@_; - my $p =$period->get_value(); - my $n =$rise->get_value(); - my $v= ($p * $n)/100; - $r_lab->set_text("=$v ns"); - $n =$fall->get_value(); - $v= ($p * $n)/100; - $f_lab->set_text("=$v ns"); + my ($period,$rise,$fall,$r_lab,$f_lab)=@_; + my $p =$period->get_value(); + my $n =$rise->get_value(); + my $v= ($p * $n)/100; + $r_lab->set_text("=$v ns"); + $n =$fall->get_value(); + $v= ($p * $n)/100; + $f_lab->set_text("=$v ns"); } sub get_source_assignment_win{ - my ($mpsoc,$s,$ports_ref,$type)=@_; - my$row=0; - my $column=0; - my $num = $mpsoc->object_get_attribute('SOURCE_SET',"${s}_number"); - my $table1 = def_table(20, 20, FALSE); - my $win1=add_widget_to_scrolled_win($table1); - my $win2; - my $v2; - - #if($s eq 'clk'){ - # my @labels=("clk name", 'Frequency MHz', 'Period ns', 'rise edge times ns', 'fall edge times ns'); - # foreach my $l (@labels){ - # $table1->attach (gen_label_in_center($l),$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=5; - # } - #$row++; - #$column=0; - #} - - #get source signal names - my $loc = 'vertical'; - for(my $n=0;$n<$num; $n++ ){ - my $entry; - my $enter= def_image_button("icons/enter.png"); - my $box=def_hbox(FALSE,0); - $box->pack_start( $enter, FALSE, FALSE, 0); - - ($row,$column,$entry)= add_param_widget($mpsoc,"$n-","${s}_${n}_name", "${s}$n",'Entry',undef,undef, $table1,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); - $table1->attach ($box,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column++; - - $enter->signal_connect ("clicked" => sub{ - $mpsoc->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",1); - $win2->destroy; - $win2= get_source_assignment_win2($mpsoc,$s,$ports_ref,$type); - $v2-> pack2($win2, TRUE, TRUE); - $v2->show_all; - }); - - - if($s eq 'clk'){ - ($column,$row)=get_clk_constrain_widget($mpsoc,$table1,$column,$row, $s,$n); - } - - - - # if((($n+1) % 4)==0){ - $column=0; - $row++; - #} - } - - #source assigmnmet + my ($mpsoc,$s,$ports_ref,$type)=@_; + my$row=0; + my $column=0; + my $num = $mpsoc->object_get_attribute('SOURCE_SET',"${s}_number"); + my $table1 = def_table(20, 20, FALSE); + my $win1=add_widget_to_scrolled_win($table1); + my $win2; + my $v2; + + #if($s eq 'clk'){ + # my @labels=("clk name", 'Frequency MHz', 'Period ns', 'rise edge times ns', 'fall edge times ns'); + # foreach my $l (@labels){ + # $table1->attach (gen_label_in_center($l),$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=5; + # } + #$row++; + #$column=0; + #} + + #get source signal names + my $loc = 'vertical'; + for(my $n=0;$n<$num; $n++ ){ + my $entry; + my $enter= def_image_button("icons/enter.png"); + my $box=def_hbox(FALSE,0); + $box->pack_start( $enter, FALSE, FALSE, 0); + + ($row,$column,$entry)= add_param_widget($mpsoc,"$n-","${s}_${n}_name", "${s}$n",'Entry',undef,undef, $table1,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); + $table1->attach ($box,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column++; + + $enter->signal_connect ("clicked" => sub{ + $mpsoc->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",1); + $win2->destroy; + $win2= get_source_assignment_win2($mpsoc,$s,$ports_ref,$type); + $v2-> pack2($win2, TRUE, TRUE); + $v2->show_all; + }); + + + if($s eq 'clk'){ + ($column,$row)=get_clk_constrain_widget($mpsoc,$table1,$column,$row, $s,$n); + } + + + + # if((($n+1) % 4)==0){ + $column=0; + $row++; + #} + } + + #source assigmnmet $win2= get_source_assignment_win2($mpsoc,$s,$ports_ref,$type); - $v2=gen_vpaned($win1,.2,$win2); - return $v2; + $v2=gen_vpaned($win1,.2,$win2); + return $v2; } sub get_clk_constrain_widget { - my ($self,$table,$column,$row, $s,$n)=@_; - $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; - return ($column,$row); - my $frequency; - ($row,$column,$frequency)= add_param_widget($self,"Frequency(MHz)","${s}_${n}_mhz", 100,'Spin-button',"1,1024,0.01",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); - $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; - my $period; - ($row,$column,$period)= add_param_widget($self,"Period(ns)","${s}_${n}_period", 10,'Spin-button',"0,1024,0.01",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); - $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; - my $rise; - ($row,$column,$rise)= add_param_widget($self,"rising edge(%)","${s}_${n}_rise", 0,'Spin-button',"0,100,0.1",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); - my $r_lab=gen_label_in_center('=0 ns'); - $table->attach ($r_lab,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=1; - $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; - my $fall; - ($row,$column,$fall)= add_param_widget($self,"falling edge(%)","${s}_${n}_fall", 50,'Spin-button',"0,100,0.1",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); - my $f_lab=gen_label_in_center('=5 ns'); - $table->attach ($f_lab,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=1; - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); - $frequency-> signal_connect("value_changed" => sub{ - my $fr =$frequency->get_value(); - my $p = 1000/$fr; - $period->set_value($p); - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); - }); - $period-> signal_connect("value_changed" => sub{ - my $p =$period->get_value(); - my $fr = 1000/$p; - $frequency->set_value($fr); - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); - }); - $rise-> signal_connect("value_changed" => sub{ - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); - }); - $fall-> signal_connect("value_changed" => sub{ - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); - }); - return ($column,$row); + my ($self,$table,$column,$row, $s,$n)=@_; + $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; + return ($column,$row); + my $frequency; + ($row,$column,$frequency)= add_param_widget($self,"Frequency(MHz)","${s}_${n}_mhz", 100,'Spin-button',"1,1024,0.01",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); + $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; + my $period; + ($row,$column,$period)= add_param_widget($self,"Period(ns)","${s}_${n}_period", 10,'Spin-button',"0,1024,0.01",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); + $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; + my $rise; + ($row,$column,$rise)= add_param_widget($self,"rising edge(%)","${s}_${n}_rise", 0,'Spin-button',"0,100,0.1",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); + my $r_lab=gen_label_in_center('=0 ns'); + $table->attach ($r_lab,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=1; + $table->attach (gen_Vsep() , $column,$column+1,$row,$row+1,'fill','fill',2,2);$column+=1; + my $fall; + ($row,$column,$fall)= add_param_widget($self,"falling edge(%)","${s}_${n}_fall", 50,'Spin-button',"0,100,0.1",undef, $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); + my $f_lab=gen_label_in_center('=5 ns'); + $table->attach ($f_lab,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=1; + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + $frequency-> signal_connect("value_changed" => sub{ + my $fr =$frequency->get_value(); + my $p = 1000/$fr; + $period->set_value($p); + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + }); + $period-> signal_connect("value_changed" => sub{ + my $p =$period->get_value(); + my $fr = 1000/$p; + $frequency->set_value($fr); + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + }); + $rise-> signal_connect("value_changed" => sub{ + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + }); + $fall-> signal_connect("value_changed" => sub{ + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + }); + return ($column,$row); } sub get_source_assignment_win2{ - my ($mpsoc,$s,$ports_ref,$type)=@_; - my $num = $mpsoc->object_get_attribute('SOURCE_SET',"${s}_number"); - my $table2 = def_table(10, 7, FALSE); - my $win2=add_widget_to_scrolled_win($table2); - my %ports = %{$ports_ref} if(defined $ports_ref); + my ($mpsoc,$s,$ports_ref,$type)=@_; + my $num = $mpsoc->object_get_attribute('SOURCE_SET',"${s}_number"); + my $table2 = def_table(10, 7, FALSE); + my $win2=add_widget_to_scrolled_win($table2); + my %ports = %{$ports_ref} if(defined $ports_ref); - my $contents; - for(my $n=0;$n<$num; $n++ ){ - my $m=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); - $contents=(defined $contents)? "$contents,$m":$m; - } - my $default=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_0_name"); - my $n=0; - my($row,$column)=(0,0); - if($type eq 'mpsoc' ) { - add_param_widget($mpsoc," NoC $s","NoC_${s}", $default,'Combo-box',$contents,undef, $table2,$row,$column,1,'SOURCE_SET_CONNECT',undef,undef,'horizontal'); - ($row,$column)=(1,0); - } - - foreach my $p (sort keys %ports){ - my @array=@{$ports{$p}}; - foreach my $q (@array){ - my $param="${p}_$q"; - my $label=" ${p}_$q"; - ($row,$column)= add_param_widget($mpsoc,$label,$param, $default,'Combo-box',$contents,undef, $table2,$row,$column,1,'SOURCE_SET_CONNECT',undef,undef,'horizontal'); - if((($n+1) % 4)==0){$column=0;$row++;}$n++; - } - } - return $win2; - + my $contents; + for(my $n=0;$n<$num; $n++ ){ + my $m=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); + $contents=(defined $contents)? "$contents,$m":$m; + } + my $default=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_0_name"); + my $n=0; + my($row,$column)=(0,0); + if($type eq 'mpsoc' ) { + add_param_widget($mpsoc," NoC $s","NoC_${s}", $default,'Combo-box',$contents,undef, $table2,$row,$column,1,'SOURCE_SET_CONNECT',undef,undef,'horizontal'); + ($row,$column)=(1,0); + } + + foreach my $p (sort keys %ports){ + my @array=@{$ports{$p}}; + foreach my $q (@array){ + my $param="${p}_$q"; + my $label=" ${p}_$q"; + ($row,$column)= add_param_widget($mpsoc,$label,$param, $default,'Combo-box',$contents,undef, $table2,$row,$column,1,'SOURCE_SET_CONNECT',undef,undef,'horizontal'); + if((($n+1) % 4)==0){$column=0;$row++;}$n++; + } + } + return $win2; + } sub get_all_tiles_clk_sources_list{ - my $mpsoc=shift; - my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); - my %all_sources; - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); - next if(!defined $soc_name); - my $top=$mpsoc->mpsoc_get_soc($soc_name); - my @intfcs=$top->top_get_intfc_list(); - - my @sources=('clk','reset'); - - foreach my $intfc (@intfcs){ - my($type,$name,$num)= split("[:\[ \\]]", $intfc); - foreach my $s (@sources){ - if ($intfc =~ /plug:$s/){ - my @ports=$top->top_get_intfc_ports_list($intfc); - $all_sources{$s}{"T$tile_num"}=\@ports; - } - } - - } - } - return %all_sources; + my $mpsoc=shift; + my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); + my %all_sources; + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); + next if(!defined $soc_name); + my $top=$mpsoc->mpsoc_get_soc($soc_name); + my @intfcs=$top->top_get_intfc_list(); + + my @sources=('clk','reset'); + + foreach my $intfc (@intfcs){ + my($type,$name,$num)= split("[:\[ \\]]", $intfc); + foreach my $s (@sources){ + if ($intfc =~ /plug:$s/){ + my @ports=$top->top_get_intfc_ports_list($intfc); + $all_sources{$s}{"T$tile_num"}=\@ports; + } + } + + } + } + return %all_sources; } sub clk_setting_win2{ - my ($self,$info,$type)=@_; - - my $window = def_popwin_size(70,70,"CLK setting",'percent'); + my ($self,$info,$type)=@_; + + my $window = def_popwin_size(70,70,"CLK setting",'percent'); my $table = def_table(10, 7, FALSE); my $scrolled_win=add_widget_to_scrolled_win($table); - my $ok = def_image_button('icons/select.png','OK'); + my $ok = def_image_button('icons/select.png','OK'); my $back = def_image_button('icons/left.png',undef); - my $diagram = def_image_button('icons/diagram.png','Diagram'); + my $diagram = def_image_button('icons/diagram.png','Diagram'); my $ip = ip->lib_new (); #print "get_top_ip(\$self,$type);\n"; my $mpsoc_ip=get_top_ip($self,$type); - $ip->add_ip($mpsoc_ip); + $ip->add_ip($mpsoc_ip); my $soc =get_source_set_top($self,$type); my $infc = interface->interface_new(); set_gui_status($soc,"ideal",0); # A tree view for holding a library - my %tree_text; - my @categories= ('Source'); + my %tree_text; + my @categories= ('Source'); foreach my $p (@categories) { - my @modules= $ip->get_modules($p); - $tree_text{$p}=\@modules; + my @modules= $ip->get_modules($p); + $tree_text{$p}=\@modules; } - my $tree_box = create_tree ($soc,'IP list', $info,\%tree_text,\&tmp,\&add_module_to_mpsoc); + my $tree_box = create_tree ($soc,'IP list', $info,\%tree_text,\&tmp,\&add_module_to_mpsoc); my $device_win=show_active_dev($soc,$ip,$infc,$info); my $h1=gen_hpaned($tree_box,.15,$device_win); $table->attach_defaults ($h1,0, 10, 0, 10); - + my $event =Event->timer (after => 1, interval => 1, cb => sub { my ($state,$timeout)= get_gui_status($soc); - - - if ($timeout>0){ - $timeout--; - set_gui_status($soc,$state,$timeout); - } - elsif( $state ne "ideal" ){ - - #check if top is removed add it - my @instances=$soc->soc_get_all_instances(); - my $redefine =1; - foreach my $inst (@instances){ - $redefine = 0 if ($inst eq 'TOP'); - } - if($redefine == 1){ - my $ip = ip->lib_new (); - #print "get_top_ip(\$self,$type);\n"; - my $mpsoc_ip=get_top_ip($self,$type); - - $ip->add_ip($mpsoc_ip); - $soc ->object_add_attribute('SOURCE_SET',"IP",$mpsoc_ip); - $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",0); - add_mpsoc_to_device($soc,$ip); - $self->object_add_attribute('SOURCE_SET',"SOC",$soc); - } - - $device_win->destroy; - - $device_win=show_active_dev($soc,$ip,$infc,$info); - $h1 -> pack2($device_win, TRUE, TRUE); - $h1 -> show_all; - $table->show_all(); - $device_win->show_all(); - - $self->object_add_attribute('SOURCE_SET',"SOC",$soc); - set_gui_status($soc,"ideal",0); - - } - return TRUE; + + + if ($timeout>0){ + $timeout--; + set_gui_status($soc,$state,$timeout); + } + elsif( $state ne "ideal" ){ + + #check if top is removed add it + my @instances=$soc->soc_get_all_instances(); + my $redefine =1; + foreach my $inst (@instances){ + $redefine = 0 if ($inst eq 'TOP'); + } + if($redefine == 1){ + my $ip = ip->lib_new (); + #print "get_top_ip(\$self,$type);\n"; + my $mpsoc_ip=get_top_ip($self,$type); + + $ip->add_ip($mpsoc_ip); + $soc ->object_add_attribute('SOURCE_SET',"IP",$mpsoc_ip); + $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",0); + add_mpsoc_to_device($soc,$ip); + $self->object_add_attribute('SOURCE_SET',"SOC",$soc); + } + + $device_win->destroy; + + $device_win=show_active_dev($soc,$ip,$infc,$info); + $h1 -> pack2($device_win, TRUE, TRUE); + $h1 -> show_all; + $table->show_all(); + $device_win->show_all(); + + $self->object_add_attribute('SOURCE_SET',"SOC",$soc); + set_gui_status($soc,"ideal",0); + + } + return TRUE; }); - my $mtable = def_table(10, 5, FALSE); - $mtable->attach_defaults($scrolled_win,0,5,0,9); - $mtable->attach($back,0,1,9,10,'expand','fill',2,2) if($type ne 'soc'); - $mtable->attach($diagram,2,4,9,10,'expand','fill',2,2); - $mtable->attach($ok,4,5,9,10,'expand','fill',2,2); - - $window->add ($mtable); - $window->show_all(); - $self->object_add_attribute('SOURCE_SET',"SOC",$soc); - $back-> signal_connect("clicked" => sub{ - $self->object_add_attribute('SOURCE_SET',"SOC",$soc); - clk_setting_win1($self,$info,$type); - $window->destroy; - $event->cancel; - }); - - $diagram-> signal_connect("clicked" => sub{ - show_tile_diagram ($soc); - }); - - $ok-> signal_connect("clicked" => sub{ - set_gui_status($self,"ref",1); - $window->destroy; - $event->cancel; - }); - - + my $mtable = def_table(10, 5, FALSE); + $mtable->attach_defaults($scrolled_win,0,5,0,9); + $mtable->attach($back,0,1,9,10,'expand','fill',2,2) if($type ne 'soc'); + $mtable->attach($diagram,2,4,9,10,'expand','fill',2,2); + $mtable->attach($ok,4,5,9,10,'expand','fill',2,2); + + $window->add ($mtable); + $window->show_all(); + $self->object_add_attribute('SOURCE_SET',"SOC",$soc); + $back-> signal_connect("clicked" => sub{ + $self->object_add_attribute('SOURCE_SET',"SOC",$soc); + clk_setting_win1($self,$info,$type); + $window->destroy; + $event->cancel; + }); + + $diagram-> signal_connect("clicked" => sub{ + show_tile_diagram ($soc); + }); + + $ok-> signal_connect("clicked" => sub{ + set_gui_status($self,"ref",1); + $window->destroy; + $event->cancel; + }); + + - - - + + + } sub tmp{ - + } sub add_module_to_mpsoc{ - my ($soc,$category,$module,$info)=@_; - my $ip = ip->lib_new (); - - my ($instance_id,$id)= get_instance_id($soc,$category,$module); - - #add module instance - my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); - - if($result == 0){ - my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; - show_info($info,$info_text); - return; - } - $soc->soc_add_instance_order($instance_id); - # Add IP version - my $v=$ip->ip_get($category,$module,"version"); - $v = 0 if(!defined $v); - #print "$v\n"; - $soc->object_add_attribute($instance_id,"version",$v); - # Read default parameter from lib and add them to soc - my %param_default= $ip->get_param_default($category,$module); - - my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); - if($rr == 0){ - my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist."; - show_info($info,$info_text); - return; - } - my @r=$ip->ip_get_param_order($category,$module); - $soc->soc_add_instance_param_order($instance_id,\@r); - - get_module_parameter($soc,$ip,$instance_id); - undef $ip; - set_gui_status($soc,"refresh_soc",0); + my ($soc,$category,$module,$info)=@_; + my $ip = ip->lib_new (); + + my ($instance_id,$id)= get_instance_id($soc,$category,$module); + + #add module instance + my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); + + if($result == 0){ + my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; + show_info($info,$info_text); + return; + } + $soc->soc_add_instance_order($instance_id); + # Add IP version + my $v=$ip->ip_get($category,$module,"version"); + $v = 0 if(!defined $v); + #print "$v\n"; + $soc->object_add_attribute($instance_id,"version",$v); + # Read default parameter from lib and add them to soc + my %param_default= $ip->get_param_default($category,$module); + + my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); + if($rr == 0){ + my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist."; + show_info($info,$info_text); + return; + } + my @r=$ip->ip_get_param_order($category,$module); + $soc->soc_add_instance_param_order($instance_id,\@r); + + get_module_parameter($soc,$ip,$instance_id); + undef $ip; + set_gui_status($soc,"refresh_soc",0); } @@ -2906,211 +2919,211 @@ sub add_module_to_mpsoc{ #$mpsoc,$top_ip,$sw_dir,$soc_name,$id,$soc_num,$txview sub get_top_ip{ - my ($self,$type)=@_; - - my $mpsoc_ip=ip_gen->ip_gen_new(); - $mpsoc_ip->ipgen_add("module_name",'TOP'); - $mpsoc_ip->ipgen_add("ip_name",'TOP'); - $mpsoc_ip->ipgen_add("category",'TOP'); - $mpsoc_ip->ipgen_add('GUI_REMOVE_SET','DISABLE'); - if($type eq 'mpsoc'){ - my @sources=('clk','reset'); - foreach my $s (@sources){ - my $num = $self->object_get_attribute('SOURCE_SET',"${s}_number"); - $num=1 if(!defined $num); - $mpsoc_ip->ipgen_add_plug("$s",'num',$num); - for (my $n=0; $n<$num; $n++ ){ - - my $name=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); - $mpsoc_ip->ipgen_set_plug_name($s,$n,$name); - $mpsoc_ip->ipgen_add_port($name,undef,'input',"plug:${s}\[$n\]","${s}_i"); - - } - } - # add_mpsoc_ip_other_interfaces($mpsoc,$mpsoc_ip); - } - else{ - my %sources = get_soc_clk_source_list($self); - foreach my $s (sort keys %sources){ - my @ports = @{$sources{$s}} if (defined $sources{$s}); - my $num=scalar @ports; - $mpsoc_ip->ipgen_add_plug("$s",'num',$num); - my $n=0; - foreach my $p (@ports){ - $mpsoc_ip->ipgen_set_plug_name($s,$n,$p); - $mpsoc_ip->ipgen_add_port($p,undef,'input',"plug:${s}\[$n\]","${s}_i"); - $n++; - } - } - } - return $mpsoc_ip; + my ($self,$type)=@_; + + my $mpsoc_ip=ip_gen->ip_gen_new(); + $mpsoc_ip->ipgen_add("module_name",'TOP'); + $mpsoc_ip->ipgen_add("ip_name",'TOP'); + $mpsoc_ip->ipgen_add("category",'TOP'); + $mpsoc_ip->ipgen_add('GUI_REMOVE_SET','DISABLE'); + if($type eq 'mpsoc'){ + my @sources=('clk','reset'); + foreach my $s (@sources){ + my $num = $self->object_get_attribute('SOURCE_SET',"${s}_number"); + $num=1 if(!defined $num); + $mpsoc_ip->ipgen_add_plug("$s",'num',$num); + for (my $n=0; $n<$num; $n++ ){ + + my $name=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); + $mpsoc_ip->ipgen_set_plug_name($s,$n,$name); + $mpsoc_ip->ipgen_add_port($name,undef,'input',"plug:${s}\[$n\]","${s}_i"); + + } + } + # add_mpsoc_ip_other_interfaces($mpsoc,$mpsoc_ip); + } + else{ + my %sources = get_soc_clk_source_list($self); + foreach my $s (sort keys %sources){ + my @ports = @{$sources{$s}} if (defined $sources{$s}); + my $num=scalar @ports; + $mpsoc_ip->ipgen_add_plug("$s",'num',$num); + my $n=0; + foreach my $p (@ports){ + $mpsoc_ip->ipgen_set_plug_name($s,$n,$p); + $mpsoc_ip->ipgen_add_port($p,undef,'input',"plug:${s}\[$n\]","${s}_i"); + $n++; + } + } + } + return $mpsoc_ip; } sub add_mpsoc_ip_other_interfaces{ - my ($mpsoc,$mpsoc_ip)=@_; + my ($mpsoc,$mpsoc_ip)=@_; my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); my $processors_en=0; my %intfc_num; my @parameters_order; - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); - - - my $top=$mpsoc->mpsoc_get_soc($soc_name); - my @nis=get_NI_instance_list($top); - my @noc_param=$top->top_get_parameter_list($nis[0]); - my $inst_name=$top->top_get_def_of_instance($nis[0],'instance'); - - #other parameters - my %params=$top->top_get_default_soc_param(); - - my @intfcs=$top->top_get_intfc_list(); - - my $i=0; - - my $dir = Cwd::getcwd(); - my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); - my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - my $soc_file="$target_dir/src_verilog/tiles/$soc_name.sv"; - - my $vdb =read_verilog_file($soc_file); - - my %soc_localparam = $vdb->get_modules_parameters($soc_name); - - - foreach my $intfc (@intfcs){ - - # Auto connected/not connected interface - if( $intfc eq 'socket:ni[0]' || ($intfc =~ /plug:clk\[/) || ( $intfc =~ /plug:reset\[/)|| ($intfc =~ /socket:RxD_sim\[/ ) || $intfc =~ /plug:enable\[/){ - #do nothing - } - elsif( $intfc eq 'IO' ){ - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); - $mpsoc_ip->ipgen_add_port($io_port,$new_range,$type,'IO','IO'); - - - } - - } - - else { - #other interface - my($if_type,$if_name,$if_num)= split("[:\[ \\]]", $intfc); - print "my($if_type,$if_name,$if_num)= split(, $intfc); \n"; - my $num = (defined $intfc_num{"$if_type:$if_name"})? $intfc_num{"$if_type:$if_name"}+1:0; - $intfc_num{"$if_type:$if_name"}=$num; - $mpsoc_ip->ipgen_add_plug("$if_name",'num',$num) if ($if_type eq 'plug'); - $mpsoc_ip->ipgen_add_soket("$if_name",'num',$num) if ($if_type eq 'socket'); - - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); - $mpsoc_ip->ipgen_add_port($io_port,$new_range,$type,"$if_type:$if_name\[$num\]",$intfc_port); - - } - } - } - - - my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); - #if ($setting eq 'Custom'){ - %params= $top->top_get_custom_soc_param($tile_num); - #}else{ - # %params=$top->top_get_default_soc_param(); - #} - - foreach my $p (sort keys %params){ - $params{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$params{$p}); - $params{$p}=add_instantc_name_to_parameters(\%soc_localparam,"T$tile_num",$params{$p}); - my $pname="T${tile_num}_$p"; - $mpsoc_ip-> ipgen_add_parameter ($pname,$params{$p},'Fixed',undef,undef,'Localparam',1); - push (@parameters_order,$pname); - - } - foreach my $p (sort keys %soc_localparam){ - $soc_localparam{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$soc_localparam{$p}); - $soc_localparam{$p}=add_instantc_name_to_parameters(\%soc_localparam,"T$tile_num",$soc_localparam{$p}); - my $pname="T${tile_num}_$p"; - $mpsoc_ip-> ipgen_add_parameter ($pname,$soc_localparam{$p},'Fixed',undef,undef,'Localparam',0); - push (@parameters_order,$pname); - - } - - - - } - #TODO get parameter order - $mpsoc_ip->ipgen_add("parameters_order",\@parameters_order); - + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); + + + my $top=$mpsoc->mpsoc_get_soc($soc_name); + my @nis=get_NI_instance_list($top); + my @noc_param=$top->top_get_parameter_list($nis[0]); + my $inst_name=$top->top_get_def_of_instance($nis[0],'instance'); + + #other parameters + my %params=$top->top_get_default_soc_param(); + + my @intfcs=$top->top_get_intfc_list(); + + my $i=0; + + my $dir = Cwd::getcwd(); + my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); + my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + my $soc_file="$target_dir/src_verilog/tiles/$soc_name.sv"; + + my $vdb =read_verilog_file($soc_file); + + my %soc_localparam = $vdb->get_modules_parameters($soc_name); + + + foreach my $intfc (@intfcs){ + + # Auto connected/not connected interface + if( $intfc eq 'socket:ni[0]' || ($intfc =~ /plug:clk\[/) || ( $intfc =~ /plug:reset\[/)|| ($intfc =~ /socket:RxD_sim\[/ ) || $intfc =~ /plug:enable\[/){ + #do nothing + } + elsif( $intfc eq 'IO' ){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); + $mpsoc_ip->ipgen_add_port($io_port,$new_range,$type,'IO','IO'); + + + } + + } + + else { + #other interface + my($if_type,$if_name,$if_num)= split("[:\[ \\]]", $intfc); + print "my($if_type,$if_name,$if_num)= split(, $intfc); \n"; + my $num = (defined $intfc_num{"$if_type:$if_name"})? $intfc_num{"$if_type:$if_name"}+1:0; + $intfc_num{"$if_type:$if_name"}=$num; + $mpsoc_ip->ipgen_add_plug("$if_name",'num',$num) if ($if_type eq 'plug'); + $mpsoc_ip->ipgen_add_soket("$if_name",'num',$num) if ($if_type eq 'socket'); + + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); + $mpsoc_ip->ipgen_add_port($io_port,$new_range,$type,"$if_type:$if_name\[$num\]",$intfc_port); + + } + } + } + + + my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); + #if ($setting eq 'Custom'){ + %params= $top->top_get_custom_soc_param($tile_num); + #}else{ + # %params=$top->top_get_default_soc_param(); + #} + + foreach my $p (sort keys %params){ + $params{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$params{$p}); + $params{$p}=add_instantc_name_to_parameters(\%soc_localparam,"T$tile_num",$params{$p}); + my $pname="T${tile_num}_$p"; + $mpsoc_ip-> ipgen_add_parameter ($pname,$params{$p},'Fixed',undef,undef,'Localparam',1); + push (@parameters_order,$pname); + + } + foreach my $p (sort keys %soc_localparam){ + $soc_localparam{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$soc_localparam{$p}); + $soc_localparam{$p}=add_instantc_name_to_parameters(\%soc_localparam,"T$tile_num",$soc_localparam{$p}); + my $pname="T${tile_num}_$p"; + $mpsoc_ip-> ipgen_add_parameter ($pname,$soc_localparam{$p},'Fixed',undef,undef,'Localparam',0); + push (@parameters_order,$pname); + + } + + + + } + #TODO get parameter order + $mpsoc_ip->ipgen_add("parameters_order",\@parameters_order); + } sub get_source_set_top{ - my ($self,$type)=@_; - my $soc =$self->object_get_attribute('SOURCE_SET',"SOC"); + my ($self,$type)=@_; + my $soc =$self->object_get_attribute('SOURCE_SET',"SOC"); my $redefine =$self->object_get_attribute('SOURCE_SET',"REDEFINE_TOP"); $redefine=1 if(!defined $redefine); if(!defined $soc){ - $soc = soc->soc_new(); - $soc->object_add_attribute('soc_name','TOP'); - $redefine=1; + $soc = soc->soc_new(); + $soc->object_add_attribute('soc_name','TOP'); + $redefine=1; } if($redefine==1){ - my $ip = ip->lib_new (); - #print "get_top_ip(\$self,$type);\n"; - my $mpsoc_ip=get_top_ip($self,$type); - - $ip->add_ip($mpsoc_ip); - $soc ->object_add_attribute('SOURCE_SET',"IP",$mpsoc_ip); - $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",0); - add_mpsoc_to_device($soc,$ip); - $self->object_add_attribute('SOURCE_SET',"SOC",$soc); - } - return $soc; + my $ip = ip->lib_new (); + #print "get_top_ip(\$self,$type);\n"; + my $mpsoc_ip=get_top_ip($self,$type); + + $ip->add_ip($mpsoc_ip); + $soc ->object_add_attribute('SOURCE_SET',"IP",$mpsoc_ip); + $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",0); + add_mpsoc_to_device($soc,$ip); + $self->object_add_attribute('SOURCE_SET',"SOC",$soc); + } + return $soc; } sub add_mpsoc_to_device{ - my ($soc,$ip)=@_; - my $category='TOP'; - my $module='TOP'; - my ($instance_id,$id) =('TOP',1); - - #my ($instance_id,$id)= get_instance_id($soc,$category,$module); - - remove_instance_from_soc($soc,$instance_id); - - #add module instanance - my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); - - if($result == 0){ - my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; - # show_info($info,$info_text); - return; - } - $soc->soc_add_instance_order($instance_id); - # Add IP version - my $v=$ip->ip_get($category,$module,"version"); - $v = 0 if(!defined $v); - #print "$v\n"; - $soc->object_add_attribute($instance_id,"version",$v); - # Read default parameter from lib and add them to soc - my %param_default= $ip->get_param_default($category,$module); - - my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); - if($rr == 0){ - my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist."; - # show_info($info,$info_text); - return; - } - my @r=$ip->ip_get_param_order($category,$module); - $soc->soc_add_instance_param_order($instance_id,\@r); - - #get_module_parameter($soc,$ip,$instance_id); - undef $ip; - set_gui_status($soc,"refresh_soc",0); + my ($soc,$ip)=@_; + my $category='TOP'; + my $module='TOP'; + my ($instance_id,$id) =('TOP',1); + + #my ($instance_id,$id)= get_instance_id($soc,$category,$module); + + remove_instance_from_soc($soc,$instance_id); + + #add module instanance + my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); + + if($result == 0){ + my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; + # show_info($info,$info_text); + return; + } + $soc->soc_add_instance_order($instance_id); + # Add IP version + my $v=$ip->ip_get($category,$module,"version"); + $v = 0 if(!defined $v); + #print "$v\n"; + $soc->object_add_attribute($instance_id,"version",$v); + # Read default parameter from lib and add them to soc + my %param_default= $ip->get_param_default($category,$module); + + my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); + if($rr == 0){ + my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist."; + # show_info($info,$info_text); + return; + } + my @r=$ip->ip_get_param_order($category,$module); + $soc->soc_add_instance_param_order($instance_id,\@r); + + #get_module_parameter($soc,$ip,$instance_id); + undef $ip; + set_gui_status($soc,"refresh_soc",0); } ###### @@ -3118,19 +3131,19 @@ sub add_mpsoc_to_device{ ###### sub ctrl_box{ - my ($mpsoc,$info)=@_; - my $table = def_table (1, 12, FALSE); - my $generate = def_image_button('icons/gen.png','_Generate RTL',FALSE,1); + my ($mpsoc,$info)=@_; + my $table = def_table (1, 12, FALSE); + my $generate = def_image_button('icons/gen.png','_Generate RTL',FALSE,1); my $compile = def_image_button('icons/gate.png','_Compile RTL',FALSE,1); my $software = def_image_button('icons/binary.png','_Software',FALSE,1); my $diagram = def_image_button('icons/diagram.png','Diagram'); - my $clk= def_image_button('icons/clk.png','CLK setting'); + my $clk= def_image_button('icons/clk.png','CLK setting'); - my $row=0; + my $row=0; - my $target_dir= "$ENV{'PRONOC_WORK'}/MPSOC"; - my ($entrybox,$entry ) =gen_save_load_widget ( + my $target_dir= "$ENV{'PRONOC_WORK'}/MPSOC"; + my ($entrybox,$entry ) =gen_save_load_widget ( $mpsoc, #the object "MPSoC name",#the label shown for setting configuration 'mpsoc_name',#the key name for saveing the setting configuration in object @@ -3139,8 +3152,8 @@ sub ctrl_box{ 'mpsoc',#check the given name match the SoC or mpsoc name rules 'lib/mpsoc',#where the current configuration seting file is saved 'MPSOC',#the extenstion given for configuration seting file - \&load_mpsoc,#refrence to load function - $info + \&load_mpsoc,#refrence to load function + $info ); $table->attach ($entrybox,$row, $row+2, 0,1,'expand','shrink',2,2);$row+=2; @@ -3149,8 +3162,8 @@ sub ctrl_box{ $table->attach ($generate, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; $table->attach ($software, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; $table->attach ($compile, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; - - $generate-> signal_connect("clicked" => sub{ + + $generate-> signal_connect("clicked" => sub{ generate_mpsoc($mpsoc,$info,1); set_gui_status($mpsoc,"refresh_soc",1); }); @@ -3166,7 +3179,7 @@ sub ctrl_box{ my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$name"; my $top_file = "$target_dir/src_verilog/${name}_top.v"; if (-f $top_file){ - my $answer = yes_no_dialog ("Do you want to Regenearte the MPSoC RTL code too?"); + my $answer = yes_no_dialog ("Do you want to Regenearte the MPSoC RTL code too?"); generate_mpsoc($mpsoc,$info,0) if ($answer eq 'yes'); select_compiler($mpsoc,$name,$top_file,$target_dir); } else { @@ -3176,18 +3189,18 @@ sub ctrl_box{ }); $software -> signal_connect("clicked" => sub{ - my $name=$mpsoc->object_get_attribute('mpsoc_name'); - $name="" if (!defined $name); - if (length($name)==0){ + my $name=$mpsoc->object_get_attribute('mpsoc_name'); + $name="" if (!defined $name); + if (length($name)==0){ message_dialog("Please define the MPSoC name!"); return ; } - my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$name"; - my $sw_folder = "$target_dir/sw"; - unless (-d $sw_folder){ - message_dialog("Cannot find $sw_folder. Please run RTL Generator first!"); - return; - } + my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$name"; + my $sw_folder = "$target_dir/sw"; + unless (-d $sw_folder){ + message_dialog("Cannot find $sw_folder. Please run RTL Generator first!"); + return; + } software_edit_mpsoc($mpsoc); }); @@ -3196,12 +3209,12 @@ sub ctrl_box{ show_topology_diagram ($mpsoc); }); - - $clk-> signal_connect("clicked" => sub{ - clk_setting_win1($mpsoc,$info,'mpsoc'); - }); - - return $table; + + $clk-> signal_connect("clicked" => sub{ + clk_setting_win1($mpsoc,$info,'mpsoc'); + }); + + return $table; } @@ -3221,54 +3234,54 @@ sub gen_save_load_widget { my $load = def_image_button('icons/load2.png'); my $entry=gen_entry_object($self,$param_name,undef,undef,undef,undef); my $entrybox=gen_label_info("$label:",$entry); - my $save = def_image_button('icons/save.png'); + my $save = def_image_button('icons/save.png'); my $open_dir = def_image_button('icons/open-folder.png') if (defined $target_dir); set_tip($save, "Save current $full_name configuration setting"); - set_tip($load, "Load a saved $full_name configuration setting"); - set_tip($open_dir, "Open target $full_name folder") if (defined $target_dir); - - $entrybox->pack_start( $save, FALSE, FALSE, 0); - $entrybox->pack_start( $load, FALSE, FALSE, 0); - $entrybox->pack_start( $open_dir , FALSE, FALSE, 0) if (defined $target_dir); - - $open_dir-> signal_connect("clicked" => sub{ - my $name=$self->object_get_attribute($param_name); + set_tip($load, "Load a saved $full_name configuration setting"); + set_tip($open_dir, "Open target $full_name folder") if (defined $target_dir); + + $entrybox->pack_start( $save, FALSE, FALSE, 0); + $entrybox->pack_start( $load, FALSE, FALSE, 0); + $entrybox->pack_start( $open_dir , FALSE, FALSE, 0) if (defined $target_dir); + + $open_dir-> signal_connect("clicked" => sub{ + my $name=$self->object_get_attribute($param_name); $name="" if (!defined $name); if (length($name)==0){ message_dialog("Please define the $label!"); return ; } return if(check_mpsoc_name($name,$label) && $check=='mpsoc') ; - return if(check_soc_name($name,$label) && $check=='soc') ; + return if(check_soc_name($name,$label) && $check=='soc') ; unless (-d "$target_dir/$name"){ - message_dialog("Cannot find $target_dir/$name.\n Please run RTL Generator first!",'error'); - return; - } - system "xdg-open $target_dir/$name"; - }) if (defined $target_dir); + message_dialog("Cannot find $target_dir/$name.\n Please run RTL Generator first!",'error'); + return; + } + system "xdg-open $target_dir/$name"; + }) if (defined $target_dir); $save-> signal_connect("clicked" => sub{ - my $name=$self->object_get_attribute($param_name); + my $name=$self->object_get_attribute($param_name); if (length($name)==0){ message_dialog("Please define the $label!"); return ; - } - return if(check_mpsoc_name($name,$label) && $check=='mpsoc') ; - return if(check_soc_name($name,$label) && $check=='soc') ; - # Write object file + } + return if(check_mpsoc_name($name,$label) && $check=='mpsoc') ; + return if(check_soc_name($name,$label) && $check=='soc') ; + # Write object file my $config_file = "${config_dir}/${name}.$extention"; - open(FILE, ">$config_file") || die "Can not open $config_file: $!"; - print FILE perl_file_header("${name}.$extention"); - print FILE Data::Dumper->Dump([\%$self],[$extention]); - close(FILE) || die "Error closing file: $!"; - message_dialog("Current configuration \"$name\" is saved as $config_file."); + open(FILE, ">$config_file") || die "Can not open $config_file: $!"; + print FILE perl_file_header("${name}.$extention"); + print FILE Data::Dumper->Dump([\%$self],[$extention]); + close(FILE) || die "Error closing file: $!"; + message_dialog("Current configuration \"$name\" is saved as $config_file."); }); $entry->signal_connect( 'changed'=> sub{ - my $name=$entry->get_text(); - $self->object_add_attribute ("save_as",undef,$name); - }); + my $name=$entry->get_text(); + $self->object_add_attribute ("save_as",undef,$name); + }); $load-> signal_connect("clicked" => sub{ set_gui_status($self,"ref",5); @@ -3301,7 +3314,7 @@ sub mpsocgen_main{ my $ctrl=ctrl_box($mpsoc,$info); my $h1=gen_hpaned($noc_conf_box,.3,$noc_tiles); my $v2=gen_vpaned($h1,.55,$infobox); - my $row=0; + my $row=0; $main_table->attach_defaults ($v2 , 0, 12, 0,24); #$main_table->attach_defaults ($ctrl,0, 12, 24,25); $main_table->attach ($ctrl,0, 12, 24,25, 'fill','fill',2,2); @@ -3349,4 +3362,4 @@ sub mpsocgen_main{ return $sc_win; } - +1 diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl index b025947..849c078 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl @@ -325,6 +325,9 @@ sub gen_noc_param_v{ my $custom_topology = $mpsoc->object_get_attribute($noc_param,'CUSTOM_TOPOLOGY_NAME'); my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); my %noc_info; + my $hashref= $mpsoc->object_get_attribute('noc_param_comments'); + my %comments = %{$hashref} if defined $hashref; + if(defined $sample ){ my $ref=$mpsoc->object_get_attribute($sample,"noc_info"); %noc_info= %$ref; @@ -340,7 +343,13 @@ sub gen_noc_param_v{ $val="$NE".$val; } + $param_v= $param_v."\tlocalparam $p=$val;\n"; + my $comment=$comments{$p}; + if(defined $comment){ + $comment=~ s/\n/\n \/\//g; + $param_v.=" //$p : $comment\n\n"; + } $pass_param=$pass_param."\t\t.$p($p),\n"; #print "$p:$val\n"; From ce71e77bb8da4a242220ebb7069bb993c45b8426 Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 29 Jan 2025 11:22:28 +0100 Subject: [PATCH 002/107] add hetro_vc setting to gui --- .../Integration_test/synthetic_sim/src/src.pl | 5 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 181 ++++++++++++++---- mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl | 1 + mpsoc/perl_gui/lib/perl/topology.pl | 31 +-- mpsoc/rtl/src_noc/noc_localparam.v | 116 ++++++++++- 5 files changed, 283 insertions(+), 51 deletions(-) diff --git a/mpsoc/Integration_test/synthetic_sim/src/src.pl b/mpsoc/Integration_test/synthetic_sim/src/src.pl index ae2cce9..70cef1b 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/src.pl +++ b/mpsoc/Integration_test/synthetic_sim/src/src.pl @@ -83,6 +83,7 @@ sub gen_noc_param_h{ foreach my $p (@params){ my $val=$mpsoc->object_get_attribute('noc_param',$p); next if($p eq "CUSTOM_TOPOLOGY_NAME"); + next if($p eq "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"); $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); if($p eq "MCAST_ENDP_LIST" || $p eq "ESCAP_VC_MASK"){ $val="$NE".$val if($p eq 'MCAST_ENDP_LIST'); @@ -94,8 +95,8 @@ sub gen_noc_param_h{ #print "$p:$val\n"; } - - + + my $v=$mpsoc->object_get_attribute('noc_param',"V")-1; my $escape=$mpsoc->object_get_attribute('noc_param',"ESCAP_VC_MASK"); if (! defined $escape){ diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index b82ffde..e21d47c 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -820,7 +820,7 @@ sub noc_config{ ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); my $cast_type=$mpsoc->object_get_attribute($noc_param,'CAST_TYPE'); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); + my ($NE, $NR, $RAw, $EAw, $Fw, $MAX_P) = get_topology_info($mpsoc,$noc_id); my $cast = $mpsoc->object_get_attribute($noc_param,"MCAST_ENDP_LIST"); if(!defined $cast){ @@ -1071,7 +1071,59 @@ sub noc_config{ $type= 'Spin-button'; #($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,$wrra_show,$noc_param,undef); - + #HETRO_VC + $label='Heterogeneous VC En'; + $param='HETRO_VC'; + $default='0'; + $content='0,1,2'; + $type='Combo-box'; + $info="Configures the VC (Virtual Channel) distribution across routers and ports in the NoC. + 0 : Uniform VC distribution. All routers in the NoC have an equal number of VCs. + 1 : Router-specific VC distribution. All ports in a specific router have the same number of VCs, + but different routers in the NoC can have different numbers of VCs. + 2 : Fully heterogeneous VC distribution. Each port in any router can have a unique number of VCs."; + $noc_param_comment{$param}="$info"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,1); + $noc_param_comment{$param}="$info"; + + + #VC_CONFIG_TABLE + my $hetro_en=$mpsoc->object_get_attribute($noc_param,'HETRO_VC'); + $label='Heterogeneous VC setting'; + $param='int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]'; + $default='\'{0}'; + $content='0,1,2'; + $type='Combo-box'; + $info='Defines how a heterogeneous number of VCs are distributed in the NoC. + - HETRO_VC= 0: Uniform VC configuration. All routers and ports have + the same number of VCs, and this parameter is not used. + - HETRO_VC= 1,2 : Specifies the VC count in a 2D parameter array, where: + * The first dimension represents the router ID. + * The second dimension represents the port number. + - For HETRO_VC = 1: All ports within a router have the same number of VCs, + so only the first element of each row is considered valid. + - For HETRO_VC = 2: Each port in every router can have a unique VC count.'; + $noc_param_comment{$param}="$info"; + if($hetro_en eq '0'){ + $mpsoc->object_add_attribute($noc_param,"MAX_ROUTER",1); + $mpsoc->object_add_attribute($noc_param,"MAX_PORT",1); + $mpsoc->object_add_attribute($noc_param,$param,$default); + + }elsif($hetro_en eq '1'){ + $mpsoc->object_add_attribute($noc_param,"MAX_ROUTER",$NR); + $mpsoc->object_add_attribute($noc_param,"MAX_PORT",1); + $row=hetro_vc_widget($mpsoc,$row,$NR,1,$label,$info,$table,$noc_id,$param,$v); + }else{ + $mpsoc->object_add_attribute($noc_param,"MAX_ROUTER",$NR); + $mpsoc->object_add_attribute($noc_param,"MAX_PORT",$MAX_P); + $row=hetro_vc_widget($mpsoc,$row,$NR,$MAX_P,$label,$info,$table,$noc_id,$param,$v); + } + + + $mpsoc->object_add_attribute_order($noc_param,"MAX_ROUTER"); + $mpsoc->object_add_attribute_order($noc_param,"MAX_PORT"); + $mpsoc->object_add_attribute_order($noc_param,$param); + if($show_noc == 1){ $b1= def_image_button("icons/up.png","NoC Parameters"); $table->attach ( $b1 , 0, 2, $row,$row+1,'fill','shrink',2,2); @@ -1083,21 +1135,7 @@ sub noc_config{ set_gui_status($mpsoc,"ref",1); }); - - - - # if($adv_set == 1){ - # $advc= def_image_button("icons/up.png","Advance Parameters"); - # $table->attach ( $advc , 0, 2, $row,$row+1,'fill','shrink',2,2); - # $row++; - # } - # $advc->signal_connect("clicked" => sub{ - # $adv_set=($adv_set==1)?0:1; - # $mpsoc->object_add_attribute('setting','show_adv_setting',$adv_set); - # set_gui_status($mpsoc,"ref",1); - # }); - - + #other fixed parameters # AVC_ATOMIC_EN @@ -1111,21 +1149,98 @@ sub noc_config{ ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param); - #ROUTE_SUBFUNC - #$label='ROUTE_SUBFUNC'; - #$param='ROUTE_SUBFUNC'; - #$default= '"XY"'; - #$info='ROUTE_SUBFUNC'; - #$content='"XY"'; - #$type="Combo-box"; - #($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param); $mpsoc->object_add_attribute('noc_param_comments',undef,\%noc_param_comment); return $row; } +sub hetro_vc_widget{ + my ($mpsoc,$row,$nr,$np,$label_text,$info,$table,$noc_id,$param,$v)=@_; + my $b1= def_image_button("icons/setting.png","Set"); + my $label=gen_label_in_left($label_text); + my $inf_bt= (defined $info)? gen_button_message ($info,"icons/help.png"):gen_label_in_left(" "); + attach_widget_to_table ($table,$row,$label,$inf_bt,$b1,0); + $row++; + update_vc_list($mpsoc,$noc_id,$nr,$np,$v,$param,$info); + $b1->signal_connect("clicked" => sub{ + set_hetro_vc_list($mpsoc,$noc_id,$nr,$np,$param,$v,$info); + }); + return $row; +} + +sub set_hetro_vc_list{ + my($mpsoc,$noc_id,$nr,$np,$param,$v,$info)=@_; + my $noc_param="noc_param$noc_id"; + my $vc_param="vc_param$noc_id"; + my $title=($np==1)? "Specify number of VCs in each router" : "Specify number of VCs in each router port"; + my $window = def_popwin_size(50,40,$title,'percent'); + my $table= def_table(10,10,FALSE); + my $row=0; + my $col=0; + my $init = $mpsoc->object_get_attribute($noc_param,$param); + my $label = "$param="; + my ($Ebox,$entry) = def_h_labeled_entry ($label); + $entry->set_sensitive (FALSE); + $entry->set_text("$init"); + my $content="1"; + for(my $r=2;$r<=$v;$r++){ $content.=",$r" } + for(my $p=0;$p<$np;$p++){ + if ($p==0){ + my $label= gen_label_in_center("R/P"); + $table->attach ($label , $col, $col+4, $row,$row+1,'fill','shrink',2,2);$col+=4; + } + my $label= gen_label_in_center("P$p"); + $table->attach ($label , $col, $col+4, $row,$row+1,'fill','shrink',2,2);$col+=4; + } + $row++;$col=0; + for(my $r=0;$r<$nr;$r++){ + my $label= gen_label_in_center("R$r"); + $table->attach ($label , $col, $col+4, $row,$row+1,'fill','shrink',2,2);$col+=4; + + for(my $p=0;$p<$np;$p++){ + my $w; + ($row,$col,$w)=add_param_widget ($mpsoc,undef,"R$r-P$p", $v,"Combo-box",$content,undef, $table,$row,$col,1,$vc_param,undef,undef,"horizental"); + set_tip($w,"R$r-P$p"); + } + $row++; + $col=0; + } + #$table->attach ($Ebox , $row, 10, $row,$row+1,'fill','shrink',2,2);$row++; + + my $main_table=def_table(10,10,FALSE); + my $ok = def_image_button('icons/select.png','OK'); + $main_table->attach_defaults ($table , 0, 12, 0,11); + $main_table->attach ($ok,5, 6, 11,12,'shrink','shrink',0,0); + $ok->signal_connect('clicked', sub { + update_vc_list($mpsoc,$noc_id,$nr,$np,$v,$param,$info); + set_gui_status($mpsoc,"ref",1); + $window->destroy; + }); + my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_multicast'); + add_widget_to_scrolled_win($main_table,$scrolled_win); + $window->add($scrolled_win); + $window->show_all(); +} +sub update_vc_list{ + my ($mpsoc,$noc_id,$nr,$np,$v,$param_in)=@_; + my $noc_param="noc_param$noc_id"; + my $vc_param="vc_param$noc_id"; + my $out="'{\n\t//"; + for(my $p=0;$p<$np;$p++){$out.="P$p ";}; + for(my $r=0;$r<$nr;$r++){ + $out.="\n\t\'{"; + for(my $p=0;$p<$np;$p++){ + my $param ="R$r-P$p"; + my $val=$mpsoc->object_get_attribute($vc_param,$param) //$v; + $out.=($p <$np-1 )? "$val, " : "$val"; + } + $out.=($r<$nr-1)? "}, // R$r" : "} // R$r" + } + $out.="\n\t}"; + $mpsoc->object_add_attribute($noc_param,$param_in,$out) +} sub set_multicast_list{ my($mpsoc,$noc_id)=@_; @@ -1205,14 +1320,14 @@ sub set_multicast_list{ $combo->set_active(0); get_multicast_val ($mpsoc,$entry,$NE,@check); - }); + }); $table->attach ($Ebox , 0, 10, $row,$row+1,'fill','shrink',2,2);$row++; my $main_table=def_table(10,10,FALSE); - + my $ok = def_image_button('icons/select.png','OK'); $main_table->attach_defaults ($table , 0, 12, 0,11); $main_table->attach ($ok,5, 6, 11,12,'shrink','shrink',0,0); @@ -1267,15 +1382,15 @@ sub config_custom_topology_gui{ my $dir =get_project_dir()."/mpsoc/rtl/src_topology"; my $file="$dir/param.obj"; unless (-f $file){ - add_colored_info($txview,"No Custom topology find in $dir. You can define a Custom Topology using ProNoC Topology maker.\n",'red'); - return; + add_colored_info($txview,"No Custom topology find in $dir. You can define a Custom Topology using ProNoC Topology maker.\n",'red'); + return; } my %param; my ($pp,$r,$err) = regen_object($file ); if ($r){ - add_colored_info($txview,"Error: cannot open $file file: $err\n",'red'); - return; + add_colored_info($txview,"Error: cannot open $file file: $err\n",'red'); + return; } %param=%{$pp}; @@ -1300,11 +1415,11 @@ sub config_custom_topology_gui{ $default=$rr[0]; $info="Select the routing algorithm"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,1,$noc_param,1); - + $mpsoc->object_add_attribute($noc_param,'T1',$param{$topology_name}{'T1'}); $mpsoc->object_add_attribute($noc_param,'T2',$param{$topology_name}{'T2'}); $mpsoc->object_add_attribute($noc_param,'T3',$param{$topology_name}{'T3'}); - $mpsoc->object_add_attribute('noc_connection','er_addr',$param{$topology_name}{'er_addr'}); + $mpsoc->object_add_attribute('noc_connection','er_addr',$param{$topology_name}{'er_addr'}); return ($row,$coltmp); diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl index 849c078..75e8e93 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl @@ -402,6 +402,7 @@ sub gen_noc_param_h{ foreach my $p (@params){ my $val=$mpsoc->object_get_attribute('noc_param',$p); next if($p eq "CUSTOM_TOPOLOGY_NAME"); + next if($p eq "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"); $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); if($p eq "MCAST_ENDP_LIST" || $p eq "ESCAP_VC_MASK"){ $val="$NE".$val if($p eq 'MCAST_ENDP_LIST'); diff --git a/mpsoc/perl_gui/lib/perl/topology.pl b/mpsoc/perl_gui/lib/perl/topology.pl index 69906ab..5535f17 100644 --- a/mpsoc/perl_gui/lib/perl/topology.pl +++ b/mpsoc/perl_gui/lib/perl/topology.pl @@ -34,7 +34,6 @@ sub get_topology_info_from_parameters { my $T3 =$param{'T3'}; my $V =$param{'V'}; my $Fpay=$param{'Fpay'}; - print "lllllllllllllll\n"; return get_topology_info_sub($topology, $T1, $T2, $T3,$V, $Fpay); } @@ -44,11 +43,11 @@ 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 $NE; # Total number of end points (local ports) in the NoC + my $NR; # Total number of routers in NoC + my $RAw; # Routers address width + my $EAw; # Endpoints address width + my $MAX_P; # Maximum number of ports in any router in the NoC my $Fw = 2+$V+$Fpay; if($topology eq '"TREE"') { @@ -60,7 +59,8 @@ sub get_topology_info_sub { my $LKw=$L*$Kw; my $Lw=log2($L); $RAw=$LKw + $Lw; - $EAw = $LKw; + $EAw = $LKw; + $MAX_P = $K + 1; }elsif($topology eq '"FATTREE"') { my $K = $T1; @@ -72,6 +72,7 @@ sub get_topology_info_sub { my $Lw=log2($L); $RAw=$LKw + $Lw; $EAw = $LKw; + $MAX_P = 2 * $K; }elsif ($topology eq '"RING"' || $topology eq '"LINE"'){ my $NX=$T1; @@ -83,8 +84,9 @@ sub get_topology_info_sub { my $Yw=log2($NY); my $Lw=log2($NL); $RAw = $Xw; - $EAw = ($NL==1) ? $RAw : $RAw + $Lw; - + $EAw = ($NL==1) ? $RAw : $RAw + $Lw; + $MAX_P = 2 + $NL; + }elsif ($topology eq '"MESH"' || $topology eq '"TORUS"' ) { my $NX=$T1; my $NY=$T2; @@ -96,6 +98,8 @@ sub get_topology_info_sub { my $Lw=log2($NL); $RAw = $Xw + $Yw; $EAw = ($NL==1) ? $RAw : $RAw + $Lw; + $MAX_P = 4 + $NL; + }elsif ($topology eq '"FMESH"'){ my $NX=$T1; my $NY=$T2; @@ -106,21 +110,24 @@ sub get_topology_info_sub { my $Yw=log2($NY); my $Lw=log2($NL); $RAw = $Xw + $Yw; - $EAw = $RAw + log2(4+$NL); + $EAw = $RAw + log2(4+$NL); + $MAX_P = 4 + $NL; }elsif ($topology eq '"STAR"' ) { $NE= $T1; $NR= 1; $RAw=log2($NR); - $EAw=log2($NE); + $EAw=log2($NE); + $MAX_P = $NE; }else{ #custom $NE= $T1; $NR= $T2; $RAw=log2($NR); $EAw=log2($NE); + $MAX_P = $T3; } - return ($NE, $NR, $RAw, $EAw, $Fw); + return ($NE, $NR, $RAw, $EAw, $Fw,$MAX_P); } diff --git a/mpsoc/rtl/src_noc/noc_localparam.v b/mpsoc/rtl/src_noc/noc_localparam.v index 73208db..3c7d5d9 100644 --- a/mpsoc/rtl/src_noc/noc_localparam.v +++ b/mpsoc/rtl/src_noc/noc_localparam.v @@ -8,9 +8,9 @@ /********************************************************************** ** File: noc_localparam.v ** -** Copyright (C) 2014-2021 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.1.0 +** This file is part of ProNoC 2.2.0 ** ** ProNoC ( stands for Prototype Network-on-chip) is free software: ** you can redistribute it and/or modify it under the terms of the GNU @@ -32,42 +32,150 @@ -//NoC localparams +//NoC parameters localparam TOPOLOGY="MESH"; + //TOPOLOGY : Specifies the NoC topology. + // Options include "MESH","FMESH","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM" + localparam T1=4; + //T1 : Number of NoC routers in row (X dimension) + localparam T2=4; + //T2 : Number of NoC routers in column (Y dimension) + localparam T3=2; + //T3 : Number of endpoints per router. In "MESH" topology, each router + // can have up to 4 endpoint processing tile. + localparam V=2; + //V : Number of Virtual chanel per each router port + localparam B=4; + //B : Buffer queue size per VC in flits + localparam LB=7; + //LB : Buffer width for local router ports connected to endpoints. + // May differ from B, which is for neighboring router ports. + // Applicable to MESH, FMESH, TORUS, LINE, and RING topologies. + // In FMESH, LB does not affect extra endpoints on edge routers. + localparam Fpay=32; + //Fpay : The packet payload width in bits + localparam ROUTE_NAME="XY"; + //ROUTE_NAME : Select the routing algorithm: XY(DoR) , partially adaptive (Turn models). Fully adaptive (Duato) + // options are "XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN","DUATO" + localparam PCK_TYPE="MULTI_FLIT"; + //PCK_TYPE : Packet type. + // - SINGLE_FLIT: All packets are single-flit sized. + // - MULTI_FLIT: Packets can be single-flit, two-flit, or multi-flit sized: + // a) Single-flit: Head and tail flags set on one flit. + // b) Two-flit: Separate header and tail flits. + // c) Multi-flit: Header, one or more body flits, and a tail flit. + localparam MIN_PCK_SIZE=2; + //MIN_PCK_SIZE : Minimum packet size in flits. + // - For atomic VC reallocation, any value ≥1 is valid. + // - For non-atomic VC reallocation, this value defines buffer behavior. + // Note: Setting a value smaller than received packet size may cause crashes. + localparam BYTE_EN=0; + //BYTE_EN : 0 - Disable, 1 - Enable. + // Adds a Byte Enable (BE) field to the header flit, indicating the location of + // the last valid byte in the tail flit. This is required when the data unit being + // sent is smaller than the Fpay value. + localparam CAST_TYPE="UNICAST"; + //CAST_TYPE : Specifies NoC communication type. + // - UNICAST: A packet targets a single destination. + // - MULTICAST/BROADCAST: A single packet targets multiple/all destinations. + // Options: FULL (all nodes) or PARTIAL (defined by MCAST_ENDP_LIST). + // Select one of "UNICAST","MULTICAST_PARTIAL","MULTICAST_FULL","BROADCAST_PARTIAL","BROADCAST_FULL" + localparam MCAST_ENDP_LIST=32'hf; localparam SSA_EN="NO"; + //SSA_EN : Enable single cycle latency on packets traversing in the same direction using + // static straight allocator (SSA) + localparam SMART_MAX=0; + //SMART_MAX : Maximum number of routers a packet can bypass in a straight direction + // in a single cycle (0 = no bypass) + localparam CONGESTION_INDEX=3; + //CONGESTION_INDEX : Congestion index determines how congestion information is collected + // from neighboring routers. Please refer to the usere manual for more information + localparam ESCAP_VC_MASK=2'b01; + //ESCAP_VC_MASK : Select the escap VC for fully adaptive routing. + localparam VC_REALLOCATION_TYPE="NONATOMIC"; + //VC_REALLOCATION_TYPE : VC reallocation policy. + // - ATOMIC: Only empty VCs can be reallocated. + // - NONATOMIC: Non-empty VCs with completed packets can accept new packets. + localparam COMBINATION_TYPE="COMB_NONSPEC"; + //COMBINATION_TYPE : Specifies the joint VC/Switch allocator type as either speculative or non-speculative. + //Options are: + // - SPEC: Speculative allocation. + // - NONSPEC: Non-speculative allocation. + localparam MUX_TYPE="BINARY"; + //MUX_TYPE : Crossbar multiplexer type + localparam C=0; localparam DEBUG_EN=0; + //DEBUG_EN : Add extra Verilog code for debugging NoC for simulation + localparam ADD_PIPREG_AFTER_CROSSBAR=1'b0; + //ADD_PIPREG_AFTER_CROSSBAR : If is enabled it adds a pipeline register at the output port of the router. + localparam FIRST_ARBITER_EXT_P_EN=1; + //FIRST_ARBITER_EXT_P_EN : Enables switch allocator's input priority registers + // only when a request gets grants from both input and output arbiters. + localparam SWA_ARBITER_TYPE="RRA"; + //SWA_ARBITER_TYPE : Switch allocator arbitration type. + // - RRA: Round Robin Arbiter (local fairness only). + // - WRRA: Weighted Round Robin Arbiter (global fairness based on contention). + // + localparam WEIGHTw=4; + //WEIGHTw : Maximum weight width + localparam SELF_LOOP_EN="NO"; + //SELF_LOOP_EN : Allows a router input port to send packets to its own output port, + // enabling self-communication for tiles. + + localparam HETRO_VC=0; + //HETRO_VC : Configures the VC (Virtual Channel) distribution across routers and ports in the NoC. + // 0 : Uniform VC distribution. All routers in the NoC have an equal number of VCs. + // 1 : Router-specific VC distribution. All ports in a specific router have the same number of VCs, + // but different routers in the NoC can have different numbers of VCs. + // 2 : Fully heterogeneous VC distribution. Each port in any router can have a unique number of VCs. + + localparam MAX_ROUTER=1; + localparam MAX_PORT=1; + localparam int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]='{0}; + //int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT] : Defines how a heterogeneous number of VCs are distributed in the NoC. + // - HETRO_VC= 0: Uniform VC configuration. All routers and ports have + // the same number of VCs, and this parameter is not used. + // - HETRO_VC= 1,2 : Specifies the VC count in a 2D parameter array, where: + // * The first dimension represents the router ID. + // * The second dimension represents the port number. + // - For HETRO_VC = 1: All ports within a router have the same number of VCs, + // so only the first element of each row is considered valid. + // - For HETRO_VC = 2: Each port in every router can have a unique VC count. + localparam AVC_ATOMIC_EN=0; + //AVC_ATOMIC_EN : AVC_ATOMIC_EN + localparam CLASS_SETTING={V{1'b1}}; localparam CVw=(C==0)? V : C * V; - //simulation localparam + //simulation parameter //localparam MAX_RATIO = 1000; localparam MAX_PCK_NUM = 1000000000; localparam MAX_PCK_SIZ = 16383; From ede8b20723ad491bec8302c0ef6aef621ada447e Mon Sep 17 00:00:00 2001 From: amonemi Date: Fri, 31 Jan 2025 22:56:56 +0100 Subject: [PATCH 003/107] add SIMULATION macro --- .../synthetic_sim/reports/default_report | 126 - mpsoc/rtl/pronoc_def.v | 160 +- mpsoc/rtl/src_noc/inout_ports.sv | 803 +++-- mpsoc/rtl/src_noc/input_ports.sv | 2584 ++++++++--------- mpsoc/rtl/src_noc/router_top.sv | 892 +++--- mpsoc/rtl/src_noc/router_two_stage.sv | 1317 ++++----- 6 files changed, 2728 insertions(+), 3154 deletions(-) diff --git a/mpsoc/Integration_test/synthetic_sim/reports/default_report b/mpsoc/Integration_test/synthetic_sim/reports/default_report index 606a952..72e7467 100644 --- a/mpsoc/Integration_test/synthetic_sim/reports/default_report +++ b/mpsoc/Integration_test/synthetic_sim/reports/default_report @@ -1,133 +1,7 @@ Verification Results: -****************************bintree_k3_L3_st : Compile *******************************: - model is generated successfully. -****************************custom1_topology : Compile *******************************: - model is generated successfully. -****************************Fattree_k3_L3_st : Compile *******************************: - model is generated successfully. -****************************fmesh_1x1_openpiton : Compile *******************************: - model is generated successfully. -****************************fmesh_2x2_openpiton : Compile *******************************: - model is generated successfully. -****************************fmesh_8x8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************fmesh_8x8_openpiton : Compile *******************************: - model is generated successfully. -****************************mesh_2x2_openpiton : Compile *******************************: - model is generated successfully. ****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: model is generated successfully. -****************************mesh_4x4_smart3 : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_v1_B15 : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x3_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_2cycle_adaptive : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_2cycle_west_first : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_4vc_4c : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_b2 : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_sbp6_xy : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_single_flit : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_ssa_xy : Compile *******************************: - model is generated successfully. -****************************star_6 : Compile *******************************: - model is generated successfully. -****************************torus_8x8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************bintree_k3_L3_st : random traffic *******************************: - Passed: zero load (2,14.5705) saturation (14,400.884) -****************************custom1_topology : random traffic *******************************: - Passed: zero load (2,13.0626) saturation (42,65.4283) -****************************Fattree_k3_L3_st : random traffic *******************************: - Passed: zero load (2,13.5991) saturation (62,98.8008) -****************************fmesh_1x1_openpiton : random traffic *******************************: - Passed: zero load (2,7.06202) saturation (66,51.0968) -****************************fmesh_2x2_openpiton : random traffic *******************************: - Passed: zero load (2,8.27536) saturation (54,67.4686) -****************************fmesh_8x8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,19.5638) saturation (18,137.798) -****************************fmesh_8x8_openpiton : random traffic *******************************: - Passed: zero load (2,14.4245) saturation (30,98.3569) -****************************mesh_2x2_openpiton : random traffic *******************************: - Passed: zero load (2,9.10156) saturation (66,72.3384) ****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: Passed: zero load (2,14.4623) saturation (22,261.684) -****************************mesh_4x4_smart3 : random traffic *******************************: - Passed: zero load (2,10.1271) saturation (42,72.4117) -****************************mesh_4x4_v1_B15 : random traffic *******************************: - Passed: zero load (6,12.719) saturation (58,93.2747) -****************************mesh_4x4x3_2cycle_xy : random traffic *******************************: - Passed: zero load (2,12.7475) saturation (26,188.161) -****************************mesh_8x8_2cycle_adaptive : random traffic *******************************: - Passed: zero load (2,18.2154) saturation (34,186.128) -****************************mesh_8x8_2cycle_west_first : random traffic *******************************: - Passed: zero load (2,18.2239) saturation (34,154.392) -****************************mesh_8x8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,18.2211) saturation (34,132.962) -****************************mesh_8x8_4vc_4c : random traffic *******************************: - Passed: zero load (2,18.0557) saturation (26,162.893) -****************************mesh_8x8_b2 : random traffic *******************************: - Passed: zero load (2,22.1073) saturation (30,198.439) -****************************mesh_8x8_sbp6_xy : random traffic *******************************: - Passed: zero load (2,11.1597) saturation (34,119.674) -****************************mesh_8x8_single_flit : random traffic *******************************: - Passed: zero load (2,12.7369) saturation (58,65.8427) -****************************mesh_8x8_ssa_xy : random traffic *******************************: - Passed: zero load (2,14.769) saturation (34,111.6) -****************************star_6 : random traffic *******************************: - Passed: zero load (2,7.27692) saturation (62,57.3078) -****************************torus_8x8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,16.8517) saturation (38,120.208) -****************************bintree_k3_L3_st : transposed 1 traffic *******************************: - Passed: zero load (2,14.5436) saturation (14,430.149) -****************************custom1_topology : transposed 1 traffic *******************************: - Passed: zero load (2,12.6827) saturation (34,68.3986) -****************************Fattree_k3_L3_st : transposed 1 traffic *******************************: - Passed: zero load (26,13.4638) saturation (100,-) -****************************fmesh_1x1_openpiton : transposed 1 traffic *******************************: - Passed: zero load (46,6.99433) saturation (100,-) -****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,8.99642) saturation (54,71.4902) -****************************fmesh_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,21.6193) saturation (14,142.818) -****************************fmesh_8x8_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,15.916) saturation (26,118.048) -****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,8.7482) saturation (100,-) ****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: Passed: zero load (2,14.8953) saturation (26,146.747) -****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: - Passed: zero load (2,10.5055) saturation (34,60.2796) -****************************mesh_4x4_v1_B15 : transposed 1 traffic *******************************: - Passed: zero load (2,13.6902) saturation (38,106.686) -****************************mesh_4x4x3_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,13.0755) saturation (14,126.234) -****************************mesh_8x8_2cycle_adaptive : transposed 1 traffic *******************************: - Passed: zero load (2,19.3604) saturation (26,108.443) -****************************mesh_8x8_2cycle_west_first : transposed 1 traffic *******************************: - Passed: zero load (2,19.3588) saturation (22,102.056) -****************************mesh_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,19.3582) saturation (18,124.569) -****************************mesh_8x8_4vc_4c : transposed 1 traffic *******************************: - Passed: zero load (2,19.2371) saturation (18,114.964) -****************************mesh_8x8_b2 : transposed 1 traffic *******************************: - Passed: zero load (2,23.5649) saturation (18,118.423) -****************************mesh_8x8_sbp6_xy : transposed 1 traffic *******************************: - Passed: zero load (2,11.3748) saturation (18,119.786) -****************************mesh_8x8_single_flit : transposed 1 traffic *******************************: - Passed: zero load (2,14.0386) saturation (26,70.9042) -****************************mesh_8x8_ssa_xy : transposed 1 traffic *******************************: - Passed: zero load (2,15.3919) saturation (18,123.223) -****************************star_6 : transposed 1 traffic *******************************: - Passed: zero load (2,6.83981) saturation (100,-) -****************************torus_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,18.0133) saturation (18,134.597) diff --git a/mpsoc/rtl/pronoc_def.v b/mpsoc/rtl/pronoc_def.v index 0b344ff..06d6984 100644 --- a/mpsoc/rtl/pronoc_def.v +++ b/mpsoc/rtl/pronoc_def.v @@ -1,74 +1,96 @@ `ifndef PRONOC_DEF `define PRONOC_DEF - - `timescale 1ns/1ps - - //`define SYNC_RESET_MODE /* Reset is asynchronous by default. Uncomment this line for having synchronous reset*/ - //`define ACTIVE_LOW_RESET_MODE /* Reset is active high by deafult. Uncomment this line for having active low reset*/ - - - `define IMPORT_PRONOC_PCK - /* pronoc.sv is imported by default. Inorder to support Multiple physical NoCs with different - you need to compile each NoC as a separate library (passing USE_LIB in compilationtime). - Comment IMPORT_PRONOC_PCK macro to include pronoc_pck.sv as a file instead of importing. - Including pronoc.sv allows having Multiple physical NoCs with different configurations - where configuration can be set via parameter redefinition at NoC_Top module */ - - - - `ifdef SYNC_RESET_MODE - `define pronoc_clk_reset_edge posedge clk - `else - `ifdef ACTIVE_LOW_RESET_MODE - `define pronoc_clk_reset_edge posedge clk or negedge reset - `else - `define pronoc_clk_reset_edge posedge clk or posedge reset - `endif - `endif - - - - - `ifdef ACTIVE_LOW_RESET_MODE - `define pronoc_reset !reset - `else - `define pronoc_reset reset - `endif - - - + + // Reset Configurations + // `define SYNC_RESET_MODE + /* + * Reset is asynchronous by default. + * Uncomment this line to enable synchronous reset. + */ + + // `define ACTIVE_LOW_RESET_MODE + /* + * Reset is active-high by default. + * Uncomment this line to enable an active-low reset. + */ + + // ProNoC Package Import + `define IMPORT_PRONOC_PCK + /* + * `pronoc_pkg.sv` is imported by default. + * Commenting out this macro includes all parameters, + * functions, and structs directly from `pronoc_pkg.sv`. + */ + + /****************** + * Define SIMULATION for supported RTL simulators + *******************/ + + `ifdef VERILATOR + `define SIMULATION + `endif + + `ifdef MODEL_TECH // ModelSim/Questa + `define SIMULATION + `endif + + `ifdef VCS // Synopsys VCS + `define SIMULATION + `endif + + `ifdef XCELIUM // Cadence Xcelium + `define SIMULATION + `endif + + `ifdef RIVIERA // Aldec Riviera-PRO + `define SIMULATION + `endif + + `ifdef SIMULATION + `timescale 1ns/1ps + `endif + + /**************** + * Enable TRACE Dump + ****************/ + + `ifdef SIMULATION + // Uncomment the following defines to enable TRACE dumping + // `define TRACE_DUMP_PER_NoC // Dump all in/out traces of the NoC into a single file + // `define TRACE_DUMP_PER_ROUTER // Dump in/out traces of each router into a separate file + // `define TRACE_DUMP_PER_PORT // Dump in/out traces of each router port into a separate file + `endif + + // Clock and Reset Edge Definitions + `ifdef SYNC_RESET_MODE + `define pronoc_clk_reset_edge posedge clk + `else + `ifdef ACTIVE_LOW_RESET_MODE + `define pronoc_clk_reset_edge posedge clk or negedge reset + `else + `define pronoc_clk_reset_edge posedge clk or posedge reset + `endif + `endif + + // Reset Signal Definition + `ifdef ACTIVE_LOW_RESET_MODE + `define pronoc_reset !reset + `else + `define pronoc_reset reset + `endif + + // Library Usage `ifdef USE_LIB - `uselib lib=`USE_LIB + `uselib lib=`USE_LIB `endif - - - `ifdef IMPORT_PRONOC_PCK - `define NOC_CONF import pronoc_pkg::*; - `define PRONOC_PKG - `else - `define NOC_CONF `define PRONOC_PKG \ - `include "pronoc_pkg.sv" - `endif - - - - - - -/**************** - TRACE dump -*****************/ - //uncomment following define to enable TRACE dumping - - - // `define TRACE_DUMP_PER_NoC // dump all in/out traces to the NoC in single file - // `define TRACE_DUMP_PER_ROUTER // dump each router in/out traces in a seprate file - // `define TRACE_DUMP_PER_PORT // dump each router port in/out in a single file - - - - - -`endif - + // NoC Configuration + `ifdef IMPORT_PRONOC_PCK + `define NOC_CONF import pronoc_pkg::*; + `define PRONOC_PKG + `else + `define NOC_CONF `define PRONOC_PKG \ + `include "pronoc_pkg.sv" + `endif + +`endif // PRONOC_DEF diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index 1ff14e6..9367275 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -1,39 +1,40 @@ `include "pronoc_def.v" /********************************************************************** -** File: inout_ports.v +** File: inout_ports.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** NoC router Input/output module +** Description: +** NoC router Input/output module ** **************************************************************/ module inout_ports #( parameter NOC_ID=0, + parameter ROUTER_ID=0, parameter P=5 -) ( +)( current_r_addr, neighbors_r_addr, clk, reset, - + // to/from neighboring router flit_in_all, flit_in_wr_all, @@ -75,7 +76,7 @@ module inout_ports #( oports_weight_all, refresh_w_counter, crossbar_flit_out_wr_all, - + // status vsa_credit_decreased_all, vsa_ovc_released_all, @@ -85,9 +86,9 @@ module inout_ports #( vsa_ctrl_in, smart_ctrl_in ); - - `NOC_CONF - + + `NOC_CONF + localparam PV = V * P, PVV = PV * V, @@ -101,12 +102,10 @@ module inout_ports #( WPP = WP * P, PVDSTPw= PV * DSTPw, PRAw= P * RAw; - - + input [RAw-1 : 0] current_r_addr; - input [PRAw-1: 0] neighbors_r_addr; - - + input [PRAw-1: 0] neighbors_r_addr; + input [PFw-1 : 0] flit_in_all; input [P-1 : 0] flit_in_wr_all; output[PV-1 : 0] credit_out_all; @@ -114,8 +113,6 @@ module inout_ports #( input [PV-1 : 0] vsa_ovc_allocated_all; input [PVV-1 : 0] granted_ovc_num_all; - - input [PV-1 : 0] ivc_num_getting_ovc_grant; input [PVV-1 : 0] spec_ovc_num_all; input [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; @@ -125,13 +122,12 @@ module inout_ports #( input [PP_1-1 : 0] granted_dest_port_all; input [P-1 : 0] any_ivc_sw_request_granted_all; input [P-1 : 0] any_ovc_granted_in_outport_all; - + input [CONG_ALw-1 : 0] congestion_in_all; output[CONG_ALw-1 : 0] congestion_out_all; output[PV-1 : 0] vc_weight_is_consumed_all; output[P-1 : 0] iport_weight_is_consumed_all; - input [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - + input [P-1 : 0] granted_dst_is_from_a_single_flit_pck; // to vc/sw allocator output [PVP_1-1 : 0] dest_port_all; @@ -140,7 +136,7 @@ module inout_ports #( output [PV-1 : 0] assigned_ovc_not_full_all; output [PVV-1: 0] masked_ovc_request_all; output [PV-1 : 0] flit_is_tail_all; - + // to crossbar output [PFw-1 : 0] flit_out_all; output [P-1 : 0] ssa_flit_wr_all; @@ -148,7 +144,7 @@ module inout_ports #( output [WPP-1:0] oports_weight_all; input refresh_w_counter; input [P-1 : 0] crossbar_flit_out_wr_all; - + input clk,reset; output [PV-1 : 0] vsa_ovc_released_all; @@ -160,9 +156,8 @@ module inout_ports #( input smart_ctrl_t smart_ctrl_in [P-1 : 0]; input vsa_ctrl_t vsa_ctrl_in [P-1 : 0]; input [CRDTw-1 : 0 ] credit_init_val_in [P-1 : 0][V-1 : 0]; - output [CRDTw-1 : 0 ] credit_init_val_out [P-1 : 0][V-1 : 0]; - - + output [CRDTw-1 : 0 ] credit_init_val_out [P-1 : 0][V-1 : 0]; + wire [PPSw-1 : 0] port_pre_sel; wire [PV-1 : 0] swap_port_presel; wire [PV-1 : 0] reset_ivc_all; @@ -174,312 +169,273 @@ module inout_ports #( ssa_ctrl_t ssa_ctrl [P-1 : 0]; - - input_ports #( - .NOC_ID(NOC_ID), + input_ports #( + .NOC_ID(NOC_ID), + .ROUTER_ID(ROUTER_ID), .P(P) - ) the_input_port ( - .current_r_addr (current_r_addr), - .neighbors_r_addr(neighbors_r_addr), - .ivc_num_getting_sw_grant (ivc_num_getting_sw_grant ), - .any_ivc_sw_request_granted_all (any_ivc_sw_request_granted_all), - .flit_in_all (flit_in_all), - .flit_in_wr_all (flit_in_wr_all), - .reset_ivc_all (reset_ivc_all), - .flit_is_tail_all (flit_is_tail_all), - .ivc_request_all (ivc_request_all), - .dest_port_all(dest_port_all), - .flit_out_all (flit_out_all), - .assigned_ovc_not_full_all(assigned_ovc_not_full_all), - .ovc_is_assigned_all(ovc_is_assigned_all), - .sel (sel), - .port_pre_sel(port_pre_sel), - .swap_port_presel(swap_port_presel), - .credit_out_all(credit_out_all), - // .lk_destination_encoded_all (lk_destination_encoded_all), - .nonspec_first_arbiter_granted_ivc_all(nonspec_first_arbiter_granted_ivc_all), - .destport_clear (destport_clear), - .vc_weight_is_consumed_all (vc_weight_is_consumed_all), - .iport_weight_is_consumed_all (iport_weight_is_consumed_all), - .iport_weight_all(iport_weight_all), - .oports_weight_all(oports_weight_all), - .granted_dest_port_all(granted_dest_port_all), - .refresh_w_counter(refresh_w_counter), - .ivc_info(ivc_info), - .smart_ctrl_in(smart_ctrl_in), - .vsa_ctrl_in(vsa_ctrl_in), - .ssa_ctrl_in(ssa_ctrl), - .credit_init_val_out(credit_init_val_out), - .reset (reset), - .clk (clk) - ); - - - output_ports #( + ) the_input_port ( + .current_r_addr (current_r_addr), + .neighbors_r_addr(neighbors_r_addr), + .ivc_num_getting_sw_grant (ivc_num_getting_sw_grant ), + .any_ivc_sw_request_granted_all (any_ivc_sw_request_granted_all), + .flit_in_all (flit_in_all), + .flit_in_wr_all (flit_in_wr_all), + .reset_ivc_all (reset_ivc_all), + .flit_is_tail_all (flit_is_tail_all), + .ivc_request_all (ivc_request_all), + .dest_port_all(dest_port_all), + .flit_out_all (flit_out_all), + .assigned_ovc_not_full_all(assigned_ovc_not_full_all), + .ovc_is_assigned_all(ovc_is_assigned_all), + .sel (sel), + .port_pre_sel(port_pre_sel), + .swap_port_presel(swap_port_presel), + .credit_out_all(credit_out_all), + // .lk_destination_encoded_all (lk_destination_encoded_all), + .nonspec_first_arbiter_granted_ivc_all(nonspec_first_arbiter_granted_ivc_all), + .destport_clear (destport_clear), + .vc_weight_is_consumed_all (vc_weight_is_consumed_all), + .iport_weight_is_consumed_all (iport_weight_is_consumed_all), + .iport_weight_all(iport_weight_all), + .oports_weight_all(oports_weight_all), + .granted_dest_port_all(granted_dest_port_all), + .refresh_w_counter(refresh_w_counter), + .ivc_info(ivc_info), + .smart_ctrl_in(smart_ctrl_in), + .vsa_ctrl_in(vsa_ctrl_in), + .ssa_ctrl_in(ssa_ctrl), + .credit_init_val_out(credit_init_val_out), + .reset (reset), + .clk (clk) + ); + + output_ports #( .NOC_ID(NOC_ID), - .P (P) - ) output_ports ( - .vsa_ovc_allocated_all (vsa_ovc_allocated_all), - .flit_is_tail_all (flit_is_tail_all), - .dest_port_all (dest_port_all), - .nonspec_granted_dest_port_all (nonspec_granted_dest_port_all), - .credit_in_all (credit_in_all), - .nonspec_first_arbiter_granted_ivc_all (nonspec_first_arbiter_granted_ivc_all), - .ivc_num_getting_sw_grant (ivc_num_getting_sw_grant ), - .ovc_avalable_all (ovc_avalable_all), - .assigned_ovc_not_full_all (assigned_ovc_not_full_all), - .port_pre_sel (port_pre_sel),//only valid for adaptive routing - .congestion_in_all (congestion_in_all),//only valid for adaptive routing - .granted_ovc_num_all (granted_ovc_num_all), - - .granted_dst_is_from_a_single_flit_pck (granted_dst_is_from_a_single_flit_pck), - .reset (reset), - .clk (clk), - .crossbar_flit_out_wr_all (crossbar_flit_out_wr_all), - .any_ovc_granted_in_outport_all ( any_ovc_granted_in_outport_all), - .vsa_ovc_released_all (vsa_ovc_released_all), - .vsa_credit_decreased_all(vsa_credit_decreased_all), - .oport_info (oport_info), - .ivc_info(ivc_info), - .ovc_info (ovc_info), - .smart_ctrl_in(smart_ctrl_in), - .vsa_ctrl_in(vsa_ctrl_in), - .ssa_ctrl_in(ssa_ctrl), - .credit_init_val_in(credit_init_val_in) - ); - - + .P (P) + ) output_ports ( + .vsa_ovc_allocated_all (vsa_ovc_allocated_all), + .flit_is_tail_all (flit_is_tail_all), + .dest_port_all (dest_port_all), + .nonspec_granted_dest_port_all (nonspec_granted_dest_port_all), + .credit_in_all (credit_in_all), + .nonspec_first_arbiter_granted_ivc_all (nonspec_first_arbiter_granted_ivc_all), + .ivc_num_getting_sw_grant (ivc_num_getting_sw_grant ), + .ovc_avalable_all (ovc_avalable_all), + .assigned_ovc_not_full_all (assigned_ovc_not_full_all), + .port_pre_sel (port_pre_sel),//only valid for adaptive routing + .congestion_in_all (congestion_in_all),//only valid for adaptive routing + .granted_ovc_num_all (granted_ovc_num_all), + + .granted_dst_is_from_a_single_flit_pck (granted_dst_is_from_a_single_flit_pck), + .reset (reset), + .clk (clk), + .crossbar_flit_out_wr_all (crossbar_flit_out_wr_all), + .any_ovc_granted_in_outport_all ( any_ovc_granted_in_outport_all), + .vsa_ovc_released_all (vsa_ovc_released_all), + .vsa_credit_decreased_all(vsa_credit_decreased_all), + .oport_info (oport_info), + .ivc_info(ivc_info), + .ovc_info (ovc_info), + .smart_ctrl_in(smart_ctrl_in), + .vsa_ctrl_in(vsa_ctrl_in), + .ssa_ctrl_in(ssa_ctrl), + .credit_init_val_in(credit_init_val_in) + ); + vc_alloc_request_gen #( - .NOC_ID(NOC_ID), - .P(P) + .NOC_ID(NOC_ID), + .P(P) ) vc_alloc_req_gen ( - .ivc_info(ivc_info), - .ovc_avalable_all(ovc_avalable_all), - .dest_port_decoded_all(dest_port_all), - .masked_ovc_request_all(masked_ovc_request_all), - - .port_pre_sel(port_pre_sel), - .swap_port_presel(swap_port_presel), - .sel(sel), - .reset(reset), - .clk(clk), - .destport_clear(destport_clear), - .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant), - //.ssa_ivc_num_getting_ovc_grant_all(nla_ivc_num_getting_ovc_grant_all), - .smart_ctrl_in (smart_ctrl_in), - .ssa_ctrl_in (ssa_ctrl) - ); - - - congestion_out_gen #( + .ivc_info(ivc_info), + .ovc_avalable_all(ovc_avalable_all), + .dest_port_decoded_all(dest_port_all), + .masked_ovc_request_all(masked_ovc_request_all), + + .port_pre_sel(port_pre_sel), + .swap_port_presel(swap_port_presel), + .sel(sel), + .reset(reset), + .clk(clk), + .destport_clear(destport_clear), + .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant), + //.ssa_ivc_num_getting_ovc_grant_all(nla_ivc_num_getting_ovc_grant_all), + .smart_ctrl_in (smart_ctrl_in), + .ssa_ctrl_in (ssa_ctrl) + ); + + congestion_out_gen #( .P(P), .V(V), .ROUTE_TYPE(ROUTE_TYPE), .CONGESTION_INDEX(CONGESTION_INDEX), .CONGw(CONGw) - ) - congestion_out - ( + ) congestion_out ( .ovc_avalable_all(ovc_avalable_all), .ivc_request_all(ivc_request_all), .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant ), .congestion_out_all(congestion_out_all), .clk(clk), .reset(reset) - ); - - - - - - - - genvar i; - generate - - /* verilator lint_off WIDTH */ - if( SSA_EN =="YES" ) begin : ssa - /* verilator lint_on WIDTH */ - ss_allocator #( - .NOC_ID(NOC_ID), - .P(P) - ) - the_ssa - ( - .ivc_info(ivc_info), - .ovc_info(ovc_info), - .flit_in_wr_all(flit_in_wr_all), - .flit_in_all(flit_in_all), - .any_ivc_sw_request_granted_all(any_ivc_sw_request_granted_all), - .any_ovc_granted_in_outport_all(any_ovc_granted_in_outport_all), - .ovc_avalable_all(ovc_avalable_all), - .clk(clk), - .reset(reset), - .ssa_ctrl_o(ssa_ctrl) - ); - - end else begin :non_ssa - for(i=0;i< P;i=i+1) begin :p_ - assign ssa_ctrl[i] = {SSA_CTRL_w{1'b0}}; - end - end - - - - for(i=0;i< P;i=i+1) begin :p_ - assign ssa_flit_wr_all [i] = ssa_ctrl[i].ssa_flit_wr; - end//for - - //synthesis translate_off - //synopsys translate_off - if(DEBUG_EN && MIN_PCK_SIZE >1 )begin :dbg - wire [PV-1 : 0] non_vsa_ivc_num_getting_ovc_grant_all; - integer kk; - for(i=0;i< P;i=i+1) begin :p_ - assign non_vsa_ivc_num_getting_ovc_grant_all [(i+1)*V-1 : i*V] = ssa_ctrl[i].ivc_num_getting_ovc_grant | smart_ctrl_in[i].ivc_num_getting_ovc_grant; - end//for - always @(posedge clk ) begin - for(kk=0; kk< PV; kk=kk+1'b1 ) if(reset_ivc_all[kk] & (ivc_num_getting_ovc_grant[kk] | non_vsa_ivc_num_getting_ovc_grant_all[kk])) begin - $display("%t: ERROR: the ovc %d released and allocat signal is asserted in the same clock cycle : %m",$time,kk); - $finish; - end - end - end - //synopsys translate_on - //synthesis translate_on - endgenerate + ); + + genvar i; + generate + + /* verilator lint_off WIDTH */ + if( SSA_EN =="YES" ) begin : ssa + /* verilator lint_on WIDTH */ + ss_allocator #( + .NOC_ID(NOC_ID), + .P(P) + ) the_ssa ( + .ivc_info(ivc_info), + .ovc_info(ovc_info), + .flit_in_wr_all(flit_in_wr_all), + .flit_in_all(flit_in_all), + .any_ivc_sw_request_granted_all(any_ivc_sw_request_granted_all), + .any_ovc_granted_in_outport_all(any_ovc_granted_in_outport_all), + .ovc_avalable_all(ovc_avalable_all), + .clk(clk), + .reset(reset), + .ssa_ctrl_o(ssa_ctrl) + ); + + end else begin :non_ssa + for(i=0;i< P;i=i+1) begin :p_ + assign ssa_ctrl[i] = {SSA_CTRL_w{1'b0}}; + end + end //ssa + + for(i=0;i< P;i=i+1) begin :p_ + assign ssa_flit_wr_all [i] = ssa_ctrl[i].ssa_flit_wr; + end//for + + `ifdef SIMULATION + if(DEBUG_EN && MIN_PCK_SIZE >1 )begin :dbg + wire [PV-1 : 0] non_vsa_ivc_num_getting_ovc_grant_all; + integer kk; + for(i=0;i< P;i=i+1) begin :p_ + assign non_vsa_ivc_num_getting_ovc_grant_all [(i+1)*V-1 : i*V] = ssa_ctrl[i].ivc_num_getting_ovc_grant | smart_ctrl_in[i].ivc_num_getting_ovc_grant; + end//for + always @(posedge clk ) begin + for(kk=0; kk< PV; kk=kk+1'b1 ) if(reset_ivc_all[kk] & (ivc_num_getting_ovc_grant[kk] | non_vsa_ivc_num_getting_ovc_grant_all[kk])) begin + $display("%t: ERROR: the ovc %d released and allocat signal is asserted in the same clock cycle : %m",$time,kk); + $finish; + end + end + end + `endif// SIMULATION + endgenerate endmodule - - - - - /****************** - +/****************** output_vc_status - - ******************/ - - module output_vc_status #( +******************/ +module output_vc_status #( parameter V = 4, parameter B = 16, parameter CAND_VC_SEL_MODE = 0, // 0: use arbiteration between not full vcs, 1: select the vc with most availble free space parameter CRDTw = 4 )( - credit_init_val_in, - wr_in, - credit_in, - nearly_full_vc, - full_vc, - empty_vc, - cand_vc, - cand_wr_vc_en, - clk, - reset + credit_init_val_in, + wr_in, + credit_in, + nearly_full_vc, + full_vc, + empty_vc, + cand_vc, + cand_wr_vc_en, + clk, + reset ); - - - input [V-1 : 0] [CRDTw-1 : 0 ] credit_init_val_in ; - input [V-1 :0] wr_in; - input [V-1 :0] credit_in; - output [V-1 :0] nearly_full_vc; - output [V-1 : 0] full_vc; - output [V-1 :0] empty_vc; - output [V-1 :0] cand_vc; - input cand_wr_vc_en; - input clk; - input reset; - + + input [V-1 : 0] [CRDTw-1 : 0 ] credit_init_val_in ; + input [V-1 :0] wr_in; + input [V-1 :0] credit_in; + output [V-1 :0] nearly_full_vc; + output [V-1 : 0] full_vc; + output [V-1 :0] empty_vc; + output [V-1 :0] cand_vc; + input cand_wr_vc_en; + input clk; + input reset; + function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2. + ** You should have received a copy of the GNU Lesser General Public + ** License along with ProNoC. If not, see . ** ** - ** Description: - ** NoC router input Port. It consists of input buffer, control FIFO - ** and request masking/generation control modules + ** Description: + ** NoC router input Port. It consists of input buffer, control FIFO + ** and request masking/generation control modules ** **************************************************************/ - + module input_ports #( - parameter NOC_ID=0, - parameter P=5 -) ( - current_r_addr, - neighbors_r_addr, - ivc_num_getting_sw_grant,// for non spec ivc_num_getting_first_sw_grant, - any_ivc_sw_request_granted_all, - flit_in_all, - flit_in_wr_all, - reset_ivc_all, - flit_is_tail_all, - ivc_request_all, - dest_port_all, - flit_out_all, - - assigned_ovc_not_full_all, - ovc_is_assigned_all, - sel, - port_pre_sel, - swap_port_presel, - nonspec_first_arbiter_granted_ivc_all, - credit_out_all, - - destport_clear, - vc_weight_is_consumed_all, - iport_weight_is_consumed_all, - iport_weight_all, - oports_weight_all, - granted_dest_port_all, - refresh_w_counter, - ivc_info, - vsa_ctrl_in, - ssa_ctrl_in, - smart_ctrl_in, - credit_init_val_out, - reset, - clk + parameter NOC_ID=0, + parameter ROUTER_ID=0, + parameter P=5 +)( + current_r_addr, + neighbors_r_addr, + ivc_num_getting_sw_grant,// for non spec ivc_num_getting_first_sw_grant, + any_ivc_sw_request_granted_all, + flit_in_all, + flit_in_wr_all, + reset_ivc_all, + flit_is_tail_all, + ivc_request_all, + dest_port_all, + flit_out_all, + + assigned_ovc_not_full_all, + ovc_is_assigned_all, + sel, + port_pre_sel, + swap_port_presel, + nonspec_first_arbiter_granted_ivc_all, + credit_out_all, + + destport_clear, + vc_weight_is_consumed_all, + iport_weight_is_consumed_all, + iport_weight_all, + oports_weight_all, + granted_dest_port_all, + refresh_w_counter, + ivc_info, + vsa_ctrl_in, + ssa_ctrl_in, + smart_ctrl_in, + credit_init_val_out, + reset, + clk ); - - `NOC_CONF - - localparam - PV = V * P, - VV = V * V, - PVV = PV * V, - P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, - PP_1 = P * P_1, - VP_1 = V * P_1, - PVP_1 = PV * P_1, - PFw = P*Fw, - W= WEIGHTw, - WP= W * P, - WPP = WP * P, - PVDSTPw= PV * DSTPw, - PRAw= P * RAw; - + + `NOC_CONF + + localparam + PV = V * P, + VV = V * V, + PVV = PV * V, + P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, + PP_1 = P * P_1, + VP_1 = V * P_1, + PVP_1 = PV * P_1, + PFw = P*Fw, + W= WEIGHTw, + WP= W * P, + WPP = WP * P, + PVDSTPw= PV * DSTPw, + PRAw= P * RAw; + + input reset,clk; + input [RAw-1 : 0] current_r_addr; + input [PRAw-1: 0] neighbors_r_addr; + output [PV-1 : 0] ivc_num_getting_sw_grant; + input [P-1 : 0] any_ivc_sw_request_granted_all; + input [PFw-1 : 0] flit_in_all; + input [P-1 : 0] flit_in_wr_all; + output [PV-1 : 0] reset_ivc_all; + output [PV-1 : 0] flit_is_tail_all; + output [PV-1 : 0] ivc_request_all; + output [PV-1 : 0] credit_out_all; + + output [PVP_1-1 : 0] dest_port_all; + output [PFw-1 : 0] flit_out_all; + + input [PV-1 : 0] assigned_ovc_not_full_all; + output [PV-1 : 0] ovc_is_assigned_all; + input [PV-1 : 0] sel; + input [PPSw-1 : 0] port_pre_sel; + input [PV-1 : 0] swap_port_presel; + input [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; + + output [WP-1 : 0] iport_weight_all; + output [PV-1 : 0] vc_weight_is_consumed_all; + output [P-1 : 0] iport_weight_is_consumed_all; + input [PP_1-1 : 0] granted_dest_port_all; + output [WPP-1 : 0] oports_weight_all; + + output ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + input vsa_ctrl_t vsa_ctrl_in [P-1: 0]; + input ssa_ctrl_t ssa_ctrl_in [P-1: 0]; + input smart_ctrl_t smart_ctrl_in [P-1 : 0]; + output [CRDTw-1 : 0 ] credit_init_val_out [P-1 : 0][V-1 : 0]; + + input refresh_w_counter; + + input [DSTPw-1 : 0] destport_clear [P-1 : 0][V-1 : 0]; + + genvar i; + generate + for(i=0;iMIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, - MAX_PCK = (VC_REALLOCATION_TYPE== "ATOMIC")? 1 : NON_ATOM_PCKS + OVC_ALLOC_MODE,// min packet size is two hence the max packet number in buffer is (B/2) - IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN=="YES")| SMART_EN)? "YES" : "NO"; - - - localparam - ELw = log2(T3), - Pw = log2(P), - PLw = (TOPOLOGY == "FMESH") ? Pw : ELw, - VPLw= V * PLw, - PRAw= P * RAw; - /* verilator lint_on WIDTH */ - - - input reset, clk; - output [V-1 : 0] credit_out; - input [RAw-1 : 0] current_r_addr; - input [PRAw-1: 0] neighbors_r_addr; - output [V-1 : 0] ivc_num_getting_sw_grant; - input any_ivc_sw_request_granted; - input [Fw-1 : 0] flit_in; - input flit_in_wr; - output [V-1 : 0] reset_ivc; - output [V-1 : 0] flit_is_tail; - output [V-1 : 0] ivc_request; - output [VP_1-1 : 0] dest_port; - output [Fw-1 : 0] flit_out; - input [V-1 : 0] assigned_ovc_not_full; - output [V-1 : 0] ovc_is_assigned; - input [V-1 : 0] sel; - input [V-1 : 0] nonspec_first_arbiter_granted_ivc; - - input [DSTPw-1 : 0] destport_clear [V-1 : 0]; - output [WEIGHTw-1 : 0] iport_weight; - output [V-1 : 0] vc_weight_is_consumed; - output iport_weight_is_consumed; - input refresh_w_counter; - input [P_1-1 : 0] granted_dest_port; - output [WP-1 : 0] oports_weight; - input [PPSw-1 : 0] port_pre_sel; - input [V-1 : 0] swap_port_presel; - - output ivc_info_t ivc_info [V-1 : 0]; - input smart_ctrl_t smart_ctrl_in; - input vsa_ctrl_t vsa_ctrl_in; - input ssa_ctrl_t ssa_ctrl_in; - output [CRDTw-1 : 0 ] credit_init_val_out [V-1 : 0]; - - wire [DSTPw-1 : 0] dest_port_encoded [V-1 : 0]; - //for multicast - wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; - wire [V-1 : 0] multiple_dest,dst_onhot0; - wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; - - wire [VV-1 : 0] candidate_ovcs; - - wire [Cw-1 : 0] class_in; - wire [DSTPw-1 : 0] destport_in,destport_in_encoded; - wire [VDSTPw-1 : 0] lk_destination_encoded; - - wire [DAw-1 : 0] dest_e_addr_in; - wire [EAw-1 : 0] src_e_addr_in; - wire [V-1 : 0] vc_num_in; - wire [V-1 : 0] hdr_flit_wr,flit_wr; - wire [VV-1 : 0] assigned_ovc_num; - - wire [DSTPw-1 : 0] lk_destination_in_encoded; - wire [WEIGHTw-1 : 0] weight_in; - wire [Fw-1 : 0] buffer_out; - wire hdr_flg_in,tail_flg_in; - wire [V-1 : 0] ivc_not_empty; - wire [Cw-1 : 0] class_out [V-1 : 0]; - wire [VPLw-1 : 0] endp_localp_num; - - wire [V-1 : 0] smart_hdr_en; - wire [ELw-1 : 0] endp_l_in; - wire [Pw-1 : 0] endp_p_in; - - wire [V-1 : 0] rd_hdr_fwft_fifo,wr_hdr_fwft_fifo,rd_hdr_fwft_fifo_delay,wr_hdr_fwft_fifo_delay; - - logic [V-1 : 0] ovc_is_assigned_next; - logic [VV-1 : 0] assigned_ovc_num_next; - - wire odd_column = current_r_addr[0]; - wire [P-1 : 0] destport_one_hot [V-1 :0]; - wire [V-1 : 0] mux_out[V-1 : 0]; - - wire [V-1 : 0] dstport_fifo_not_empty; - - logic [WEIGHTw-1 : 0] iport_weight_next; - - assign smart_hdr_en = (SMART_EN) ? smart_ctrl_in.ivc_num_getting_ovc_grant: {V{1'b0}}; - assign reset_ivc = smart_ctrl_in.ivc_reset | ssa_ctrl_in.ivc_reset | vsa_ctrl_in.ivc_reset; - assign ivc_num_getting_sw_grant = ssa_ctrl_in.ivc_num_getting_sw_grant | vsa_ctrl_in.ivc_num_getting_sw_grant; - assign flit_wr =(flit_in_wr )? vc_num_in : {V{1'b0}}; - assign rd_hdr_fwft_fifo = (ssa_ctrl_in.ivc_reset | vsa_ctrl_in.ivc_reset | (smart_ctrl_in.ivc_reset & ~ smart_ctrl_in.ivc_single_flit_pck)) & ~ multiple_dest; - assign wr_hdr_fwft_fifo = hdr_flit_wr | (smart_hdr_en & ~ smart_ctrl_in.ivc_single_flit_pck); - assign ivc_request = ivc_not_empty; - - - wire [V-1 : 0] flit_is_tail2; - - - pronoc_register #(.W(V)) reg1( - .in (ovc_is_assigned_next), - .reset (reset ), - .clk (clk ), - .out (ovc_is_assigned )); - - pronoc_register #(.W(VV)) reg2( - .in (assigned_ovc_num_next), - .reset (reset ), - .clk (clk ), - .out (assigned_ovc_num )); - - pronoc_register #(.W(V)) reg3( - .in (rd_hdr_fwft_fifo), - .reset (reset ), - .clk (clk ), - .out (rd_hdr_fwft_fifo_delay )); - - pronoc_register #(.W(V)) reg4( - .in (wr_hdr_fwft_fifo), - .reset (reset ), - .clk (clk ), - .out (wr_hdr_fwft_fifo_delay )); - - pronoc_register #(.W(WEIGHTw), .RESET_TO(1)) reg5( - .in (iport_weight_next ), - .reset (reset ), - .clk (clk ), - .out (iport_weight )); - - - pronoc_register #(.W(V)) credit_reg ( - .in (ivc_num_getting_sw_grant & ~ multiple_dest), - .reset (reset), - .clk (clk), - .out (credit_out)); - - - - - always @ (*)begin - iport_weight_next = iport_weight; - if(hdr_flit_wr != {V{1'b0}}) iport_weight_next = (weight_in=={WEIGHTw{1'b0}})? 1 : weight_in; // the minimum weight is 1 - end - - - //extract header flit info - extract_header_flit_info #( - .NOC_ID(NOC_ID), - .DATA_w(0) - ) header_extractor ( - .flit_in(flit_in), - .flit_in_wr(flit_in_wr), - .class_o(class_in), - .destport_o(destport_in), - .dest_e_addr_o(dest_e_addr_in), - .src_e_addr_o(src_e_addr_in), - .vc_num_o(vc_num_in), - .hdr_flit_wr_o(hdr_flit_wr), - .hdr_flg_o(hdr_flg_in), - .tail_flg_o(tail_flg_in), - .weight_o(weight_in), - .be_o( ), - .data_o( ) - ); - - - - genvar i; - generate - /* verilator lint_off WIDTH */ - if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local - /* verilator lint_on WIDTH */ - - - - mesh_tori_endp_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) - endp_addr_decode - ( - .e_addr(dest_e_addr_in), - .ex( ), - .ey( ), - .el(endp_l_in), - .valid( ) - ); - end - /* verilator lint_off WIDTH */ - if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST" ) begin : fmesh - /* verilator lint_on WIDTH */ - - - - fmesh_endp_addr_decode #( - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) - endp_addr_decode - ( - .e_addr(dest_e_addr_in), - .ex(), - .ey(), - .ep(endp_p_in), - .valid() - ); - - end - /* verilator lint_off WIDTH */ - if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat - /* verilator lint_on WIDTH */ - - fattree_destport_up_select #( - .K(T1), - .SW_LOC(SW_LOC) - ) - static_sel - ( - .destport_in(destport_in), - .destport_o(destport_in_encoded) - ); - - end else begin : other - assign destport_in_encoded = destport_in; - end - - - for (i=0;iMIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, + MAX_PCK = (VC_REALLOCATION_TYPE== "ATOMIC")? 1 : NON_ATOM_PCKS + OVC_ALLOC_MODE,// min packet size is two hence the max packet number in buffer is (B/2) + IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN=="YES")| SMART_EN)? "YES" : "NO"; - if(PCK_TYPE == "MULTI_FLIT") begin : multi_flit - - always @ (*) begin - ovc_is_assigned_next[i] = ovc_is_assigned[i]; - if( vsa_ctrl_in.ivc_reset[i] | - ssa_ctrl_in.ivc_reset[i] | - smart_ctrl_in.ivc_reset[i] - ) ovc_is_assigned_next[i] = 1'b0; - - else if( vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | - (ssa_ctrl_in.ivc_num_getting_ovc_grant[i] & ~ ssa_ctrl_in.ivc_single_flit_pck[i])| - (smart_ctrl_in.ivc_num_getting_ovc_grant[i] & ~ smart_ctrl_in.ivc_single_flit_pck[i]) - ) ovc_is_assigned_next[i] = 1'b1; - end//always - - - always @(*) begin - assigned_ovc_num_next[(i+1)*V-1 : i*V] = assigned_ovc_num[(i+1)*V-1 : i*V] ; - if(vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | ssa_ctrl_in.ivc_num_getting_ovc_grant[i] | smart_ctrl_in.ivc_num_getting_ovc_grant[i] ) begin - assigned_ovc_num_next[(i+1)*V-1 : i*V] = mux_out[i]; - end - end - - onehot_mux_1D #( - .N (3), - .W (V) - ) hot_mux ( - .in ({vsa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V], - ssa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V], - smart_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V]}), - .sel ({vsa_ctrl_in.ivc_num_getting_ovc_grant[i],ssa_ctrl_in.ivc_num_getting_ovc_grant[i],smart_ctrl_in.ivc_num_getting_ovc_grant[i]} ), - .out (mux_out[i] ) - ); - - - /* - //tail fifo - fwft_fifo #( - .DATA_WIDTH(1), - .MAX_DEPTH (PORT_B), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - tail_fifo - ( - .din (tail_flg_in), - .wr_en (flit_wr[i]), // Write enable - .rd_en (ivc_num_getting_sw_grant[i]), // Read the next word - .dout (flit_is_tail[i]), // Data out - .full ( ), - .nearly_full ( ), - .recieve_more_than_0 ( ), - .recieve_more_than_1 ( ), - .reset (reset), - .clk (clk) - ); - */ - - end else begin :single_flit - //assign flit_is_tail[i]=1'b1; - assign ovc_is_assigned_next[i] = 1'b0; - - always @(*) begin - assigned_ovc_num_next[(i+1)*V-1 : i*V] = assigned_ovc_num[(i+1)*V-1 : i*V] ; - if(vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | ssa_ctrl_in.ivc_num_getting_ovc_grant[i]) begin - assigned_ovc_num_next[(i+1)*V-1 : i*V] = mux_out[i]; - end - end - - onehot_mux_1D #( - .N (2), - .W (V) - ) hot_mux ( - .in ({vsa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V], - ssa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V]}), - .sel ({vsa_ctrl_in.ivc_num_getting_ovc_grant[i],ssa_ctrl_in.ivc_num_getting_ovc_grant[i]} ), - .out (mux_out[i] ) - ); - - - - end - //dest_e_addr_in fifo - if(SMART_EN) begin : smart_ - - fwft_fifo #( - .DATA_WIDTH(EAw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - dest_e_addr_fifo - ( - .din (dest_e_addr_in), - .wr_en (wr_hdr_fwft_fifo[i]), // Write enable - .rd_en (rd_hdr_fwft_fifo[i]), // Read the next word - .dout (ivc_info[i].dest_e_addr), // Data out - .full ( ), - .nearly_full ( ), - .recieve_more_than_0 ( ), - .recieve_more_than_1 ( ), - .reset (reset), - .clk (clk) - ); - - end else begin : no_smart - assign ivc_info[i].dest_e_addr = {EAw{1'bx}}; - end + + localparam + ELw = log2(T3), + Pw = log2(P), + PLw = (TOPOLOGY == "FMESH") ? Pw : ELw, + VPLw= V * PLw, + PRAw= P * RAw; + /* verilator lint_on WIDTH */ + + input reset, clk; + output [V-1 : 0] credit_out; + input [RAw-1 : 0] current_r_addr; + input [PRAw-1: 0] neighbors_r_addr; + output [V-1 : 0] ivc_num_getting_sw_grant; + input any_ivc_sw_request_granted; + input [Fw-1 : 0] flit_in; + input flit_in_wr; + output [V-1 : 0] reset_ivc; + output [V-1 : 0] flit_is_tail; + output [V-1 : 0] ivc_request; + output [VP_1-1 : 0] dest_port; + output [Fw-1 : 0] flit_out; + input [V-1 : 0] assigned_ovc_not_full; + output [V-1 : 0] ovc_is_assigned; + input [V-1 : 0] sel; + input [V-1 : 0] nonspec_first_arbiter_granted_ivc; + + input [DSTPw-1 : 0] destport_clear [V-1 : 0]; + output [WEIGHTw-1 : 0] iport_weight; + output [V-1 : 0] vc_weight_is_consumed; + output iport_weight_is_consumed; + input refresh_w_counter; + input [P_1-1 : 0] granted_dest_port; + output [WP-1 : 0] oports_weight; + input [PPSw-1 : 0] port_pre_sel; + input [V-1 : 0] swap_port_presel; + + output ivc_info_t ivc_info [V-1 : 0]; + input smart_ctrl_t smart_ctrl_in; + input vsa_ctrl_t vsa_ctrl_in; + input ssa_ctrl_t ssa_ctrl_in; + output [CRDTw-1 : 0 ] credit_init_val_out [V-1 : 0]; + + wire [DSTPw-1 : 0] dest_port_encoded [V-1 : 0]; + //for multicast + wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + wire [V-1 : 0] multiple_dest,dst_onhot0; + wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; + + wire [VV-1 : 0] candidate_ovcs; + + wire [Cw-1 : 0] class_in; + wire [DSTPw-1 : 0] destport_in,destport_in_encoded; + wire [VDSTPw-1 : 0] lk_destination_encoded; + + wire [DAw-1 : 0] dest_e_addr_in; + wire [EAw-1 : 0] src_e_addr_in; + wire [V-1 : 0] vc_num_in; + wire [V-1 : 0] hdr_flit_wr,flit_wr; + wire [VV-1 : 0] assigned_ovc_num; + + wire [DSTPw-1 : 0] lk_destination_in_encoded; + wire [WEIGHTw-1 : 0] weight_in; + wire [Fw-1 : 0] buffer_out; + wire hdr_flg_in,tail_flg_in; + wire [V-1 : 0] ivc_not_empty; + wire [Cw-1 : 0] class_out [V-1 : 0]; + wire [VPLw-1 : 0] endp_localp_num; + + wire [V-1 : 0] smart_hdr_en; + wire [ELw-1 : 0] endp_l_in; + wire [Pw-1 : 0] endp_p_in; + + wire [V-1 : 0] rd_hdr_fwft_fifo,wr_hdr_fwft_fifo,rd_hdr_fwft_fifo_delay,wr_hdr_fwft_fifo_delay; + + logic [V-1 : 0] ovc_is_assigned_next; + logic [VV-1 : 0] assigned_ovc_num_next; + + wire odd_column = current_r_addr[0]; + wire [P-1 : 0] destport_one_hot [V-1 :0]; + wire [V-1 : 0] mux_out[V-1 : 0]; + + wire [V-1 : 0] dstport_fifo_not_empty; + + logic [WEIGHTw-1 : 0] iport_weight_next; + + assign smart_hdr_en = (SMART_EN) ? smart_ctrl_in.ivc_num_getting_ovc_grant: {V{1'b0}}; + assign reset_ivc = smart_ctrl_in.ivc_reset | ssa_ctrl_in.ivc_reset | vsa_ctrl_in.ivc_reset; + assign ivc_num_getting_sw_grant = ssa_ctrl_in.ivc_num_getting_sw_grant | vsa_ctrl_in.ivc_num_getting_sw_grant; + assign flit_wr =(flit_in_wr )? vc_num_in : {V{1'b0}}; + assign rd_hdr_fwft_fifo = (ssa_ctrl_in.ivc_reset | vsa_ctrl_in.ivc_reset | (smart_ctrl_in.ivc_reset & ~ smart_ctrl_in.ivc_single_flit_pck)) & ~ multiple_dest; + assign wr_hdr_fwft_fifo = hdr_flit_wr | (smart_hdr_en & ~ smart_ctrl_in.ivc_single_flit_pck); + assign ivc_request = ivc_not_empty; + + wire [V-1 : 0] flit_is_tail2; + + pronoc_register #(.W(V)) reg1( + .in (ovc_is_assigned_next), + .reset (reset ), + .clk (clk ), + .out (ovc_is_assigned )); + + pronoc_register #(.W(VV)) reg2( + .in (assigned_ovc_num_next), + .reset (reset ), + .clk (clk ), + .out (assigned_ovc_num )); + + pronoc_register #(.W(V)) reg3( + .in (rd_hdr_fwft_fifo), + .reset (reset ), + .clk (clk ), + .out (rd_hdr_fwft_fifo_delay )); + + pronoc_register #(.W(V)) reg4( + .in (wr_hdr_fwft_fifo), + .reset (reset ), + .clk (clk ), + .out (wr_hdr_fwft_fifo_delay )); + + pronoc_register #(.W(WEIGHTw), .RESET_TO(1)) reg5( + .in (iport_weight_next ), + .reset (reset ), + .clk (clk ), + .out (iport_weight )); + + pronoc_register #(.W(V)) credit_reg ( + .in (ivc_num_getting_sw_grant & ~ multiple_dest), + .reset (reset), + .clk (clk), + .out (credit_out)); + + always @ (*)begin + iport_weight_next = iport_weight; + if(hdr_flit_wr != {V{1'b0}}) iport_weight_next = (weight_in=={WEIGHTw{1'b0}})? 1 : weight_in; // the minimum weight is 1 + end + + + //extract header flit info + extract_header_flit_info #( + .NOC_ID(NOC_ID), + .DATA_w(0) + ) header_extractor ( + .flit_in(flit_in), + .flit_in_wr(flit_in_wr), + .class_o(class_in), + .destport_o(destport_in), + .dest_e_addr_o(dest_e_addr_in), + .src_e_addr_o(src_e_addr_in), + .vc_num_o(vc_num_in), + .hdr_flit_wr_o(hdr_flit_wr), + .hdr_flg_o(hdr_flg_in), + .tail_flg_o(tail_flg_in), + .weight_o(weight_in), + .be_o( ), + .data_o( ) + ); + + genvar i; + generate + /* verilator lint_off WIDTH */ + if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + /* verilator lint_on WIDTH */ + mesh_tori_endp_addr_decode #( + .TOPOLOGY(TOPOLOGY), + .T1(T1), + .T2(T2), + .T3(T3), + .EAw(EAw) + ) endp_addr_decode ( + .e_addr(dest_e_addr_in), + .ex( ), + .ey( ), + .el(endp_l_in), + .valid( ) + ); + end :multi_local + /* verilator lint_off WIDTH */ + if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST" ) begin : fmesh + /* verilator lint_on WIDTH */ + + fmesh_endp_addr_decode #( + .T1(T1), + .T2(T2), + .T3(T3), + .EAw(EAw) + ) endp_addr_decode ( + .e_addr(dest_e_addr_in), + .ex(), + .ey(), + .ep(endp_p_in), + .valid() + ); + + end + /* verilator lint_off WIDTH */ + if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat + /* verilator lint_on WIDTH */ + + fattree_destport_up_select #( + .K(T1), + .SW_LOC(SW_LOC) + ) static_sel ( + .destport_in(destport_in), + .destport_o(destport_in_encoded) + ); + + end else begin : other + assign destport_in_encoded = destport_in; + end + + for (i=0;i1)begin :cb1 - fwft_fifo #( - .DATA_WIDTH(Cw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - class_fifo - ( - .din (class_in), - .wr_en (wr_hdr_fwft_fifo[i]), // Write enable - .rd_en (rd_hdr_fwft_fifo[i]), // Read the next word - .dout (class_out[i]), // Data out - .full ( ), - .nearly_full ( ), - .recieve_more_than_0 ( ), - .recieve_more_than_1 ( ), - .reset (reset), - .clk (clk) + assign credit_init_val_out [i] = PORT_B [CRDTw-1 : 0 ]; + + one_hot_to_bin #(.ONE_HOT_WIDTH(V),.BIN_WIDTH(Vw)) conv ( + .one_hot_code(assigned_ovc_num[(i+1)*V-1 : i*V]), + .bin_code(ivc_info[i].assigned_ovc_bin) + ); + + assign ivc_info[i].single_flit_pck = + /* verilator lint_off WIDTH */ + (PCK_TYPE == "SINGLE_FLIT")? 1'b1 : + /* verilator lint_on WIDTH */ + (MIN_PCK_SIZE == 1)? flit_is_tail[i] & ~ovc_is_assigned[i] : 1'b0; + assign ivc_info[i].ivc_req = ivc_request[i]; + assign ivc_info[i].class_num = class_out[i]; + assign ivc_info[i].flit_is_tail = flit_is_tail[i]; + assign ivc_info[i].assigned_ovc_not_full=assigned_ovc_not_full[i]; + assign ivc_info[i].candidate_ovc= candidate_ovcs [(i+1)*V-1 : i*V]; + assign ivc_info[i].ovc_is_assigned = ovc_is_assigned[i]; + assign ivc_info[i].assigned_ovc_num= assigned_ovc_num[(i+1)*V-1 : i*V]; + assign ivc_info[i].dest_port_encoded=dest_port_encoded[i]; + //assign ivc_info[i].getting_swa_first_arbiter_grant=nonspec_first_arbiter_granted_ivc[i]; + //assign ivc_info[i].getting_swa_grant=ivc_num_getting_sw_grant[i]; + if(P==MAX_P) begin :max_ + assign ivc_info[i].destport_one_hot= destport_one_hot[i]; + end else begin : no_max + assign ivc_info[i].destport_one_hot= {{(MAX_P-P){1'b0}},destport_one_hot[i]}; + end + + `ifdef SIMULATION + //check ivc info + //assigned ovc must be onehot coded + //assert property (@(posedge clk) $onehot0(ivc_info[i].assigned_ovc_num)); + always @ (posedge clk )begin + if(~ $onehot0(ivc_info[i].assigned_ovc_num)) begin + $display ("ERROR: assigned OVC is not ont-hot coded %d,%m",ivc_info[i].assigned_ovc_num); + $finish; + end + end + `endif + + class_ovc_table #( + .CVw(CVw), + .CLASS_SETTING(CLASS_SETTING), + .C(C), + .V(V) + ) class_table ( + .class_in(class_out[i]), + .candidate_ovcs(candidate_ovcs [(i+1)*V-1 : i*V]) + ); + + if(PCK_TYPE == "MULTI_FLIT") begin : multi_flit - ); - end else begin :c_num_1 - assign class_out[i] = 1'b0; - end - - - //localparam CAST_TYPE = "UNICAST"; // multicast is not yet supported - /* verilator lint_off WIDTH */ - if(CAST_TYPE!= "UNICAST") begin : muticast - /* verilator lint_on WIDTH */ - - // for multicast we send one packet to each direction in order. The priority is according to DoR routing dimentions - - fwft_fifo_with_output_clear #( - .DATA_WIDTH(DSTPw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - dest_fifo - ( - .din(destport_in_encoded), - .wr_en(wr_hdr_fwft_fifo[i]), // Write enable - .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word - .dout(dest_port_multi[i]), // Data out - .full(), - .nearly_full(), - .recieve_more_than_0(), - .recieve_more_than_1(), - .reset(reset), - .clk(clk), - .clear(clear_dspt_mulicast [i]) // clear the destination port once it got the entire packet - ); - - //TODO remove multiple_dest[i] to see if it works? - - assign clear_dspt_mulicast [i] = (reset_ivc[i] & multiple_dest[i]) ? dest_port_encoded[i] : {DSTPw{1'b0}}; - - // a fix priority arbiter. - multicast_dst_sel #( - .NOC_ID(NOC_ID) - ) sel_arb( - .destport_in(dest_port_multi[i]), - .destport_out(dest_port_encoded[i]) - ); - - //check if we have multiple port to send a packet to - is_onehot0 #( - .IN_WIDTH(DSTPw) - ) - one_h - ( - .in(dest_port_multi[i]), - .result(dst_onhot0[i]) - ); - assign multiple_dest[i]=~dst_onhot0[i]; - - - end else begin : unicast - assign multiple_dest[i] = 1'b0; - - - //lk_dst_fifo - fwft_fifo #( - .DATA_WIDTH(DSTPw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - lk_dest_fifo - ( - .din (lk_destination_in_encoded), - .wr_en (wr_hdr_fwft_fifo_delay [i]), // Write enable - .rd_en (rd_hdr_fwft_fifo_delay [i]), // Read the next word - .dout (lk_destination_encoded [(i+1)*DSTPw-1 : i*DSTPw]), // Data out - .full (), - .nearly_full (), - .recieve_more_than_0 (), - .recieve_more_than_1 (), - .reset (reset), - .clk (clk) - - ); - - - - /* verilator lint_off WIDTH */ - if( ROUTE_TYPE=="DETERMINISTIC") begin : dtrmn_dest - /* verilator lint_on WIDTH */ - //destport_fifo - fwft_fifo #( - .DATA_WIDTH(DSTPw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - dest_fifo - ( - .din(destport_in_encoded), - .wr_en(wr_hdr_fwft_fifo[i]), // Write enable - .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word - .dout(dest_port_encoded[i]), // Data out - .full(), - .nearly_full(), - .recieve_more_than_0(), - .recieve_more_than_1(), - .reset(reset), - .clk(clk) - ); - - end else begin : adptv_dest - - fwft_fifo_with_output_clear #( - .DATA_WIDTH(DSTPw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - dest_fifo - ( - .din(destport_in_encoded), - .wr_en(wr_hdr_fwft_fifo[i]), // Write enable - .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word - .dout(dest_port_encoded[i]), // Data out - .full(), - .nearly_full(), - .recieve_more_than_0(), - .recieve_more_than_1(), - .reset(reset), - .clk(clk), - .clear(destport_clear[i]) // clear other destination ports once one of them is selected - ); - - - end - end//unicast - - - destp_generator #( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .T1(T1), - .NL(T3), - .P(P), - .DSTPw(DSTPw), - .PLw(PLw), - .PPSw(PPSw), - .SELF_LOOP_EN (SELF_LOOP_EN), - .SW_LOC(SW_LOC), - .CAST_TYPE(CAST_TYPE) - ) - decoder - ( - .destport_one_hot (destport_one_hot[i]), - .dest_port_encoded(dest_port_encoded[i]), - .dest_port_out(dest_port[(i+1)*P_1-1 : i*P_1]), - .endp_localp_num(endp_localp_num[(i+1)*PLw-1 : i*PLw]), - .swap_port_presel(swap_port_presel[i]), - .port_pre_sel(port_pre_sel), - .odd_column(odd_column) - ); - - - /* verilator lint_off WIDTH */ - if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local - /* verilator lint_on WIDTH */ - // the router has multiple local ports. Save the destination local port - - + always @ (*) begin + ovc_is_assigned_next[i] = ovc_is_assigned[i]; + if( vsa_ctrl_in.ivc_reset[i] | + ssa_ctrl_in.ivc_reset[i] | + smart_ctrl_in.ivc_reset[i] + ) ovc_is_assigned_next[i] = 1'b0; + else if( vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | + (ssa_ctrl_in.ivc_num_getting_ovc_grant[i] & ~ ssa_ctrl_in.ivc_single_flit_pck[i])| + (smart_ctrl_in.ivc_num_getting_ovc_grant[i] & ~ smart_ctrl_in.ivc_single_flit_pck[i]) + ) ovc_is_assigned_next[i] = 1'b1; + end//always + + always @(*) begin + assigned_ovc_num_next[(i+1)*V-1 : i*V] = assigned_ovc_num[(i+1)*V-1 : i*V] ; + if(vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | ssa_ctrl_in.ivc_num_getting_ovc_grant[i] | smart_ctrl_in.ivc_num_getting_ovc_grant[i] ) begin + assigned_ovc_num_next[(i+1)*V-1 : i*V] = mux_out[i]; + end + end + + onehot_mux_1D #( + .N (3), + .W (V) + ) hot_mux ( + .in ({vsa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V], + ssa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V], + smart_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V]}), + .sel ({vsa_ctrl_in.ivc_num_getting_ovc_grant[i],ssa_ctrl_in.ivc_num_getting_ovc_grant[i],smart_ctrl_in.ivc_num_getting_ovc_grant[i]} ), + .out (mux_out[i]) + ); - fwft_fifo #( - .DATA_WIDTH(ELw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - local_dest_fifo - ( - .din(endp_l_in), - .wr_en(wr_hdr_fwft_fifo[i]), // Write enable - .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word - .dout(endp_localp_num[(i+1)*PLw-1 : i*PLw]), // Data out - .full( ), - .nearly_full( ), - .recieve_more_than_0(), - .recieve_more_than_1(), - .reset(reset), - .clk(clk) - ); - /* verilator lint_off WIDTH */ - end else if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST") begin : fmesh - /* verilator lint_on WIDTH */ - - fwft_fifo #( - .DATA_WIDTH(Pw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) - local_dest_fifo - ( - .din(endp_p_in), - .wr_en(wr_hdr_fwft_fifo[i]), // Write enable - .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word - .dout(endp_localp_num[(i+1)*PLw-1 : i*PLw]), // Data out - .full( ), - .nearly_full( ), - .recieve_more_than_0(), - .recieve_more_than_1(), - .reset(reset), - .clk(clk) - ); - - end else begin : single_local - assign endp_localp_num[(i+1)*PLw-1 : i*PLw] = {PLw{1'bx}}; - end + /* + //tail fifo + fwft_fifo #( + .DATA_WIDTH(1), + .MAX_DEPTH (PORT_B), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) + tail_fifo + ( + .din (tail_flg_in), + .wr_en (flit_wr[i]), // Write enable + .rd_en (ivc_num_getting_sw_grant[i]), // Read the next word + .dout (flit_is_tail[i]), // Data out + .full ( ), + .nearly_full ( ), + .recieve_more_than_0 ( ), + .recieve_more_than_1 ( ), + .reset (reset), + .clk (clk) + ); + */ + + end else begin :single_flit + //assign flit_is_tail[i]=1'b1; + assign ovc_is_assigned_next[i] = 1'b0; + + always @(*) begin + assigned_ovc_num_next[(i+1)*V-1 : i*V] = assigned_ovc_num[(i+1)*V-1 : i*V] ; + if(vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | ssa_ctrl_in.ivc_num_getting_ovc_grant[i]) begin + assigned_ovc_num_next[(i+1)*V-1 : i*V] = mux_out[i]; + end + end + + onehot_mux_1D #( + .N (2), + .W (V) + ) hot_mux ( + .in ({vsa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V], ssa_ctrl_in.ivc_granted_ovc_num[(i+1)*V-1 : i*V]}), + .sel ({vsa_ctrl_in.ivc_num_getting_ovc_grant[i], ssa_ctrl_in.ivc_num_getting_ovc_grant[i]}), + .out (mux_out[i]) + ); + + end + //dest_e_addr_in fifo + if(SMART_EN) begin : smart_ + + fwft_fifo #( + .DATA_WIDTH(EAw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) dest_e_addr_fifo ( + .din (dest_e_addr_in), + .wr_en (wr_hdr_fwft_fifo[i]), // Write enable + .rd_en (rd_hdr_fwft_fifo[i]), // Read the next word + .dout (ivc_info[i].dest_e_addr), // Data out + .full ( ), + .nearly_full ( ), + .recieve_more_than_0 ( ), + .recieve_more_than_1 ( ), + .reset (reset), + .clk (clk) + ); + + end else begin : no_smart + assign ivc_info[i].dest_e_addr = {EAw{1'bx}}; + end + + //class_fifo + if(C>1)begin :cb1 + fwft_fifo #( + .DATA_WIDTH(Cw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) class_fifo ( + .din (class_in), + .wr_en (wr_hdr_fwft_fifo[i]), // Write enable + .rd_en (rd_hdr_fwft_fifo[i]), // Read the next word + .dout (class_out[i]), // Data out + .full ( ), + .nearly_full ( ), + .recieve_more_than_0 ( ), + .recieve_more_than_1 ( ), + .reset (reset), + .clk (clk) + + ); + end else begin :c_num_1 + assign class_out[i] = 1'b0; + end - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra - /* verilator lint_on WIDTH */ - /* - weight_control #( - .WEIGHTw(WEIGHTw) - ) - wctrl_per_vc - ( - .sw_is_granted(ivc_num_getting_sw_grant[i]), - .flit_is_tail(flit_is_tail[i]), - .weight_is_consumed_o(vc_weight_is_consumed[i]), - .iport_weight(1), //(iport_weight), + //localparam CAST_TYPE = "UNICAST"; // multicast is not yet supported + /* verilator lint_off WIDTH */ + if(CAST_TYPE!= "UNICAST") begin : muticast + /* verilator lint_on WIDTH */ + + // for multicast we send one packet to each direction in order. The priority is according to DoR routing dimentions + + fwft_fifo_with_output_clear #( + .DATA_WIDTH(DSTPw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) dest_fifo ( + .din(destport_in_encoded), + .wr_en(wr_hdr_fwft_fifo[i]), // Write enable + .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word + .dout(dest_port_multi[i]), // Data out + .full(), + .nearly_full(), + .recieve_more_than_0(), + .recieve_more_than_1(), + .reset(reset), + .clk(clk), + .clear(clear_dspt_mulicast [i]) // clear the destination port once it got the entire packet + ); + + //TODO remove multiple_dest[i] to see if it works? + + assign clear_dspt_mulicast [i] = (reset_ivc[i] & multiple_dest[i]) ? dest_port_encoded[i] : {DSTPw{1'b0}}; + + // a fix priority arbiter. + multicast_dst_sel #( + .NOC_ID(NOC_ID) + ) sel_arb( + .destport_in(dest_port_multi[i]), + .destport_out(dest_port_encoded[i]) + ); + + //check if we have multiple port to send a packet to + is_onehot0 #( + .IN_WIDTH(DSTPw) + ) one_h ( + .in(dest_port_multi[i]), + .result(dst_onhot0[i]) + ); + assign multiple_dest[i]=~dst_onhot0[i]; + + end else begin : unicast + assign multiple_dest[i] = 1'b0; + + //lk_dst_fifo + fwft_fifo #( + .DATA_WIDTH(DSTPw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) lk_dest_fifo ( + .din (lk_destination_in_encoded), + .wr_en (wr_hdr_fwft_fifo_delay [i]), // Write enable + .rd_en (rd_hdr_fwft_fifo_delay [i]), // Read the next word + .dout (lk_destination_encoded [(i+1)*DSTPw-1 : i*DSTPw]), // Data out + .full (), + .nearly_full (), + .recieve_more_than_0 (), + .recieve_more_than_1 (), + .reset (reset), + .clk (clk) + ); + + /* verilator lint_off WIDTH */ + if( ROUTE_TYPE=="DETERMINISTIC") begin : dtrmn_dest + /* verilator lint_on WIDTH */ + //destport_fifo + fwft_fifo #( + .DATA_WIDTH(DSTPw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) dest_fifo ( + .din(destport_in_encoded), + .wr_en(wr_hdr_fwft_fifo[i]), // Write enable + .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word + .dout(dest_port_encoded[i]), // Data out + .full(), + .nearly_full(), + .recieve_more_than_0(), + .recieve_more_than_1(), + .reset(reset), + .clk(clk) + ); + + end else begin : adptv_dest + + fwft_fifo_with_output_clear #( + .DATA_WIDTH(DSTPw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) dest_fifo ( + .din(destport_in_encoded), + .wr_en(wr_hdr_fwft_fifo[i]), // Write enable + .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word + .dout(dest_port_encoded[i]), // Data out + .full(), + .nearly_full(), + .recieve_more_than_0(), + .recieve_more_than_1(), + .reset(reset), .clk(clk), - .reset(reset) - ); - */ - assign vc_weight_is_consumed[i] = 1'b1; - end else begin :no_wrra - assign vc_weight_is_consumed[i] = 1'bX; - end + .clear(destport_clear[i]) // clear other destination ports once one of them is selected + ); + + end// : adptv_dest + end//unicast + + destp_generator #( + .TOPOLOGY(TOPOLOGY), + .ROUTE_NAME(ROUTE_NAME), + .ROUTE_TYPE(ROUTE_TYPE), + .T1(T1), + .NL(T3), + .P(P), + .DSTPw(DSTPw), + .PLw(PLw), + .PPSw(PPSw), + .SELF_LOOP_EN (SELF_LOOP_EN), + .SW_LOC(SW_LOC), + .CAST_TYPE(CAST_TYPE) + ) decoder ( + .destport_one_hot (destport_one_hot[i]), + .dest_port_encoded(dest_port_encoded[i]), + .dest_port_out(dest_port[(i+1)*P_1-1 : i*P_1]), + .endp_localp_num(endp_localp_num[(i+1)*PLw-1 : i*PLw]), + .swap_port_presel(swap_port_presel[i]), + .port_pre_sel(port_pre_sel), + .odd_column(odd_column) + ); + + /* verilator lint_off WIDTH */ + if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + /* verilator lint_on WIDTH */ + // the router has multiple local ports. Save the destination local port + + fwft_fifo #( + .DATA_WIDTH(ELw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) local_dest_fifo ( + .din(endp_l_in), + .wr_en(wr_hdr_fwft_fifo[i]), // Write enable + .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word + .dout(endp_localp_num[(i+1)*PLw-1 : i*PLw]), // Data out + .full( ), + .nearly_full( ), + .recieve_more_than_0(), + .recieve_more_than_1(), + .reset(reset), + .clk(clk) + ); + /* verilator lint_off WIDTH */ + end else if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST") begin : fmesh + /* verilator lint_on WIDTH */ - end//for i + fwft_fifo #( + .DATA_WIDTH(Pw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) local_dest_fifo ( + .din(endp_p_in), + .wr_en(wr_hdr_fwft_fifo[i]), // Write enable + .rd_en(rd_hdr_fwft_fifo[i]), // Read the next word + .dout(endp_localp_num[(i+1)*PLw-1 : i*PLw]), // Data out + .full( ), + .nearly_full( ), + .recieve_more_than_0(), + .recieve_more_than_1(), + .reset(reset), + .clk(clk) + ); + + end else begin : single_local + assign endp_localp_num[(i+1)*PLw-1 : i*PLw] = {PLw{1'bx}}; + end + + /* verilator lint_off WIDTH */ + if(SWA_ARBITER_TYPE != "RRA")begin : wrra + /* verilator lint_on WIDTH */ + /* + weight_control #( + .WEIGHTw(WEIGHTw) + ) wctrl_per_vc ( + .sw_is_granted(ivc_num_getting_sw_grant[i]), + .flit_is_tail(flit_is_tail[i]), + .weight_is_consumed_o(vc_weight_is_consumed[i]), + .iport_weight(1), //(iport_weight), + .clk(clk), + .reset(reset) + ); + */ + assign vc_weight_is_consumed[i] = 1'b1; + end else begin :no_wrra + assign vc_weight_is_consumed[i] = 1'bX; + end + + end//for i - - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra - /* verilator lint_on WIDTH */ - wire granted_flit_is_tail; + /* verilator lint_off WIDTH */ + if(SWA_ARBITER_TYPE != "RRA")begin : wrra + /* verilator lint_on WIDTH */ + wire granted_flit_is_tail; - onehot_mux_1D #( - .W(1), - .N(V) - )onehot_mux( - .in(flit_is_tail), - .out(granted_flit_is_tail), - .sel(ivc_num_getting_sw_grant) - ); - - weight_control#( - .ARBITER_TYPE(SWA_ARBITER_TYPE), - .SW_LOC(SW_LOC), - .WEIGHTw(WEIGHTw), - .WRRA_CONFIG_INDEX(WRRA_CONFIG_INDEX), - .P(P), - .SELF_LOOP_EN(SELF_LOOP_EN) - ) - wctrl_iport - ( - .sw_is_granted(any_ivc_sw_request_granted), - .flit_is_tail(granted_flit_is_tail), - .weight_is_consumed_o(iport_weight_is_consumed), - .iport_weight(iport_weight), - .oports_weight(oports_weight), - .granted_dest_port(granted_dest_port), - .refresh_w_counter(refresh_w_counter), - .clk(clk), - .reset(reset) - ); - - end else begin :no_wrra - assign iport_weight_is_consumed=1'bX; - assign oports_weight = {WP{1'bX}}; - end + onehot_mux_1D #( + .W(1), + .N(V) + )onehot_mux( + .in(flit_is_tail), + .out(granted_flit_is_tail), + .sel(ivc_num_getting_sw_grant) + ); + + weight_control#( + .ARBITER_TYPE(SWA_ARBITER_TYPE), + .SW_LOC(SW_LOC), + .WEIGHTw(WEIGHTw), + .WRRA_CONFIG_INDEX(WRRA_CONFIG_INDEX), + .P(P), + .SELF_LOOP_EN(SELF_LOOP_EN) + ) wctrl_iport ( + .sw_is_granted(any_ivc_sw_request_granted), + .flit_is_tail(granted_flit_is_tail), + .weight_is_consumed_o(iport_weight_is_consumed), + .iport_weight(iport_weight), + .oports_weight(oports_weight), + .granted_dest_port(granted_dest_port), + .refresh_w_counter(refresh_w_counter), + .clk(clk), + .reset(reset) + ); - /* verilator lint_off WIDTH */ - if(COMBINATION_TYPE == "COMB_NONSPEC") begin : nonspec - /* verilator lint_on WIDTH */ - - - - - /* - - always @(posedge clk) - if ((ivc_not_empty & flit_is_tail2) != (ivc_not_empty & flit_is_tail))begin - $display("ERROR: %b !=%b",flit_is_tail2 , flit_is_tail ) ; - $finish; - end - */ - - - flit_buffer #( - .V(V), - .B(PORT_B), // buffer space :flit per VC - .SSA_EN(SSA_EN), - .Fw(Fw), - .PCK_TYPE(PCK_TYPE), - .CAST_TYPE(CAST_TYPE), - .DEBUG_EN(DEBUG_EN) - ) - the_flit_buffer - ( - - .din(flit_in), // Data in - .vc_num_wr(vc_num_in),//write virtual channel - .vc_num_rd(nonspec_first_arbiter_granted_ivc),//read virtual channel - .wr_en(flit_in_wr), // Write enable - .rd_en(any_ivc_sw_request_granted), // Read the next word - .dout(buffer_out), // Data out - .vc_not_empty(ivc_not_empty), - .reset(reset), - .clk(clk), - .ssa_rd(ssa_ctrl_in.ivc_num_getting_sw_grant), - .multiple_dest( multiple_dest ), - .sub_rd_ptr_ld(reset_ivc) , - .flit_is_tail(flit_is_tail) - ); - - end else begin :spec//not nonspec comb - - - flit_buffer #( - .V(V), - .B(PORT_B), // buffer space :flit per VC - .SSA_EN(SSA_EN), - .Fw(Fw), - .PCK_TYPE(PCK_TYPE), - .CAST_TYPE(CAST_TYPE), - .DEBUG_EN(DEBUG_EN) - ) - the_flit_buffer - ( - .din(flit_in), // Data in - .vc_num_wr(vc_num_in),//write virtual channel - .vc_num_rd(ivc_num_getting_sw_grant),//read virtual channel - .wr_en(flit_in_wr), // Write enable - .rd_en(any_ivc_sw_request_granted), // Read the next word - .dout(buffer_out), // Data out - .vc_not_empty(ivc_not_empty), - .reset(reset), - .clk(clk), - .ssa_rd(ssa_ctrl_in.ivc_num_getting_sw_grant), - .multiple_dest( multiple_dest ), - .sub_rd_ptr_ld(reset_ivc) , - .flit_is_tail(flit_is_tail) - - ); - - end - - - /* verilator lint_off WIDTH */ - if(CAST_TYPE== "UNICAST") begin : unicast - /* verilator lint_on WIDTH */ - look_ahead_routing #( - .NOC_ID(NOC_ID), - .T1(T1), - .T2(T2), - .T3(T3), - .T4(T4), - .P(P), - .RAw(RAw), - .EAw(EAw), - .DAw(DAw), - .DSTPw(DSTPw), - .SW_LOC(SW_LOC), - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE) - ) - lk_routing - ( - .current_r_addr(current_r_addr), - .neighbors_r_addr(neighbors_r_addr), - .dest_e_addr(dest_e_addr_in), - .src_e_addr(src_e_addr_in), - .destport_encoded(destport_in_encoded), - .lkdestport_encoded(lk_destination_in_encoded), - .reset(reset), - .clk(clk) - ); - end // unicast - - endgenerate - - - - header_flit_update_lk_route_ovc #( - .NOC_ID(NOC_ID), - .P(P) - ) the_flit_update ( - .flit_in (buffer_out), - .flit_out (flit_out), - .vc_num_in(ivc_num_getting_sw_grant), - .lk_dest_all_in (lk_destination_encoded), - .assigned_ovc_num (assigned_ovc_num), - .any_ivc_sw_request_granted(any_ivc_sw_request_granted), - .lk_dest_not_registered(lk_destination_in_encoded), - .sel (sel), - .reset (reset), - .clk (clk) - ); - - - //synthesis translate_off - //synopsys translate_off - generate - if(DEBUG_EN) begin :debg - - always @ (posedge clk) begin - if((|vsa_ctrl_in.ivc_num_getting_sw_grant) & (|ssa_ctrl_in.ivc_num_getting_sw_grant))begin - $display("%t: ERROR: VSA/SSA conflict: an input port cannot get both sva and ssa grant at the same time %m",$time); - $finish; - end - end//always - - for (i=0;i0 && vc_num_in[j] && t1[j]==0)begin - $display("%t : Parser:current_r=%h, class_in=%h, destport_in=%h, dest_e_addr_in=%h, src_e_addr_in=%h, vc_num_in=%h,hdr_flit_wr=%h, hdr_flg_in=%h,tail_flg_in=%h ",$time,current_r_addr, class_in, destport_in, dest_e_addr_in, src_e_addr_in, vc_num_in,hdr_flit_wr, hdr_flg_in,tail_flg_in); - t1[j]<=1; - end - end - end - end - endgenerate - `endif - // synopsys translate_on - // synthesis translate_on - - - - + end else begin :no_wrra + assign iport_weight_is_consumed=1'bX; + assign oports_weight = {WP{1'bX}}; + end + + /* verilator lint_off WIDTH */ + if(COMBINATION_TYPE == "COMB_NONSPEC") begin : nonspec + /* verilator lint_on WIDTH */ + + /* + always @(posedge clk) + if ((ivc_not_empty & flit_is_tail2) != (ivc_not_empty & flit_is_tail))begin + $display("ERROR: %b !=%b",flit_is_tail2 , flit_is_tail ) ; + $finish; + end + */ + + flit_buffer #( + .V(V), + .B(PORT_B), // buffer space :flit per VC + .SSA_EN(SSA_EN), + .Fw(Fw), + .PCK_TYPE(PCK_TYPE), + .CAST_TYPE(CAST_TYPE), + .DEBUG_EN(DEBUG_EN) + ) the_flit_buffer ( + .din(flit_in), // Data in + .vc_num_wr(vc_num_in),//write virtual channel + .vc_num_rd(nonspec_first_arbiter_granted_ivc),//read virtual channel + .wr_en(flit_in_wr), // Write enable + .rd_en(any_ivc_sw_request_granted), // Read the next word + .dout(buffer_out), // Data out + .vc_not_empty(ivc_not_empty), + .reset(reset), + .clk(clk), + .ssa_rd(ssa_ctrl_in.ivc_num_getting_sw_grant), + .multiple_dest( multiple_dest ), + .sub_rd_ptr_ld(reset_ivc) , + .flit_is_tail(flit_is_tail) + ); + + end else begin :spec//not nonspec comb + + flit_buffer #( + .V(V), + .B(PORT_B), // buffer space :flit per VC + .SSA_EN(SSA_EN), + .Fw(Fw), + .PCK_TYPE(PCK_TYPE), + .CAST_TYPE(CAST_TYPE), + .DEBUG_EN(DEBUG_EN) + ) the_flit_buffer ( + .din(flit_in), // Data in + .vc_num_wr(vc_num_in),//write virtual channel + .vc_num_rd(ivc_num_getting_sw_grant),//read virtual channel + .wr_en(flit_in_wr), // Write enable + .rd_en(any_ivc_sw_request_granted), // Read the next word + .dout(buffer_out), // Data out + .vc_not_empty(ivc_not_empty), + .reset(reset), + .clk(clk), + .ssa_rd(ssa_ctrl_in.ivc_num_getting_sw_grant), + .multiple_dest( multiple_dest ), + .sub_rd_ptr_ld(reset_ivc) , + .flit_is_tail(flit_is_tail) + ); + + end //:spec + + /* verilator lint_off WIDTH */ + if(CAST_TYPE== "UNICAST") begin : unicast + /* verilator lint_on WIDTH */ + look_ahead_routing #( + .NOC_ID(NOC_ID), + .T1(T1), + .T2(T2), + .T3(T3), + .T4(T4), + .P(P), + .RAw(RAw), + .EAw(EAw), + .DAw(DAw), + .DSTPw(DSTPw), + .SW_LOC(SW_LOC), + .TOPOLOGY(TOPOLOGY), + .ROUTE_NAME(ROUTE_NAME), + .ROUTE_TYPE(ROUTE_TYPE) + ) lk_routing ( + .current_r_addr(current_r_addr), + .neighbors_r_addr(neighbors_r_addr), + .dest_e_addr(dest_e_addr_in), + .src_e_addr(src_e_addr_in), + .destport_encoded(destport_in_encoded), + .lkdestport_encoded(lk_destination_in_encoded), + .reset(reset), + .clk(clk) + ); + end // unicast + + endgenerate + + + + header_flit_update_lk_route_ovc #( + .NOC_ID(NOC_ID), + .P(P) + ) the_flit_update ( + .flit_in (buffer_out), + .flit_out (flit_out), + .vc_num_in(ivc_num_getting_sw_grant), + .lk_dest_all_in (lk_destination_encoded), + .assigned_ovc_num (assigned_ovc_num), + .any_ivc_sw_request_granted(any_ivc_sw_request_granted), + .lk_dest_not_registered(lk_destination_in_encoded), + .sel (sel), + .reset (reset), + .clk (clk) + ); + + + `ifdef SIMULATION + generate + if(DEBUG_EN) begin :debg + + always @ (posedge clk) begin + if((|vsa_ctrl_in.ivc_num_getting_sw_grant) & (|ssa_ctrl_in.ivc_num_getting_sw_grant))begin + $display("%t: ERROR: VSA/SSA conflict: an input port cannot get both sva and ssa grant at the same time %m",$time); + $finish; + end + end//always + + for (i=0;i0 && vc_num_in[j] && t1[j]==0)begin + $display("%t : Parser:current_r=%h, class_in=%h, destport_in=%h, dest_e_addr_in=%h, src_e_addr_in=%h, vc_num_in=%h,hdr_flit_wr=%h, hdr_flg_in=%h,tail_flg_in=%h ",$time,current_r_addr, class_in, destport_in, dest_e_addr_in, src_e_addr_in, vc_num_in,hdr_flit_wr, hdr_flg_in,tail_flg_in); + t1[j]<=1; + end + end + end + end + `endif//MONITORE_PATH + endgenerate +`endif// SIMULATION endmodule - - - // decode and mask the destination port according to routing algorithm and topology module destp_generator #( - parameter TOPOLOGY="MESH", - parameter ROUTE_NAME="XY", - parameter ROUTE_TYPE="DETERMINISTIC", - parameter T1=3, - parameter NL=1, - parameter P=5, - parameter DSTPw=4, - parameter PLw=1, - parameter PPSw=4, - parameter SW_LOC=0, - parameter SELF_LOOP_EN="NO", - parameter CAST_TYPE = "UNICAST" - -) -( - destport_one_hot, - dest_port_encoded, - dest_port_out, - endp_localp_num, - swap_port_presel, - port_pre_sel, - odd_column + parameter TOPOLOGY="MESH", + parameter ROUTE_NAME="XY", + parameter ROUTE_TYPE="DETERMINISTIC", + parameter T1=3, + parameter NL=1, + parameter P=5, + parameter DSTPw=4, + parameter PLw=1, + parameter PPSw=4, + parameter SW_LOC=0, + parameter SELF_LOOP_EN="NO", + parameter CAST_TYPE = "UNICAST" +)( + destport_one_hot, + dest_port_encoded, + dest_port_out, + endp_localp_num, + swap_port_presel, + port_pre_sel, + odd_column ); - - localparam P_1= ( SELF_LOOP_EN=="NO")? P-1 : P; - input [DSTPw-1 : 0] dest_port_encoded; - input [PLw-1 : 0] endp_localp_num; - output [P_1-1: 0] dest_port_out; - output [P-1 : 0] destport_one_hot; - input swap_port_presel; - input [PPSw-1 : 0] port_pre_sel; - input odd_column; - - generate - - /* verilator lint_off WIDTH */ - if(CAST_TYPE!= "UNICAST") begin : muticast - /* verilator lint_on WIDTH */ - // destination port is not coded for multicast/broadcast - if( SELF_LOOP_EN=="NO") begin : nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) - remove_sw_loc - ( - .destport_in(dest_port_encoded), - .destport_out(dest_port_out) - ); - end else begin : slp - assign dest_port_out = dest_port_encoded; - end - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FATTREE" ) begin : fat - /* verilator lint_on WIDTH */ - fattree_destp_generator #( - .K(T1), - .P(P), - .SW_LOC(SW_LOC), - .DSTPw(DSTPw), - .SELF_LOOP_EN(SELF_LOOP_EN) - ) - destp_generator - ( - .dest_port_in_encoded(dest_port_encoded), - .dest_port_out(dest_port_out) - ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "TREE") begin :tree - /* verilator lint_on WIDTH */ - tree_destp_generator #( - .K(T1), - .P(P), - .SW_LOC(SW_LOC), - .DSTPw(DSTPw), - .SELF_LOOP_EN(SELF_LOOP_EN) - ) - destp_generator - ( - .dest_port_in_encoded(dest_port_encoded), - .dest_port_out(dest_port_out) - ); - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh - /* verilator lint_on WIDTH */ - mesh_torus_destp_generator #( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .P(P), - .DSTPw(DSTPw), - .NL(NL), - .PLw(PLw), - .PPSw(PPSw), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) - ) - destp_generator - ( - .dest_port_coded(dest_port_encoded), - .endp_localp_num(endp_localp_num), - .dest_port_out(dest_port_out), - .swap_port_presel(swap_port_presel), - .port_pre_sel(port_pre_sel), - .odd_column(odd_column)// only needed for odd even routing - ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "FMESH") begin :fmesh - /* verilator lint_on WIDTH */ - fmesh_destp_generator #( - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .P(P), - .DSTPw(DSTPw), - .NL(NL), - .PLw(PLw), - .PPSw(PPSw), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) - ) - destp_generator - ( - .dest_port_coded(dest_port_encoded), - .endp_localp_num(endp_localp_num), - .dest_port_out(dest_port_out), - .swap_port_presel(swap_port_presel), - .port_pre_sel(port_pre_sel), - .odd_column(odd_column) // only needed for odd even routing - ); - end else begin :custom - - custom_topology_destp_decoder #( - .ROUTE_TYPE(ROUTE_TYPE), - .DSTPw(DSTPw), - .P(P), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) - ) - destp_generator - ( - .dest_port_in_encoded(dest_port_encoded), - .dest_port_out(dest_port_out) - ); - end - - if(SELF_LOOP_EN=="NO") begin : nslp - add_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - )add - ( - .destport_in(dest_port_out), - .destport_out(destport_one_hot) - ); - - end else begin : slp - assign destport_one_hot = dest_port_out; - end - - endgenerate - - - - - + localparam P_1= ( SELF_LOOP_EN=="NO")? P-1 : P; + input [DSTPw-1 : 0] dest_port_encoded; + input [PLw-1 : 0] endp_localp_num; + output [P_1-1: 0] dest_port_out; + output [P-1 : 0] destport_one_hot; + input swap_port_presel; + input [PPSw-1 : 0] port_pre_sel; + input odd_column; + generate + /* verilator lint_off WIDTH */ + if(CAST_TYPE!= "UNICAST") begin : muticast + /* verilator lint_on WIDTH */ + // destination port is not coded for multicast/broadcast + if( SELF_LOOP_EN=="NO") begin : nslp + remove_sw_loc_one_hot #( + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(dest_port_encoded), + .destport_out(dest_port_out) + ); + end else begin : slp + assign dest_port_out = dest_port_encoded; + end + /* verilator lint_off WIDTH */ + end else if(TOPOLOGY == "FATTREE" ) begin : fat + /* verilator lint_on WIDTH */ + fattree_destp_generator #( + .K(T1), + .P(P), + .SW_LOC(SW_LOC), + .DSTPw(DSTPw), + .SELF_LOOP_EN(SELF_LOOP_EN) + ) + destp_generator + ( + .dest_port_in_encoded(dest_port_encoded), + .dest_port_out(dest_port_out) + ); + /* verilator lint_off WIDTH */ + end else if (TOPOLOGY == "TREE") begin :tree + /* verilator lint_on WIDTH */ + tree_destp_generator #( + .K(T1), + .P(P), + .SW_LOC(SW_LOC), + .DSTPw(DSTPw), + .SELF_LOOP_EN(SELF_LOOP_EN) + ) destp_generator ( + .dest_port_in_encoded(dest_port_encoded), + .dest_port_out(dest_port_out) + ); + /* verilator lint_off WIDTH */ + end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh + /* verilator lint_on WIDTH */ + mesh_torus_destp_generator #( + .TOPOLOGY(TOPOLOGY), + .ROUTE_NAME(ROUTE_NAME), + .ROUTE_TYPE(ROUTE_TYPE), + .P(P), + .DSTPw(DSTPw), + .NL(NL), + .PLw(PLw), + .PPSw(PPSw), + .SW_LOC(SW_LOC), + .SELF_LOOP_EN(SELF_LOOP_EN) + ) destp_generator ( + .dest_port_coded(dest_port_encoded), + .endp_localp_num(endp_localp_num), + .dest_port_out(dest_port_out), + .swap_port_presel(swap_port_presel), + .port_pre_sel(port_pre_sel), + .odd_column(odd_column)// only needed for odd even routing + ); + /* verilator lint_off WIDTH */ + end else if (TOPOLOGY == "FMESH") begin :fmesh + /* verilator lint_on WIDTH */ + fmesh_destp_generator #( + .ROUTE_NAME(ROUTE_NAME), + .ROUTE_TYPE(ROUTE_TYPE), + .P(P), + .DSTPw(DSTPw), + .NL(NL), + .PLw(PLw), + .PPSw(PPSw), + .SW_LOC(SW_LOC), + .SELF_LOOP_EN(SELF_LOOP_EN) + ) destp_generator ( + .dest_port_coded(dest_port_encoded), + .endp_localp_num(endp_localp_num), + .dest_port_out(dest_port_out), + .swap_port_presel(swap_port_presel), + .port_pre_sel(port_pre_sel), + .odd_column(odd_column) // only needed for odd even routing + ); + end else begin :custom + + custom_topology_destp_decoder #( + .ROUTE_TYPE(ROUTE_TYPE), + .DSTPw(DSTPw), + .P(P), + .SW_LOC(SW_LOC), + .SELF_LOOP_EN(SELF_LOOP_EN) + ) destp_generator ( + .dest_port_in_encoded(dest_port_encoded), + .dest_port_out(dest_port_out) + ); + end + /* verilator lint_off WIDTH */ + if(SELF_LOOP_EN=="NO") begin : nslp + /* verilator lint_on WIDTH */ + add_sw_loc_one_hot #( + .P(P), + .SW_LOC(SW_LOC) + )add ( + .destport_in(dest_port_out), + .destport_out(destport_one_hot) + ); + + end else begin : slp + assign destport_one_hot = dest_port_out; + end + endgenerate endmodule /****************** * custom_topology_destp_decoder * ***************/ - - module custom_topology_destp_decoder #( - parameter ROUTE_TYPE="DETERMINISTIC", - parameter DSTPw=4, - parameter P=5, - parameter SW_LOC=0, - parameter SELF_LOOP_EN="NO" - )( - dest_port_in_encoded, - dest_port_out - ); - - localparam - P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, - MAXW =2**DSTPw; - - input [DSTPw-1 : 0] dest_port_in_encoded; - output [P_1-1 : 0] dest_port_out; - - - wire [MAXW-1 : 0] dest_port_one_hot; - - bin_to_one_hot #( - .BIN_WIDTH(DSTPw), - .ONE_HOT_WIDTH(MAXW) - ) - conv - ( - .bin_code(dest_port_in_encoded), - .one_hot_code(dest_port_one_hot) - ); - generate - if( SELF_LOOP_EN=="NO") begin : nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) - remove_sw_loc - ( - .destport_in(dest_port_one_hot[P-1 : 0]), - .destport_out(dest_port_out) - ); - end else begin : slp - assign dest_port_out = dest_port_one_hot; - end - endgenerate - //synthesis translate_off - //synopsys translate_off - - initial begin - if( ROUTE_TYPE != "DETERMINISTIC") begin - $display("%t: ERROR: Custom topologies can only support deterministic routing in the current version of ProNoC",$time); - $finish; - end - end - - - //synopsys translate_on - //synthesis translate_on - + parameter ROUTE_TYPE="DETERMINISTIC", + parameter DSTPw=4, + parameter P=5, + parameter SW_LOC=0, + parameter SELF_LOOP_EN="NO" +)( + dest_port_in_encoded, + dest_port_out +); + + localparam + P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, + MAXW =2**DSTPw; + + input [DSTPw-1 : 0] dest_port_in_encoded; + output [P_1-1 : 0] dest_port_out; + + wire [MAXW-1 : 0] dest_port_one_hot; + + bin_to_one_hot #( + .BIN_WIDTH(DSTPw), + .ONE_HOT_WIDTH(MAXW) + ) conv ( + .bin_code(dest_port_in_encoded), + .one_hot_code(dest_port_one_hot) + ); + + generate + /* verilator lint_off WIDTH */ + if( SELF_LOOP_EN=="NO") begin : nslp + /* verilator lint_on WIDTH */ + remove_sw_loc_one_hot #( + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(dest_port_one_hot[P-1 : 0]), + .destport_out(dest_port_out) + ); + end else begin : slp + assign dest_port_out = dest_port_one_hot; + end + endgenerate + + `ifdef SIMULATION + initial begin + if( ROUTE_TYPE != "DETERMINISTIC") begin + $display("%t: ERROR: Custom topologies can only support deterministic routing in the current version of ProNoC",$time); + $finish; + end + end + `endif endmodule diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 27c9662..f56df3e 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -1,470 +1,448 @@ `include "pronoc_def.v" +/*********************************************************************** + ** File: router_top.v + ** + ** Copyright (C) 2014-2017 Alireza Monemi + ** + ** This file is part of ProNoC + ** + ** ProNoC ( stands for Prototype Network-on-chip) is free software: + ** you can redistribute it and/or modify it under the terms of the GNU + ** Lesser General Public License as published by the Free Software Foundation, + ** either version 2 of the License, or (at your option) any later version. + ** + ** ProNoC 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 Lesser General + ** Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with ProNoC. If not, see . + ** + ** + ** Description: + * ProNoC Top-Level Router + * This module implements a two-stage NoC router with optional bypass + * links for direct connections in the straight direction. + **************************************************************/ - -/**************************************************************************** - * router_top.v - ****************************************************************************/ - -/** - * Module: router_top - * - * add optional bypass links to two stage router. - */ module router_top #( - parameter NOC_ID=0, - parameter P=5 + parameter NOC_ID=0, + parameter ROUTER_ID=0, + parameter P=5 )( - current_r_id, - current_r_addr, - - chan_in, - chan_out, - - router_event, - - clk, - reset + current_r_id, + current_r_addr, + + chan_in, + chan_out, + + router_event, + + clk, + reset ); - - `NOC_CONF - - - localparam DISABLED =P; - - input [RAw-1 : 0] current_r_addr; - input [31 : 0] current_r_id; - - - input smartflit_chanel_t chan_in [P-1 : 0]; - output smartflit_chanel_t chan_out [P-1 : 0]; - - output router_event_t router_event [P-1 : 0]; - - - - input clk,reset; - - genvar i,j; - - - //synthesis translate_off - //synopsys translate_off - /* verilator lint_off WIDTH */ - initial begin - if((SSA_EN=="YES") &&(SMART_EN==1'b1))begin - $display("ERROR: Only one of the SMART or SAA can be enabled at the same time"); - $finish; - end - if((SMART_EN==1'b1) && COMBINATION_TYPE!="COMB_NONSPEC")begin - $display("ERROR: SMART only works with non-speculative VSA"); - $finish; - end - if((MIN_PCK_SIZE > 1) &&(PCK_TYPE == "SINGLE_FLIT")) begin - $display("ERROR: The minimum packet size must be set as one for single-flit packet type NoC"); - $finish; - end - if(((SSA_EN=="YES") ||(SMART_EN==1'b1)) && CAST_TYPE!="UNICAST") begin - $display("ERROR: SMART or SAA do not support muticast/braodcast packets"); - $finish; - end - - end - /* verilator lint_on WIDTH */ - - - - - - logic report_active_ivcs = 0; - - generate - for(i=0; i 1) &&(PCK_TYPE == "SINGLE_FLIT")) begin + $display("ERROR: The minimum packet size must be set as one for single-flit packet type NoC"); + $finish; + end + if(((SSA_EN=="YES") ||(SMART_EN==1'b1)) && CAST_TYPE!="UNICAST") begin + $display("ERROR: SMART or SAA do not support muticast/braodcast packets"); + $finish; + end + + end + /* verilator lint_on WIDTH */ + + logic report_active_ivcs = 0; + generate + for(i=0; i {V{1'b0}}) nb_router_active[ii]=1'b1; -// if(chan_out[ii].smart_chanel.requests > {SMART_NUM{1'b0}}) nb_router_active[ii]=1'b1; -// -// for(jj=0; jj {V{1'b0}}) nb_router_active[ii]=1'b1; +// if(chan_out[ii].smart_chanel.requests > {SMART_NUM{1'b0}}) nb_router_active[ii]=1'b1; +// +// for(jj=0; jj. - ** - ** - ** Description: - ** A two stage router + ** This file is part of ProNoC + ** + ** ProNoC ( stands for Prototype Network-on-chip) is free software: + ** you can redistribute it and/or modify it under the terms of the GNU + ** Lesser General Public License as published by the Free Software Foundation, + ** either version 2 of the License, or (at your option) any later version. + ** + ** ProNoC 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 Lesser General + ** Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with ProNoC. If not, see . + ** + ** + ** Description: + ** A two stage router ** stage1: lk-route,sw/VC allocation ** stage2: switch-traversal **************************************************************/ - - + module router_two_stage #( - parameter NOC_ID=0, - parameter P=5 + parameter NOC_ID=0, + parameter ROUTER_ID=0, + parameter P=5 ) ( - current_r_id, - current_r_addr,// connected to constant parameter - - chan_in, - chan_out, - - ctrl_in, - ctrl_out, - - //internal router status - ivc_info, - ovc_info, - iport_info, - oport_info, - - smart_ctrl_in, - - clk, - reset - + current_r_id, + current_r_addr,// connected to constant parameter + + chan_in, + chan_out, + + ctrl_in, + ctrl_out, + + //internal router status + ivc_info, + ovc_info, + iport_info, + oport_info, + + smart_ctrl_in, + + clk, + reset ); - - `NOC_CONF - - - // The current/neighbor routers addresses/port. These values are fixed in each router and they are supposed to be given as parameter. - // However, in order to give an identical RTL code to each router, they are given as input ports. The identical RTL code reduces the - // compilation time. Note that they wont be implemented as input ports in the final synthesized code. - - input [RAw-1 : 0] current_r_addr; - input [31:0] current_r_id; - - input flit_chanel_t chan_in [P-1 : 0]; - output flit_chanel_t chan_out [P-1 : 0]; - input ctrl_chanel_t ctrl_in [P-1 : 0]; - output ctrl_chanel_t ctrl_out [P-1 : 0]; - input clk,reset; - - - output ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; - output ovc_info_t ovc_info [P-1 : 0][V-1 : 0]; - output iport_info_t iport_info [P-1 : 0]; - output oport_info_t oport_info [P-1 : 0]; - - input smart_ctrl_t smart_ctrl_in [P-1 : 0]; - - - vsa_ctrl_t vsa_ctrl [P-1 : 0]; - - localparam - PV = V * P, - VV = V*V, - PVV = PV * V, - P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, - PP_1 = P_1 * P, - PVP_1 = PV * P_1, - PFw = P*Fw, - CONG_ALw = CONGw* P, // congestion width per router - W = WEIGHTw, - WP = W * P, - WPP= WP * P, - PRAw= P * RAw; - - - flit_chanel_t chan_in_tmp [P-1 : 0]; - - - wire [PFw-1 : 0] flit_in_all; - wire [P-1 : 0] flit_in_wr_all; - wire [PV-1 : 0] credit_out_all; - wire [CONG_ALw-1 : 0] congestion_in_all; - - wire [PFw-1 : 0] flit_out_all; - wire [P-1 : 0] flit_out_wr_all; - wire [PV-1 : 0] credit_in_all; - wire [CONG_ALw-1 : 0] congestion_out_all; - - wire [PV-1 : 0] credit_release_out; - - - // old router verilog code - - - - //internal wires - wire [PV-1 : 0] ovc_allocated_all; - wire [PVV-1 : 0] granted_ovc_num_all; - wire [PV-1 : 0] ivc_num_getting_sw_grant; - wire [PV-1 : 0] ivc_num_getting_ovc_grant; - wire [PVV-1 : 0] spec_ovc_num_all; - wire [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; - wire [PV-1 : 0] spec_first_arbiter_granted_ivc_all; - wire [PP_1-1 : 0] nonspec_granted_dest_port_all; - wire [PP_1-1 : 0] spec_granted_dest_port_all; - wire [PP_1-1 : 0] granted_dest_port_all; - wire [P-1 : 0] any_ivc_sw_request_granted_all; - wire [P-1 : 0] any_ovc_granted_in_outport_all; - wire [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - // to vc/sw allocator - wire [PVP_1-1 : 0] dest_port_all; - wire [PV-1 : 0] ovc_is_assigned_all; - wire [PV-1 : 0] ivc_request_all; - wire [PV-1 : 0] assigned_ovc_not_full_all; - wire [PVV-1: 0] masked_ovc_request_all; - - wire [PV-1 : 0] vc_weight_is_consumed_all; - wire [P-1 : 0] iport_weight_is_consumed_all; + `NOC_CONF + + // The current/neighbor routers addresses/port. These values are fixed in each router and they are supposed to be given as parameter. + // However, in order to give an identical RTL code to each router, they are given as input ports. The identical RTL code reduces the + // compilation time. Note that they wont be implemented as input ports in the final synthesized code. + + input [RAw-1 : 0] current_r_addr; + input [31:0] current_r_id; + + input flit_chanel_t chan_in [P-1 : 0]; + output flit_chanel_t chan_out [P-1 : 0]; + input ctrl_chanel_t ctrl_in [P-1 : 0]; + output ctrl_chanel_t ctrl_out [P-1 : 0]; + input clk,reset; + + output ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + output ovc_info_t ovc_info [P-1 : 0][V-1 : 0]; + output iport_info_t iport_info [P-1 : 0]; + output oport_info_t oport_info [P-1 : 0]; + + input smart_ctrl_t smart_ctrl_in [P-1 : 0]; + + vsa_ctrl_t vsa_ctrl [P-1 : 0]; + + localparam + PV = V * P, + VV = V*V, + PVV = PV * V, + P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, + PP_1 = P_1 * P, + PVP_1 = PV * P_1, + PFw = P*Fw, + CONG_ALw = CONGw* P, // congestion width per router + W = WEIGHTw, + WP = W * P, + WPP= WP * P, + PRAw= P * RAw; + + flit_chanel_t chan_in_tmp [P-1 : 0]; + + wire [PFw-1 : 0] flit_in_all; + wire [P-1 : 0] flit_in_wr_all; + wire [PV-1 : 0] credit_out_all; + wire [CONG_ALw-1 : 0] congestion_in_all; + + wire [PFw-1 : 0] flit_out_all; + wire [P-1 : 0] flit_out_wr_all; + wire [PV-1 : 0] credit_in_all; + wire [CONG_ALw-1 : 0] congestion_out_all; + + wire [PV-1 : 0] credit_release_out; + + // old router verilog code + + //internal wires + wire [PV-1 : 0] ovc_allocated_all; + wire [PVV-1 : 0] granted_ovc_num_all; + wire [PV-1 : 0] ivc_num_getting_sw_grant; + wire [PV-1 : 0] ivc_num_getting_ovc_grant; + wire [PVV-1 : 0] spec_ovc_num_all; + wire [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; + wire [PV-1 : 0] spec_first_arbiter_granted_ivc_all; + wire [PP_1-1 : 0] nonspec_granted_dest_port_all; + wire [PP_1-1 : 0] spec_granted_dest_port_all; + wire [PP_1-1 : 0] granted_dest_port_all; + wire [P-1 : 0] any_ivc_sw_request_granted_all; + wire [P-1 : 0] any_ovc_granted_in_outport_all; + wire [P-1 : 0] granted_dst_is_from_a_single_flit_pck; + + // to vc/sw allocator + wire [PVP_1-1 : 0] dest_port_all; + wire [PV-1 : 0] ovc_is_assigned_all; + wire [PV-1 : 0] ivc_request_all; + wire [PV-1 : 0] assigned_ovc_not_full_all; + wire [PVV-1: 0] masked_ovc_request_all; + wire [PV-1 : 0] vc_weight_is_consumed_all; + wire [P-1 : 0] iport_weight_is_consumed_all; wire [PV-1 : 0] vsa_ovc_released_all; wire [PV-1 : 0] vsa_credit_decreased_all; - // to/from the crossbar - wire [PFw-1 : 0] iport_flit_out_all; - wire [P-1 : 0] ssa_flit_wr_all; - logic [PP_1-1 : 0] granted_dest_port_all_delayed; - wire [PFw-1 : 0] crossbar_flit_out_all; - wire [P-1 : 0] crossbar_flit_out_wr_all; - wire [PFw-1 : 0] link_flit_out_all; - wire [P-1 : 0] link_flit_out_wr_all; - wire [PV-1 : 0] flit_is_tail_all; - + // to/from the crossbar + wire [PFw-1 : 0] iport_flit_out_all; + wire [P-1 : 0] ssa_flit_wr_all; + logic [PP_1-1 : 0] granted_dest_port_all_delayed; + wire [PFw-1 : 0] crossbar_flit_out_all; + wire [P-1 : 0] crossbar_flit_out_wr_all; + wire [PFw-1 : 0] link_flit_out_all; + wire [P-1 : 0] link_flit_out_wr_all; + wire [PV-1 : 0] flit_is_tail_all; - //to weight control - wire [WP-1 : 0] iport_weight_all; - wire [WPP-1: 0] oports_weight_all; - wire refresh_w_counter; - - - //ctrl port - wire [PRAw-1 : 0] neighbors_r_addr; - wire [CRDTw-1 : 0 ] credit_init_val_in [P-1 : 0][V-1 : 0]; - wire [CRDTw-1 : 0 ] credit_init_val_out [P-1 : 0][V-1 : 0]; - - - - - - - genvar i,j; - generate - for (i=0; i0 && t2[i]==0)begin - $display("%t :Out router (id=%d, addr=%h, port=%d), flitout=%h",$time,current_r_id,current_r_addr,i,flit_out_all[(i+1)*Fw-1 : i*Fw]); - t2[i]<=1; - end - - if(flit_in_wr_all[i]>0 && t1[i]==0)begin - $display("%t :In router (id=%d, addr=%h, port=%d), flitin=%h",$time,current_r_id,current_r_addr,i,flit_in_all[(i+1)*Fw-1 : i*Fw]); - t1[i]<=1; - end - + assign vsa_ctrl[i].ovc_is_allocated = ovc_allocated_all [(i+1)*V-1: i*V]; + assign vsa_ctrl[i].ovc_is_released = vsa_ovc_released_all[(i+1)*V-1: i*V]; + assign vsa_ctrl[i].ivc_num_getting_sw_grant = ivc_num_getting_sw_grant [(i+1)*V-1: i*V]; + assign vsa_ctrl[i].ivc_num_getting_ovc_grant=ivc_num_getting_ovc_grant [(i+1)*V-1: i*V]; + assign vsa_ctrl[i].ivc_reset=flit_is_tail_all[(i+1)*V-1: i*V] & ivc_num_getting_sw_grant[(i+1)*V-1: i*V]; + assign vsa_ctrl[i].buff_space_decreased = vsa_credit_decreased_all[(i+1)*V-1: i*V]; + assign vsa_ctrl[i].ivc_granted_ovc_num = granted_ovc_num_all[(i+1)*VV-1: i*VV]; + if(SELF_LOOP_EN == "NO") begin :nslp + add_sw_loc_one_hot #( + .P(P), + .SW_LOC(i) + )add( + .destport_in(granted_dest_port_all[(i+1)*P_1-1: i*P_1]), + .destport_out(iport_info[i].granted_oport_one_hot[P-1 : 0]) + ); + end else begin :slp + assign iport_info[i].granted_oport_one_hot[P-1 : 0] = granted_dest_port_all[(i+1)*P_1-1: i*P_1]; + end - end - end - end - endgenerate - `endif - - - - /* - - - + for (j=0;j0 && t2[i]==0)begin + $display("%t :Out router (id=%d, addr=%h, port=%d), flitout=%h",$time,current_r_id,current_r_addr,i,flit_out_all[(i+1)*Fw-1 : i*Fw]); + t2[i]<=1; + end + + if(flit_in_wr_all[i]>0 && t1[i]==0)begin + $display("%t :In router (id=%d, addr=%h, port=%d), flitin=%h",$time,current_r_id,current_r_addr,i,flit_in_all[(i+1)*Fw-1 : i*Fw]); + t1[i]<=1; + end + end + end //always + end //for + `endif //MONITORE_PATH + endgenerate + /* reg [10 : 0] counter; reg [31 : 0] flit_counter; always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin + if(`pronoc_reset) begin flit_counter <=0; counter <= 0; end else begin if(flit_in_wr_all>0 )begin counter <=0; - flit_counter<=flit_counter+1'b1; - + flit_counter<=flit_counter+1'b1; end else begin counter <= counter+1'b1; if( counter == 512 ) $display("%t : total flits received in (x=%d,Y=%d) is %d ",$time,current_r_addr,current_y,flit_counter); end end end - */ - - -//TRACE_DUMP_PER is defined in pronoc_def file - - + */ + + +//TRACE_DUMP_PER_[NOC/ROUTER/PORT] macro definition should be in pronoc_def.v file + + `ifdef TRACE_DUMP_PER_NoC - pronoc_trace_dump #( - .NOC_ID(NOC_ID), - .P(P), - .TRACE_DUMP_PER("NOC"), //NOC, ROUTER, PORT - .CYCLE_REPORT(0) // 1 : enable, 0 : disable - - )dump1 - ( - .current_r_id(current_r_id), - .chan_in(chan_in), - .chan_out(chan_out), - .clk(clk) - ); -`endif + pronoc_trace_dump #( + .NOC_ID(NOC_ID), + .P(P), + .TRACE_DUMP_PER("NOC"), //NOC, ROUTER, PORT + .CYCLE_REPORT(0) // 1 : enable, 0 : disable + ) dump1 ( + .current_r_id(current_r_id), + .chan_in(chan_in), + .chan_out(chan_out), + .clk(clk) + ); +`endif `ifdef TRACE_DUMP_PER_ROUTER - pronoc_trace_dump #( - .NOC_ID(NOC_ID), - .P(P), - .TRACE_DUMP_PER("ROUTER"), //NOC, ROUTER, PORT - .CYCLE_REPORT(0) // 1 : enable, 0 : disable - - )dump2 - ( - .current_r_id(current_r_id), - .chan_in(chan_in), - .chan_out(chan_out), - .clk(clk) - ); -`endif + pronoc_trace_dump #( + .NOC_ID(NOC_ID), + .P(P), + .TRACE_DUMP_PER("ROUTER"), //NOC, ROUTER, PORT + .CYCLE_REPORT(0) // 1 : enable, 0 : disable + ) dump2 ( + .current_r_id(current_r_id), + .chan_in(chan_in), + .chan_out(chan_out), + .clk(clk) + ); +`endif `ifdef TRACE_DUMP_PER_PORT - pronoc_trace_dump #( - .NOC_ID(NOC_ID), - .P(P), - .TRACE_DUMP_PER("PORT"), //NOC, ROUTER, PORT - .CYCLE_REPORT(0) // 1 : enable, 0 : disable - - )dump3 - ( - .current_r_id(current_r_id), - .chan_in(chan_in), - .chan_out(chan_out), - .clk(clk) - ); -`endif - - - - - //synopsys translate_on - //synthesis translate_on - + pronoc_trace_dump #( + .NOC_ID(NOC_ID), + .P(P), + .TRACE_DUMP_PER("PORT"), //NOC, ROUTER, PORT + .CYCLE_REPORT(0) // 1 : enable, 0 : disable + )dump3 ( + .current_r_id(current_r_id), + .chan_in(chan_in), + .chan_out(chan_out), + .clk(clk) + ); +`endif +`endif //SIMULATION endmodule - - - -module credit_release_gen #( - parameter NOC_ID=0, - parameter CREDIT_NUM=4 -) -( - clk, - reset, - en, - credit_out -); - - `NOC_CONF - - input clk, reset; - input en; - output reg credit_out; - - localparam W=log2(CREDIT_NUM +1); - - reg [W-1 : 0] counter; - wire counter_is_zero = counter=={W{1'b0}}; - wire counter_is_max = counter==CREDIT_NUM; - wire counter_incr = (en & counter_is_zero ) | (~counter_is_zero & ~counter_is_max); - - - - - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin - counter <= {W{1'b0}}; - credit_out<=1'b0; - end else begin - if(counter_incr) begin - counter<= counter +1'b1; - credit_out<=1'b1; - end else begin - credit_out<=1'b0; - end - end - end - - -endmodule - - - - -//synthesis translate_off +`ifdef SIMULATION module pronoc_trace_dump #( - parameter NOC_ID=0, - parameter P = 6, - parameter TRACE_DUMP_PER= "ROUTER", //NOC, ROUTER, PORT - parameter CYCLE_REPORT=0 // 1 : enable, 0 : disable + parameter NOC_ID=0, + parameter P = 6, + parameter TRACE_DUMP_PER= "ROUTER", //NOC, ROUTER, PORT + parameter CYCLE_REPORT=0 // 1 : enable, 0 : disable ) ( - current_r_id, - chan_in, - chan_out, - clk + current_r_id, + chan_in, + chan_out, + clk ); - - - `NOC_CONF - - input [31:0] current_r_id; - input flit_chanel_t chan_in [P-1 : 0]; - input flit_chanel_t chan_out [P-1 : 0]; - input clk; - - pronoc_trace_dump_sub #( - .NOC_ID(NOC_ID), - .P(P), - .TRACE_DUMP_PER(TRACE_DUMP_PER), //NOC, ROUTER, PORT - .DIRECTION("in"), // in,out - .CYCLE_REPORT(CYCLE_REPORT) // 1 : enable, 0 : disable - - )dump_in - ( - .current_r_id(current_r_id), - .chan_in(chan_in), - .clk(clk) - ); - - pronoc_trace_dump_sub #( - .NOC_ID(NOC_ID), - .P(P), - .TRACE_DUMP_PER(TRACE_DUMP_PER), //NOC, ROUTER, PORT - .DIRECTION("out"), // in,out - .CYCLE_REPORT(CYCLE_REPORT) // 1 : enable, 0 : disable - - )dump_out - ( - .current_r_id(current_r_id), - .chan_in(chan_out), - .clk(clk) - ); + + `NOC_CONF + + input [31:0] current_r_id; + input flit_chanel_t chan_in [P-1 : 0]; + input flit_chanel_t chan_out [P-1 : 0]; + input clk; + + pronoc_trace_dump_sub #( + .NOC_ID(NOC_ID), + .P(P), + .TRACE_DUMP_PER(TRACE_DUMP_PER), //NOC, ROUTER, PORT + .DIRECTION("in"), // in,out + .CYCLE_REPORT(CYCLE_REPORT) // 1 : enable, 0 : disable + ) dump_in ( + .current_r_id(current_r_id), + .chan_in(chan_in), + .clk(clk) + ); + + pronoc_trace_dump_sub #( + .NOC_ID(NOC_ID), + .P(P), + .TRACE_DUMP_PER(TRACE_DUMP_PER), //NOC, ROUTER, PORT + .DIRECTION("out"), // in,out + .CYCLE_REPORT(CYCLE_REPORT) // 1 : enable, 0 : disable + ) dump_out ( + .current_r_id(current_r_id), + .chan_in(chan_out), + .clk(clk) + ); endmodule module pronoc_trace_dump_sub #( - parameter NOC_ID=0, - parameter P = 6, - parameter TRACE_DUMP_PER= "ROUTER", //NOC, ROUTER, PORT - parameter DIRECTION="in", // in,out - parameter CYCLE_REPORT=0 // 1 : enable, 0 : disable -) ( - current_r_id, - chan_in, - clk + parameter NOC_ID=0, + parameter P = 6, + parameter TRACE_DUMP_PER= "ROUTER", //NOC, ROUTER, PORT + parameter DIRECTION="in", // in,out + parameter CYCLE_REPORT=0 // 1 : enable, 0 : disable +)( + current_r_id, + chan_in, + clk ); - - - - `NOC_CONF - - - - input [31:0] current_r_id; - input flit_chanel_t chan_in [P-1 : 0]; - input clk; - - integer out; - string fname [P-1 : 0]; - - genvar p; - generate - for (p=0;p0) begin + out = $fopen(fname[p],"a"); + if(CYCLE_REPORT) $fwrite(out,"%t:",$time); + $fwrite(out, "credit %s:%h Port %0d\n",DIRECTION, chan_in[p].credit,p); + $fclose(out); + end + end + end + endgenerate +endmodule +`endif // SIMULATION - always @(posedge clk) begin - if(chan_in[p].flit_wr) begin - out = $fopen(fname[p],"a"); - if(CYCLE_REPORT) $fwrite(out,"%t:",$time); - $fwrite(out, "Flit %s: Port %0d, Payload: %h\n",DIRECTION, p, chan_in[p].flit); - $fclose(out); - end - if(chan_in[p].credit>0) begin - out = $fopen(fname[p],"a"); - if(CYCLE_REPORT) $fwrite(out,"%t:",$time); - $fwrite(out, "credit %s:%h Port %0d\n",DIRECTION, chan_in[p].credit,p); - $fclose(out); - end - end - end - endgenerate -endmodule -//synthesis translate_on +module credit_release_gen #( + parameter NOC_ID=0, + parameter CREDIT_NUM=4 +)( + clk, + reset, + en, + credit_out +); + + `NOC_CONF + + input clk, reset; + input en; + output reg credit_out; + + localparam W=log2(CREDIT_NUM +1); + + reg [W-1 : 0] counter; + wire counter_is_zero = counter=={W{1'b0}}; + wire counter_is_max = counter==CREDIT_NUM; + wire counter_incr = (en & counter_is_zero ) | (~counter_is_zero & ~counter_is_max); + + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + counter <= {W{1'b0}}; + credit_out<=1'b0; + end else begin + if(counter_incr) begin + counter<= counter +1'b1; + credit_out<=1'b1; + end else begin + credit_out<=1'b0; + end + end + end + +endmodule \ No newline at end of file From 7d14ae6801f9d400fe98f7e775ecb0c48b648fc1 Mon Sep 17 00:00:00 2001 From: amonemi Date: Sun, 2 Feb 2025 02:10:49 +0100 Subject: [PATCH 004/107] add hetro_vc to input ports --- .../configurations/default/Fattree_k3_L3_st | 3 +- .../configurations/default/bintree_k3_L3_st | 4 +- .../synthetic_sim/reports/default_report | 126 + .../synthetic_sim/src/deafult_noc_param | 175 +- mpsoc/rtl/src_noc/flit_buffer.sv | 2274 ++++++++--------- mpsoc/rtl/src_noc/input_ports.sv | 89 +- mpsoc/rtl/src_noc/pronoc_pkg.sv | 582 ++--- 7 files changed, 1556 insertions(+), 1697 deletions(-) diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/Fattree_k3_L3_st b/mpsoc/Integration_test/synthetic_sim/configurations/default/Fattree_k3_L3_st index 3f51129..e8816f6 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/default/Fattree_k3_L3_st +++ b/mpsoc/Integration_test/synthetic_sim/configurations/default/Fattree_k3_L3_st @@ -5,4 +5,5 @@ $model = bless( { "T2" => "3", "B" => "5", "ROUTE_NAME" => "\"NCA_STRAIGHT_UP\"", -}, 'ProNOC' ); \ No newline at end of file + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/bintree_k3_L3_st b/mpsoc/Integration_test/synthetic_sim/configurations/default/bintree_k3_L3_st index 9482df8..85fc4b5 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/default/bintree_k3_L3_st +++ b/mpsoc/Integration_test/synthetic_sim/configurations/default/bintree_k3_L3_st @@ -1,9 +1,9 @@ $model = bless( { - noc_param'=> { + 'noc_param'=> { "TOPOLOGY" => "\"TREE\"", "T1" => "3", "T2" => "3", "B" => "5", "ROUTE_NAME" => "\"NCA\"", } -}, 'ProNOC' ); \ No newline at end of file +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/reports/default_report b/mpsoc/Integration_test/synthetic_sim/reports/default_report index 72e7467..606a952 100644 --- a/mpsoc/Integration_test/synthetic_sim/reports/default_report +++ b/mpsoc/Integration_test/synthetic_sim/reports/default_report @@ -1,7 +1,133 @@ Verification Results: +****************************bintree_k3_L3_st : Compile *******************************: + model is generated successfully. +****************************custom1_topology : Compile *******************************: + model is generated successfully. +****************************Fattree_k3_L3_st : Compile *******************************: + model is generated successfully. +****************************fmesh_1x1_openpiton : Compile *******************************: + model is generated successfully. +****************************fmesh_2x2_openpiton : Compile *******************************: + model is generated successfully. +****************************fmesh_8x8_2cycle_xy : Compile *******************************: + model is generated successfully. +****************************fmesh_8x8_openpiton : Compile *******************************: + model is generated successfully. +****************************mesh_2x2_openpiton : Compile *******************************: + model is generated successfully. ****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: model is generated successfully. +****************************mesh_4x4_smart3 : Compile *******************************: + model is generated successfully. +****************************mesh_4x4_v1_B15 : Compile *******************************: + model is generated successfully. +****************************mesh_4x4x3_2cycle_xy : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_2cycle_adaptive : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_2cycle_west_first : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_2cycle_xy : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_4vc_4c : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_b2 : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_sbp6_xy : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_single_flit : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_ssa_xy : Compile *******************************: + model is generated successfully. +****************************star_6 : Compile *******************************: + model is generated successfully. +****************************torus_8x8_2cycle_xy : Compile *******************************: + model is generated successfully. +****************************bintree_k3_L3_st : random traffic *******************************: + Passed: zero load (2,14.5705) saturation (14,400.884) +****************************custom1_topology : random traffic *******************************: + Passed: zero load (2,13.0626) saturation (42,65.4283) +****************************Fattree_k3_L3_st : random traffic *******************************: + Passed: zero load (2,13.5991) saturation (62,98.8008) +****************************fmesh_1x1_openpiton : random traffic *******************************: + Passed: zero load (2,7.06202) saturation (66,51.0968) +****************************fmesh_2x2_openpiton : random traffic *******************************: + Passed: zero load (2,8.27536) saturation (54,67.4686) +****************************fmesh_8x8_2cycle_xy : random traffic *******************************: + Passed: zero load (2,19.5638) saturation (18,137.798) +****************************fmesh_8x8_openpiton : random traffic *******************************: + Passed: zero load (2,14.4245) saturation (30,98.3569) +****************************mesh_2x2_openpiton : random traffic *******************************: + Passed: zero load (2,9.10156) saturation (66,72.3384) ****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: Passed: zero load (2,14.4623) saturation (22,261.684) +****************************mesh_4x4_smart3 : random traffic *******************************: + Passed: zero load (2,10.1271) saturation (42,72.4117) +****************************mesh_4x4_v1_B15 : random traffic *******************************: + Passed: zero load (6,12.719) saturation (58,93.2747) +****************************mesh_4x4x3_2cycle_xy : random traffic *******************************: + Passed: zero load (2,12.7475) saturation (26,188.161) +****************************mesh_8x8_2cycle_adaptive : random traffic *******************************: + Passed: zero load (2,18.2154) saturation (34,186.128) +****************************mesh_8x8_2cycle_west_first : random traffic *******************************: + Passed: zero load (2,18.2239) saturation (34,154.392) +****************************mesh_8x8_2cycle_xy : random traffic *******************************: + Passed: zero load (2,18.2211) saturation (34,132.962) +****************************mesh_8x8_4vc_4c : random traffic *******************************: + Passed: zero load (2,18.0557) saturation (26,162.893) +****************************mesh_8x8_b2 : random traffic *******************************: + Passed: zero load (2,22.1073) saturation (30,198.439) +****************************mesh_8x8_sbp6_xy : random traffic *******************************: + Passed: zero load (2,11.1597) saturation (34,119.674) +****************************mesh_8x8_single_flit : random traffic *******************************: + Passed: zero load (2,12.7369) saturation (58,65.8427) +****************************mesh_8x8_ssa_xy : random traffic *******************************: + Passed: zero load (2,14.769) saturation (34,111.6) +****************************star_6 : random traffic *******************************: + Passed: zero load (2,7.27692) saturation (62,57.3078) +****************************torus_8x8_2cycle_xy : random traffic *******************************: + Passed: zero load (2,16.8517) saturation (38,120.208) +****************************bintree_k3_L3_st : transposed 1 traffic *******************************: + Passed: zero load (2,14.5436) saturation (14,430.149) +****************************custom1_topology : transposed 1 traffic *******************************: + Passed: zero load (2,12.6827) saturation (34,68.3986) +****************************Fattree_k3_L3_st : transposed 1 traffic *******************************: + Passed: zero load (26,13.4638) saturation (100,-) +****************************fmesh_1x1_openpiton : transposed 1 traffic *******************************: + Passed: zero load (46,6.99433) saturation (100,-) +****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: + Passed: zero load (2,8.99642) saturation (54,71.4902) +****************************fmesh_8x8_2cycle_xy : transposed 1 traffic *******************************: + Passed: zero load (2,21.6193) saturation (14,142.818) +****************************fmesh_8x8_openpiton : transposed 1 traffic *******************************: + Passed: zero load (2,15.916) saturation (26,118.048) +****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: + Passed: zero load (2,8.7482) saturation (100,-) ****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: Passed: zero load (2,14.8953) saturation (26,146.747) +****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: + Passed: zero load (2,10.5055) saturation (34,60.2796) +****************************mesh_4x4_v1_B15 : transposed 1 traffic *******************************: + Passed: zero load (2,13.6902) saturation (38,106.686) +****************************mesh_4x4x3_2cycle_xy : transposed 1 traffic *******************************: + Passed: zero load (2,13.0755) saturation (14,126.234) +****************************mesh_8x8_2cycle_adaptive : transposed 1 traffic *******************************: + Passed: zero load (2,19.3604) saturation (26,108.443) +****************************mesh_8x8_2cycle_west_first : transposed 1 traffic *******************************: + Passed: zero load (2,19.3588) saturation (22,102.056) +****************************mesh_8x8_2cycle_xy : transposed 1 traffic *******************************: + Passed: zero load (2,19.3582) saturation (18,124.569) +****************************mesh_8x8_4vc_4c : transposed 1 traffic *******************************: + Passed: zero load (2,19.2371) saturation (18,114.964) +****************************mesh_8x8_b2 : transposed 1 traffic *******************************: + Passed: zero load (2,23.5649) saturation (18,118.423) +****************************mesh_8x8_sbp6_xy : transposed 1 traffic *******************************: + Passed: zero load (2,11.3748) saturation (18,119.786) +****************************mesh_8x8_single_flit : transposed 1 traffic *******************************: + Passed: zero load (2,14.0386) saturation (26,70.9042) +****************************mesh_8x8_ssa_xy : transposed 1 traffic *******************************: + Passed: zero load (2,15.3919) saturation (18,123.223) +****************************star_6 : transposed 1 traffic *******************************: + Passed: zero load (2,6.83981) saturation (100,-) +****************************torus_8x8_2cycle_xy : transposed 1 traffic *******************************: + Passed: zero load (2,18.0133) saturation (18,134.597) diff --git a/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param b/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param index 7f2f3cd..3f5025a 100644 --- a/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param +++ b/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param @@ -1,87 +1,88 @@ -$model = bless( { - 'noc_param' => { -"TOPOLOGY" => "\"MESH\"", -"T1" => "8", -"T2" => "8", -"T3" => "1", -"V" => "2", -"B" => "4", -"LB" => "B", -"Fpay" => "32", -"ROUTE_NAME" => "\"XY\"", -"PCK_TYPE" => " \"MULTI_FLIT\"", -"MIN_PCK_SIZE" => "2", -"BYTE_EN" => "0", -"SSA_EN" => "\"NO\"", -"CONGESTION_INDEX" => "3", -"ESCAP_VC_MASK" => "2'b01", -"VC_REALLOCATION_TYPE" => "\"NONATOMIC\"", -"COMBINATION_TYPE" => "\"COMB_NONSPEC\"", -"MUX_TYPE" => "\"BINARY\"", -"C" => "0", -"CLASS_SETTING"=> "{V{1'b1}}", -"DEBUG_EN" => "1", -"ADD_PIPREG_AFTER_CROSSBAR" => "1'b0", -"FIRST_ARBITER_EXT_P_EN" => "1", -"SWA_ARBITER_TYPE" => "\"RRA\"", -"WEIGHTw" => "4", -"AVC_ATOMIC_EN" => "0", -"CLASS_SETTING" => "{V{1'b1}}", -"SMART_MAX" => "0", -"SELF_LOOP_EN" => "\"NO\"", -"MAX_PCK_NUM " => " 1000000000", -"MAX_PCK_SIZ " => " 16383" , -"MAX_SIM_CLKs" => " 1000000000", -"TIMSTMP_FIFO_NUM " => " 16", -"CVw"=> "(C==0)? V : C * V", -"CAST_TYPE" => "\"UNICAST\"", -"MCAST_ENDP_LIST" => "'b1111", - - - }, - - - 'parameters_order' => { -'noc_param' => -[ - 'TOPOLOGY', - 'T1', - 'T2', - 'T3', - 'V', - 'B', - 'LB', - 'Fpay', - 'ROUTE_NAME', - 'PCK_TYPE', - 'MIN_PCK_SIZE', - 'BYTE_EN', - 'SSA_EN', - 'SMART_MAX', - 'CONGESTION_INDEX', - 'ESCAP_VC_MASK', - 'VC_REALLOCATION_TYPE', - 'COMBINATION_TYPE', - 'MUX_TYPE', - 'C', -'CLASS_SETTING', - 'DEBUG_EN', - 'ADD_PIPREG_AFTER_CROSSBAR', - 'FIRST_ARBITER_EXT_P_EN', - 'SWA_ARBITER_TYPE', - 'WEIGHTw', - 'SELF_LOOP_EN', - 'AVC_ATOMIC_EN', -"MAX_PCK_NUM " , -"MAX_PCK_SIZ ", -"MAX_SIM_CLKs", -"TIMSTMP_FIFO_NUM ", -"CVw", -"CAST_TYPE", -"MCAST_ENDP_LIST" - ], - -} - - }, -); +$model = bless({ + 'noc_param' => { + "TOPOLOGY" => "\"MESH\"", + "T1" => "8", + "T2" => "8", + "T3" => "1", + "V" => "2", + "B" => "4", + "LB" => "B", + "Fpay" => "32", + "ROUTE_NAME" => "\"XY\"", + "PCK_TYPE" => " \"MULTI_FLIT\"", + "MIN_PCK_SIZE" => "2", + "BYTE_EN" => "0", + "SSA_EN" => "\"NO\"", + "CONGESTION_INDEX" => "3", + "ESCAP_VC_MASK" => "2'b01", + "VC_REALLOCATION_TYPE" => "\"NONATOMIC\"", + "COMBINATION_TYPE" => "\"COMB_NONSPEC\"", + "MUX_TYPE" => "\"BINARY\"", + "C" => "0", + "CLASS_SETTING"=> "{V{1'b1}}", + "DEBUG_EN" => "1", + "ADD_PIPREG_AFTER_CROSSBAR" => "1'b0", + "FIRST_ARBITER_EXT_P_EN" => "1", + "SWA_ARBITER_TYPE" => "\"RRA\"", + "WEIGHTw" => "4", + "AVC_ATOMIC_EN" => "0", + "CLASS_SETTING" => "{V{1'b1}}", + "SMART_MAX" => "0", + "SELF_LOOP_EN" => "\"NO\"", + "MAX_PCK_NUM " => " 1000000000", + "MAX_PCK_SIZ " => " 16383" , + "MAX_SIM_CLKs" => " 1000000000", + "TIMSTMP_FIFO_NUM " => " 16", + "CVw"=> "(C==0)? V : C * V", + "CAST_TYPE" => "\"UNICAST\"", + "MCAST_ENDP_LIST" => "'b1111", + "HETRO_VC"=> "0", + "MAX_ROUTER"=>"1", + "MAX_PORT"=>"1", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{0}", + }, + + 'parameters_order' => { + 'noc_param' => [ + 'TOPOLOGY', + 'T1', + 'T2', + 'T3', + 'V', + 'B', + 'LB', + 'Fpay', + 'ROUTE_NAME', + 'PCK_TYPE', + 'MIN_PCK_SIZE', + 'BYTE_EN', + 'SSA_EN', + 'SMART_MAX', + 'CONGESTION_INDEX', + 'ESCAP_VC_MASK', + 'VC_REALLOCATION_TYPE', + 'COMBINATION_TYPE', + 'MUX_TYPE', + 'C', + 'CLASS_SETTING', + 'DEBUG_EN', + 'ADD_PIPREG_AFTER_CROSSBAR', + 'FIRST_ARBITER_EXT_P_EN', + 'SWA_ARBITER_TYPE', + 'WEIGHTw', + 'SELF_LOOP_EN', + 'AVC_ATOMIC_EN', + "MAX_PCK_NUM " , + "MAX_PCK_SIZ ", + "MAX_SIM_CLKs", + "TIMSTMP_FIFO_NUM ", + "CVw", + "CAST_TYPE", + "MCAST_ENDP_LIST", + "HETRO_VC", + "MAX_ROUTER", + "MAX_PORT", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]", + ], + } +},); diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 1b7241a..fd74ad7 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -1,584 +1,489 @@ `include "pronoc_def.v" /********************************************************************** - ** File: flit_buffer.v + ** File: flit_buffer.v ** - ** Copyright (C) 2014-2017 Alireza Monemi + ** Copyright (C) 2014-2017 Alireza Monemi ** - ** This file is part of ProNoC + ** This file is part of ProNoC ** - ** ProNoC ( stands for Prototype Network-on-chip) is free software: - ** you can redistribute it and/or modify it under the terms of the GNU - ** Lesser General Public License as published by the Free Software Foundation, - ** either version 2 of the License, or (at your option) any later version. + ** ProNoC ( stands for Prototype Network-on-chip) is free software: + ** you can redistribute it and/or modify it under the terms of the GNU + ** Lesser General Public License as published by the Free Software Foundation, + ** either version 2 of the License, or (at your option) any later version. ** - ** ProNoC 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 Lesser General - ** Public License for more details. + ** ProNoC 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 Lesser General + ** Public License for more details. ** - ** You should have received a copy of the GNU Lesser General Public - ** License along with ProNoC. If not, see . + ** You should have received a copy of the GNU Lesser General Public + ** License along with ProNoC. If not, see . ** ** - ** Description: - ** Input buffer module. All VCs located in the same router - ** input port share one single FPGA BRAM + ** Description: + ** Input buffer module. All VCs located in the same router + ** input port share one single FPGA BRAM ** **************************************************************/ -module flit_buffer - #( - parameter B =4, - parameter SSA_EN="YES", // "YES" , "NO" - parameter Fw=32, - parameter PCK_TYPE ="MULTI_FLIT", - parameter CAST_TYPE = "UNICAST", - parameter DEBUG_EN = 1, - parameter V=1 - ) - ( - din, // Data in - vc_num_wr,//write virtual channel - vc_num_rd,//read virtual channel - wr_en, // Write enable - rd_en, // Read the next word - dout, // Data out - vc_not_empty, - reset, - clk, - ssa_rd, +module flit_buffer +#( + parameter ROUTER_ID = 0, + parameter SW_LOC = 0, + parameter B = 4 +)( + din, // Data in + vc_num_wr,//write virtual channel + vc_num_rd,//read virtual channel + wr_en, // Write enable + rd_en, // Read the next word + dout, // Data out + vc_not_empty, + reset, + clk, + ssa_rd, + + //for multicast + multiple_dest, // incr rd-sub + sub_rd_ptr_ld, // load rd_ptr to sub_rd_pt + flit_is_tail +); + + `NOC_CONF + + + localparam + Bw = (B==1)? 1 : log2(B), + BV = B * V, + BVw = log2(BV), + Vw = (V==1)? 1 : log2(V), + DEPTHw = log2(B+1), + BwV = Bw * V, + BVwV = BVw * V, + RESTw = Fw -2-V , + PTRw = ((2**Bw)==B)? Bw : BVw, // if B is power of 2 PTRw is Bw else is BVw + ARRAYw = PTRw * V, + /* verilator lint_off WIDTH */ + RAM_DATA_WIDTH = (PCK_TYPE == "MULTI_FLIT")? Fw - V : Fw - V -2; + /* verilator lint_on WIDTH */ + + input [Fw-1 :0] din; // Data in + input [V-1 :0] vc_num_wr;//write virtual chanel + input [V-1 :0] vc_num_rd;//read virtual chanel + input wr_en; // Write enable + input rd_en; // Read the next word + output [Fw-1 :0] dout; // Data out + output [V-1 :0] vc_not_empty; + input reset; + input clk; + input [V-1 :0] ssa_rd; + input [V-1 :0] multiple_dest; + input [V-1 :0] sub_rd_ptr_ld; + output [V-1 : 0] flit_is_tail; + + //pointers + wire [PTRw- 1 : 0] rd_ptr [V-1 :0]; + wire [PTRw- 1 : 0] wr_ptr [V-1 :0]; + reg [PTRw- 1 : 0] rd_ptr_next [V-1 :0]; + reg [PTRw- 1 : 0] wr_ptr_next [V-1 :0]; + reg [PTRw- 1 : 0] sub_rd_ptr_next [V-1 :0]; + wire [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; + wire [PTRw-1 : 0] ptr_tmp [V-1 : 0]; + wire [ARRAYw-1 : 0] rd_ptr_array; + wire [ARRAYw-1 : 0] wr_ptr_array; + + wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_din; + wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_dout; + wire [V-1 : 0] wr; + wire [V-1 : 0] rd; + wire [DEPTHw-1 : 0] depth [V-1 :0]; + reg [DEPTHw-1 : 0] depth_next [V-1 :0]; + wire [DEPTHw-1 : 0] sub_depth [V-1 :0]; + reg [DEPTHw-1 : 0] sub_depth_next [V-1 :0]; + + reg [B-1 : 0] tail_fifo [V-1 : 0]; + wire [1 : 0] flgs_in, flgs_out; + wire [V-1: 0] vc_in; + wire [RESTw-1 :0 ] flit_rest_in,flit_rest_out; + wire [V-1 : 0] sub_rd; + wire [V-1 : 0] sub_restore; + + assign wr = (wr_en)? vc_num_wr : {V{1'b0}}; + + genvar i; + generate + /* verilator lint_off WIDTH */ + if (CAST_TYPE != "UNICAST") begin : nouni + /* verilator lint_on WIDTH */ + assign sub_rd = (rd_en)? vc_num_rd : ssa_rd; + assign sub_restore = sub_rd_ptr_ld; + assign rd = (rd_en)? vc_num_rd & ~multiple_dest : ssa_rd & ~multiple_dest; + end else begin : unicast + assign rd = (rd_en)? vc_num_rd : ssa_rd; + end + + /* verilator lint_off WIDTH */ + if (PCK_TYPE == "MULTI_FLIT") begin :multi + /* verilator lint_on WIDTH */ + assign {flgs_in,vc_in,flit_rest_in}=din; + assign fifo_ram_din = {flgs_in,flit_rest_in}; + assign {flgs_out,flit_rest_out} = fifo_ram_dout; + assign dout = {flgs_out,{V{1'bX}},flit_rest_out}; + end else begin : single + assign fifo_ram_din = din[RAM_DATA_WIDTH-1 : 0]; + assign dout = {2'b11,{V{1'bX}},fifo_ram_dout}; + end + + for(i=0;i 0); - - - - - end else begin : unicast - assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = rd_ptr[i]; - assign vc_not_empty [i] = (depth[i] > 0); - end - end//for - - - - - if((2**Bw)==B)begin :pow2 - /***************** - Buffer width is power of 2 - ******************/ - - wire [Bw-1 : 0] vc_wr_addr; - wire [Bw-1 : 0] vc_rd_addr; - wire [Vw-1 : 0] wr_select_addr; - wire [Vw-1 : 0] rd_select_addr; - wire [Bw+Vw-1 : 0] wr_addr; - wire [Bw+Vw-1 : 0] rd_addr; - - assign wr_addr = {wr_select_addr,vc_wr_addr}; - assign rd_addr = {rd_select_addr,vc_rd_addr}; - + /* verilator lint_off WIDTH */ + if (CAST_TYPE != "UNICAST") begin + /* verilator lint_on WIDTH */ + assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = sub_rd_ptr[i]; + localparam RESET_TO = ((2**Bw)==B)? 0 : B*i; + pronoc_register #(.W(PTRw),.RESET_TO(RESET_TO)) reg4 (.in(sub_rd_ptr_next[i]), .out(sub_rd_ptr[i]), .reset(reset), .clk(clk)); - onehot_mux_1D #( - .W(Bw), - .N(V) - ) - wr_ptr_mux - ( - .in(wr_ptr_array), - .out(vc_wr_addr), - .sel(vc_num_wr) - ); - - - onehot_mux_1D #( - .W(Bw), - .N(V) - ) - rd_ptr_mux - ( - .in(rd_ptr_array), - .out(vc_rd_addr), - .sel(vc_num_rd) - ); - - one_hot_to_bin #( - .ONE_HOT_WIDTH(V) - ) - wr_vc_start_addr - ( - .one_hot_code(vc_num_wr), - .bin_code(wr_select_addr) - ); - - one_hot_to_bin #( - .ONE_HOT_WIDTH(V) - ) - rd_vc_start_addr - ( - .one_hot_code(vc_num_rd), - .bin_code(rd_select_addr) - ); - - fifo_ram #( - .DATA_WIDTH (RAM_DATA_WIDTH), - .ADDR_WIDTH (BVw ), - .SSA_EN(SSA_EN) - ) - the_queue - ( - .wr_data(fifo_ram_din), - .wr_addr(wr_addr[BVw-1 : 0]), - .rd_addr(rd_addr[BVw-1 : 0]), - .wr_en(wr_en), - .rd_en(rd_en), - .clk(clk), - .rd_data(fifo_ram_dout) - ); - - for(i=0;i 0); + end else begin : unicast + assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = rd_ptr[i]; + assign vc_not_empty [i] = (depth[i] > 0); + end + end//for + +/***************** + Buffer width is + power of 2 +******************/ + if((2**Bw)==B)begin : pow2 - /* verilator lint_off WIDTH */ - if (CAST_TYPE != "UNICAST") begin :multicast - /* verilator lint_on WIDTH */ - - - - - always @ (*)begin - sub_rd_ptr_next[i] = sub_rd_ptr[i]; - if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i]; - /* verilator lint_off WIDTH */ - else if(sub_rd[i]) sub_rd_ptr_next[i] = (sub_rd_ptr[i]==(B*(i+1))-1)? (B*i) : sub_rd_ptr [i]+ 1'h1; - /* verilator lint_on WIDTH */ - end - - /* verilator lint_off WIDTH */ - assign ptr_tmp [i] = sub_rd_ptr[i]-(B*i); - assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][ptr_tmp [i]] :1'b1; - /* verilator lint_on WIDTH */ - - - end else begin : unicast - /* verilator lint_off WIDTH */ - assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][rd_ptr[i]-(B*i)] : 1'b1; - /* verilator lint_on WIDTH */ - end - end//FOR - - - onehot_mux_1D #( - .W(BVw), - .N(V) - ) - wr_mux - ( - .in(wr_ptr_array), - .out(wr_addr), - .sel(vc_num_wr) - ); - - onehot_mux_1D #( - .W(BVw), - .N(V) - ) - rd_mux - ( - .in(rd_ptr_array), - .out(rd_addr), - .sel(vc_num_rd) - ); - - fifo_ram_mem_size #( - .DATA_WIDTH (RAM_DATA_WIDTH), - .MEM_SIZE (BV ), - .SSA_EN(SSA_EN) - ) - the_queue - ( - .wr_data (fifo_ram_din), - .wr_addr (wr_addr), - .rd_addr (rd_addr), - .wr_en (wr_en), - .rd_en (rd_en), - .clk (clk), - .rd_data (fifo_ram_dout) - ); - end - endgenerate - - - - - - - //synthesis translate_off - //synopsys translate_off - - - - generate - - if(DEBUG_EN) begin :dbg - always @(posedge clk) begin - if(wr_en && vc_num_wr == {V{1'b0}})begin - $display("%t: ERROR: Attempt to write when no wr VC is asserted: %m",$time); - $finish; - end - if(rd_en && vc_num_rd == {V{1'b0}})begin - $display("%t: ERROR: Attempt to read when no rd VC is asserted: %m",$time); - $finish; - end - end - end //DEBUG_EN - - - for(i=0;i2) begin :mwb2 - wire [MUX_SEL_WIDTH-1 : 0] mux_sel; - wire [DEPTH_DATA_WIDTH-1 : 0] depth_2; - wire empty; - wire out_sel ; - if(DATA_WIDTH>1) begin :wb1 - wire [MAX_DEPTH-2 : 0] mux_in [DATA_WIDTH-1 :0]; - wire [DATA_WIDTH-1 : 0] mux_out; - reg [MAX_DEPTH-2 : 0] shiftreg [DATA_WIDTH-1 :0]; - - for(i=0;i2) begin :mwb2 + wire [MUX_SEL_WIDTH-1 : 0] mux_sel; + wire [DEPTH_DATA_WIDTH-1 : 0] depth_2; + wire empty; + wire out_sel ; + if(DATA_WIDTH>1) begin :wb1 + wire [MAX_DEPTH-2 : 0] mux_in [DATA_WIDTH-1 :0]; + wire [DATA_WIDTH-1 : 0] mux_out; + reg [MAX_DEPTH-2 : 0] shiftreg [DATA_WIDTH-1 :0]; + + for(i=0;i= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; + assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; + assign recieve_more_than_0 = ~ empty; + assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); + assign out_sel = (recieve_more_than_1) ? 1'b1 : 1'b0; + assign out_ld = (depth !=0 )? rd_en : wr_en; + assign depth_2 = depth - 2; + assign mux_sel = depth_2[MUX_SEL_WIDTH-1 : 0]; - - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; - assign recieve_more_than_0 = ~ empty; - assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); - assign out_sel = (recieve_more_than_1) ? 1'b1 : 1'b0; - assign out_ld = (depth !=0 )? rd_en : wr_en; - assign depth_2 = depth - 2; - assign mux_sel = depth_2[MUX_SEL_WIDTH-1 : 0] ; - - end else if ( MAX_DEPTH == 2) begin :mw2 + end else if ( MAX_DEPTH == 2) begin :mw2 - reg [DATA_WIDTH-1 : 0] register; - + reg [DATA_WIDTH-1 : 0] register; - always @(posedge clk ) begin - if(wr_en) register <= din; - end //always + always @(posedge clk ) begin + if(wr_en) register <= din; + end //always - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign out_ld = (depth !=0 )? rd_en : wr_en; - assign recieve_more_than_0 = (depth != {DEPTH_DATA_WIDTH{1'b0}}); - assign recieve_more_than_1 = ~( depth == 0 || depth== 1 ); - assign dout_next = (recieve_more_than_1) ? register : din; - - - end else begin :mw1 // MAX_DEPTH == 1 - assign out_ld = wr_en; - assign dout_next = din; - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full= 1'b1; - assign recieve_more_than_0 = full; - assign recieve_more_than_1 = 1'b0; - end - - - - endgenerate - - - pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg1 (.in(depth_next), .out(depth), .reset(reset), .clk(clk)); - pronoc_register #(.W(DATA_WIDTH)) reg2 (.in(dout_next_ld), .out(dout ), .reset(reset), .clk(clk)); - - always @ (*)begin - depth_next = depth; - dout_next_ld = dout; - if (wr_en & ~rd_en) depth_next = depth + 1'h1; - else if (~wr_en & rd_en) depth_next = depth - 1'h1; - if (out_ld) dout_next_ld = dout_next; - end//always - - - + assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; + assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; + assign out_ld = (depth !=0 )? rd_en : wr_en; + assign recieve_more_than_0 = (depth != {DEPTH_DATA_WIDTH{1'b0}}); + assign recieve_more_than_1 = ~( depth == 0 || depth== 1 ); + assign dout_next = (recieve_more_than_1) ? register : din; - //synthesis translate_off - //synopsys translate_off - always @(posedge clk) - begin - - if (wr_en & ~rd_en & full) begin - $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); - $finish; - end - /* verilator lint_off WIDTH */ - if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin - $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); - $finish; - end - if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin - $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); - $finish; - end - /* verilator lint_on WIDTH */ - - end // always @ (posedge clk) - - //synopsys translate_on - //synthesis translate_on - - - - -endmodule - - - - - - - - - + end else begin :mw1 // MAX_DEPTH == 1 + assign out_ld = wr_en; + assign dout_next = din; + assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; + assign nearly_full= 1'b1; + assign recieve_more_than_0 = full; + assign recieve_more_than_1 = 1'b0; + end + endgenerate + + pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg1 (.in(depth_next), .out(depth), .reset(reset), .clk(clk)); + pronoc_register #(.W(DATA_WIDTH)) reg2 (.in(dout_next_ld), .out(dout ), .reset(reset), .clk(clk)); + + always @ (*)begin + depth_next = depth; + dout_next_ld = dout; + if (wr_en & ~rd_en) depth_next = depth + 1'h1; + else if (~wr_en & rd_en) depth_next = depth - 1'h1; + if (out_ld) dout_next_ld = dout_next; + end//always + +/********************************************* +* Validating Parameters/Simulation +*********************************************/ + `ifdef SIMULATION + always @(posedge clk) begin + if (wr_en & ~rd_en & full) begin + $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); + $finish; + end + /* verilator lint_off WIDTH */ + if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin + $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); + $finish; + end + if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin + $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); + $finish; + end + /* verilator lint_on WIDTH */ + end // always @ (posedge clk) + + `endif//SIMULATION +endmodule /********************* - + fwft_fifo_with_output_clear - each individual output bit has + each individual output bit has its own clear signal - + **********************/ - - - - module fwft_fifo_with_output_clear #( - parameter DATA_WIDTH = 2, - parameter MAX_DEPTH = 2, - parameter IGNORE_SAME_LOC_RD_WR_WARNING="NO" // "YES" , "NO" - ) - ( - din, // Data in - wr_en, // Write enable - rd_en, // Read the next word - dout, // Data out - full, - nearly_full, - recieve_more_than_0, - recieve_more_than_1, - reset, - clk, - clear - - ); - - input [DATA_WIDTH-1:0] din; - input wr_en; - input rd_en; - output [DATA_WIDTH-1:0] dout; - output full; - output nearly_full; - output recieve_more_than_0; - output recieve_more_than_1; - input reset; - input clk; - input [DATA_WIDTH-1:0] clear; - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log22) begin :mwb2 - wire [MUX_SEL_WIDTH-1 : 0] mux_sel; - wire [DEPTH_DATA_WIDTH-1 : 0] depth_2; - wire empty; - wire out_sel ; - if(DATA_WIDTH>1) begin :wb1 - wire [MAX_DEPTH-2 : 0] mux_in [DATA_WIDTH-1 :0]; - wire [DATA_WIDTH-1 : 0] mux_out; - reg [MAX_DEPTH-2 : 0] shiftreg [DATA_WIDTH-1 :0]; - - for(i=0;i2) begin :mwb2 + wire [MUX_SEL_WIDTH-1 : 0] mux_sel; + wire [DEPTH_DATA_WIDTH-1 : 0] depth_2; + wire empty; + wire out_sel ; + if(DATA_WIDTH>1) begin :wb1 + wire [MAX_DEPTH-2 : 0] mux_in [DATA_WIDTH-1 :0]; + wire [DATA_WIDTH-1 : 0] mux_out; + reg [MAX_DEPTH-2 : 0] shiftreg [DATA_WIDTH-1 :0]; + + for(i=0;i= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; - assign recieve_more_than_0 = ~ empty; - assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); - assign out_sel = (recieve_more_than_1) ? 1'b1 : 1'b0; - assign out_ld = (depth !=0 )? rd_en : wr_en; - assign depth_2 = depth-'d2; - assign mux_sel = depth_2[MUX_SEL_WIDTH-1 : 0] ; - - end else if ( MAX_DEPTH == 2) begin :mw2 + end else begin : w1 + wire [MAX_DEPTH-2 : 0] mux_in; + wire mux_out; + reg [MAX_DEPTH-2 : 0] shiftreg; + + always @(posedge clk ) begin + if(wr_en) shiftreg <= {shiftreg[MAX_DEPTH-3 : 0] ,din}; + end + + assign mux_in = shiftreg; + assign mux_out = mux_in[mux_sel]; + assign dout_next = (out_sel) ? mux_out : din; + end //w1 - reg [DATA_WIDTH-1 : 0] register; + assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; + assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; + assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; + assign recieve_more_than_0 = ~ empty; + assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); + assign out_sel = (recieve_more_than_1) ? 1'b1 : 1'b0; + assign out_ld = (depth !=0 )? rd_en : wr_en; + assign depth_2 = depth-'d2; + assign mux_sel = depth_2[MUX_SEL_WIDTH-1 : 0] ; - always @(posedge clk ) begin - if(wr_en) register <= din; - end //always + end else if ( MAX_DEPTH == 2) begin :mw2 - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign out_ld = (depth !=0 )? rd_en : wr_en; - assign recieve_more_than_0 = (depth != {DEPTH_DATA_WIDTH{1'b0}}); - assign recieve_more_than_1 = ~( depth == 0 || depth== 1 ); - assign dout_next = (recieve_more_than_1) ? register : din; - - end else begin :mw1 // MAX_DEPTH == 1 - assign out_ld = wr_en; - assign dout_next = din; - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full= 1'b1; - assign recieve_more_than_0 = full; - assign recieve_more_than_1 = 1'b0; - end - endgenerate - - - - - pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg1 (.in(depth_next), .out(depth), .reset(reset), .clk(clk)); - pronoc_register #(.W(DATA_WIDTH)) reg2 (.in(dout_next_ld), .out(dout ), .reset(reset), .clk(clk)); - - always @ (*)begin - depth_next = depth; - if (wr_en & ~rd_en) depth_next = depth + 1'h1; - else if (~wr_en & rd_en) depth_next = depth - 1'h1; - end//always - - - - generate - for(i=0;i= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; + assign out_ld = (depth !=0 )? rd_en : wr_en; + assign recieve_more_than_0 = (depth != {DEPTH_DATA_WIDTH{1'b0}}); + assign recieve_more_than_1 = ~( depth == 0 || depth== 1 ); + assign dout_next = (recieve_more_than_1) ? register : din; + + end else begin :mw1 // MAX_DEPTH == 1 + assign out_ld = wr_en; + assign dout_next = din; + assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; + assign nearly_full= 1'b1; + assign recieve_more_than_0 = full; + assign recieve_more_than_1 = 1'b0; + end + endgenerate + + pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg1 (.in(depth_next), .out(depth), .reset(reset), .clk(clk)); + pronoc_register #(.W(DATA_WIDTH)) reg2 (.in(dout_next_ld), .out(dout ), .reset(reset), .clk(clk)); + + always @ (*)begin + depth_next = depth; + if (wr_en & ~rd_en) depth_next = depth + 1'h1; + else if (~wr_en & rd_en) depth_next = depth - 1'h1; + end//always + + generate + for(i=0;i= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; + assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; + assign recieve_more_than_0 = ~ empty; + assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); + + + `ifdef SIMULATION + always @(posedge clk) begin + if (wr_en & ~rd_en & full) begin + $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); + $finish; + end + /* verilator lint_off WIDTH */ + if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin + $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); + $finish; + end + if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin + $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); + $finish; + end + /* verilator lint_on WIDTH */ + end // always + `endif // SIMULATION - localparam DEPTH_DATA_WIDTH = log2(MAX_DEPTH +1); - - reg valid_next; - wire valid; - wire pass_din_to_out_reg, out_reg_wr_en, bram_out_is_valid_next; - wire bram_out_is_valid; - wire bram_empty, bram_rd_en, bram_wr_en; - wire [DATA_WIDTH-1 : 0] bram_dout; - wire [DATA_WIDTH-1 : 0] out_reg; - reg [DATA_WIDTH-1 : 0] out_reg_next; - - wire [DEPTH_DATA_WIDTH-1 : 0] depth; - reg [DEPTH_DATA_WIDTH-1 : 0] depth_next; - - assign dout = (bram_out_is_valid)? bram_dout : out_reg; - - - assign pass_din_to_out_reg = (wr_en & ~valid)| // a write has been recived while the reg_flit is not valid - (wr_en & valid & bram_empty & rd_en); //or its valid but bram is empty and its got a read request - - assign bram_rd_en = (rd_en & ~bram_empty); - assign bram_wr_en = (pass_din_to_out_reg)? 1'b0 :wr_en ; //make sure not write on the Bram if the reg fifo is empty - - - assign out_reg_wr_en = pass_din_to_out_reg | bram_out_is_valid; - - assign bram_out_is_valid_next = (bram_rd_en )? (rd_en & ~bram_empty): 1'b0; - - - always @(*) begin - valid_next = valid; - if(depth_next == {DEPTH_DATA_WIDTH{1'b0}}) valid_next =1'b0; - else if(out_reg_wr_en) valid_next =1'b1; - else if(bram_empty & rd_en) valid_next =1'b0; - end - - - bram_based_fifo #( - .Dw(DATA_WIDTH),//data_width - .B(MAX_DEPTH)// buffer num - )bram_fifo( - .din(din), - .wr_en(bram_wr_en), - .rd_en(bram_rd_en), - .dout(bram_dout), - .full(), - .nearly_full(), - .empty(bram_empty), - .reset(reset), - .clk(clk) - ); - - - - - pronoc_register #(.W(DATA_WIDTH) ) reg1 (.in(out_reg_next ), .out(out_reg), .reset(reset), .clk(clk)); - pronoc_register #(.W(1) ) reg2 (.in(valid_next ), .out(valid), .reset(reset), .clk(clk)); - pronoc_register #(.W(1) ) reg3 (.in(bram_out_is_valid_next ), .out(bram_out_is_valid), .reset(reset), .clk(clk)); - pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg4 (.in(depth_next ), .out(depth), .reset(reset), .clk(clk)); - - - - always @(*) begin - out_reg_next = out_reg; - depth_next = depth; - if (wr_en & ~rd_en) depth_next = depth + 1'h1; - else if (~wr_en & rd_en) depth_next = depth - 1'h1; - if(pass_din_to_out_reg) out_reg_next = din; - else if(bram_out_is_valid) out_reg_next = bram_dout; - end - - - - - wire empty; - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; - assign recieve_more_than_0 = ~ empty; - assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); - - - - - //synthesis translate_off - //synopsys translate_off - always @(posedge clk) - begin - if (wr_en & ~rd_en & full) begin - $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); - $finish; - end - /* verilator lint_off WIDTH */ - if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin - $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); - $finish; - end - if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin - $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); - $finish; - end - /* verilator lint_on WIDTH */ - end // always @ (posedge clk) - - //synopsys translate_on - //synthesis translate_on - - - - -endmodule - - - - - - - - +endmodule /********************************** - - bram_based_fifo - + bram_based_fifo *********************************/ - - module bram_based_fifo #( - parameter Dw = 72,//data_width - parameter B = 10// buffer num - )( - din, - wr_en, - rd_en, - dout, - full, - nearly_full, - empty, - reset, - clk - ); - - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2=Bint2; // B-1 - assign empty = depth == {DEPTHw{1'b0}}; - - //synthesis translate_off - //synopsys translate_off - always @(posedge clk) - begin - if(`pronoc_reset==1'b0)begin - if (wr_en && depth == B[DEPTHw-1 : 0] && !rd_en) begin - $display(" %t: ERROR: Attempt to write to full FIFO: %m",$time); - $finish; - end - if (rd_en && depth == {DEPTHw{1'b0}}) begin - $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time); - $finish; - end - end//~reset - end - //synopsys translate_on - //synthesis translate_on - -endmodule // fifo - + parameter Dw = 72,//data_width + parameter B = 10// buffer num +)( + din, + wr_en, + rd_en, + dout, + full, + nearly_full, + empty, + reset, + clk +); + + function integer log2; + input integer number; begin + log2=(number <=1) ? 1: 0; + while(2**log2=Bint2; // B-1 + assign empty = depth == {DEPTHw{1'b0}}; + + `ifdef SIMULATION + always @(posedge clk) begin + if(`pronoc_reset==1'b0)begin + if (wr_en && depth == B[DEPTHw-1 : 0] && !rd_en) begin + $display(" %t: ERROR: Attempt to write to full FIFO: %m",$time); + $finish; + end + if (rd_en && depth == {DEPTHw{1'b0}}) begin + $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time); + $finish; + end + end//~reset + end + `endif + +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index e7f22a5..767b0bc 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -135,7 +135,7 @@ module input_ports #( .ROUTER_ID(ROUTER_ID), .SW_LOC(i), .P(P) - ) the_input_queue_per_port ( + ) the_input_queue_per_port ( .credit_out(credit_out_all [(i+1)*V-1 : i*V]), .current_r_addr(current_r_addr), .neighbors_r_addr(neighbors_r_addr), @@ -223,7 +223,9 @@ module input_queue_per_port #( localparam PORT_B = port_buffer_size(SW_LOC), - PORT_Bw= log2(PORT_B); + PORT_Bw= log2(PORT_B), + PORT_V = port_hetro_vc_num(ROUTER_ID, SW_LOC), + V = PORT_V; //Replace default V with the port specefied VC num if hetro_vc is enabled localparam VV = V * V, @@ -864,70 +866,29 @@ module input_queue_per_port #( assign iport_weight_is_consumed=1'bX; assign oports_weight = {WP{1'bX}}; end - /* verilator lint_off WIDTH */ - if(COMBINATION_TYPE == "COMB_NONSPEC") begin : nonspec - /* verilator lint_on WIDTH */ - - /* - always @(posedge clk) - if ((ivc_not_empty & flit_is_tail2) != (ivc_not_empty & flit_is_tail))begin - $display("ERROR: %b !=%b",flit_is_tail2 , flit_is_tail ) ; - $finish; - end - */ - - flit_buffer #( - .V(V), - .B(PORT_B), // buffer space :flit per VC - .SSA_EN(SSA_EN), - .Fw(Fw), - .PCK_TYPE(PCK_TYPE), - .CAST_TYPE(CAST_TYPE), - .DEBUG_EN(DEBUG_EN) - ) the_flit_buffer ( - .din(flit_in), // Data in - .vc_num_wr(vc_num_in),//write virtual channel - .vc_num_rd(nonspec_first_arbiter_granted_ivc),//read virtual channel - .wr_en(flit_in_wr), // Write enable - .rd_en(any_ivc_sw_request_granted), // Read the next word - .dout(buffer_out), // Data out - .vc_not_empty(ivc_not_empty), - .reset(reset), - .clk(clk), - .ssa_rd(ssa_ctrl_in.ivc_num_getting_sw_grant), - .multiple_dest( multiple_dest ), - .sub_rd_ptr_ld(reset_ivc) , - .flit_is_tail(flit_is_tail) - ); - - end else begin :spec//not nonspec comb - - flit_buffer #( - .V(V), - .B(PORT_B), // buffer space :flit per VC - .SSA_EN(SSA_EN), - .Fw(Fw), - .PCK_TYPE(PCK_TYPE), - .CAST_TYPE(CAST_TYPE), - .DEBUG_EN(DEBUG_EN) - ) the_flit_buffer ( - .din(flit_in), // Data in - .vc_num_wr(vc_num_in),//write virtual channel - .vc_num_rd(ivc_num_getting_sw_grant),//read virtual channel - .wr_en(flit_in_wr), // Write enable - .rd_en(any_ivc_sw_request_granted), // Read the next word - .dout(buffer_out), // Data out - .vc_not_empty(ivc_not_empty), - .reset(reset), - .clk(clk), - .ssa_rd(ssa_ctrl_in.ivc_num_getting_sw_grant), - .multiple_dest( multiple_dest ), - .sub_rd_ptr_ld(reset_ivc) , - .flit_is_tail(flit_is_tail) - ); + wire [V-1 : 0] flit_buffer_vc_num_rd = (COMBINATION_TYPE == "COMB_NONSPEC")? + /* verilator lint_on WIDTH */ + nonspec_first_arbiter_granted_ivc: + ivc_num_getting_sw_grant; - end //:spec + flit_buffer #( + .B(PORT_B) // buffer space :flit per VC + ) the_flit_buffer ( + .din(flit_in), // Data in + .vc_num_wr(vc_num_in),//write virtual channel + .vc_num_rd(flit_buffer_vc_num_rd),//read virtual channel + .wr_en(flit_in_wr), // Write enable + .rd_en(any_ivc_sw_request_granted), // Read the next word + .dout(buffer_out), // Data out + .vc_not_empty(ivc_not_empty), + .reset(reset), + .clk(clk), + .ssa_rd(ssa_ctrl_in.ivc_num_getting_sw_grant), + .multiple_dest( multiple_dest ), + .sub_rd_ptr_ld(reset_ivc) , + .flit_is_tail(flit_is_tail) + ); /* verilator lint_off WIDTH */ if(CAST_TYPE== "UNICAST") begin : unicast diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index a085c4f..5cbb28b 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -4,334 +4,314 @@ * pronoc_pkg.sv ****************************************************************************/ -`ifdef PRONOC_PKG +`ifdef PRONOC_PKG `ifdef IMPORT_PRONOC_PCK package pronoc_pkg; -`endif - - - - +`endif + `define NOC_LOCAL_PARAM `include "noc_localparam.v" - - - `define INCLUDE_TOPOLOGY_LOCALPARAM `include "topology_localparam.v" + localparam + Vw= log2(V), + Cw= (C==0)? 1 : log2(C), + NEw = log2(NE), + Bw = log2(B), + WRRA_CONFIG_INDEX=0, + SMART_EN = (SMART_MAX !=0), + SMART_NUM= (SMART_EN) ? SMART_MAX : 1, + NEV = NE * V, + T4 = 0, + BEw = (BYTE_EN)? log2(Fpay/8) : 1; + + localparam CONGw= + (CONGESTION_INDEX==3)? 3: + (CONGESTION_INDEX==5)? 3: + (CONGESTION_INDEX==7)? 3: + (CONGESTION_INDEX==9)? 3: + (CONGESTION_INDEX==10)? 4: + (CONGESTION_INDEX==12)? 3:2; + + localparam + E_SRC_LSB =0, E_SRC_MSB = E_SRC_LSB + EAw-1, + E_DST_LSB = E_SRC_MSB +1, E_DST_MSB = E_DST_LSB + DAw-1, + DST_P_LSB = E_DST_MSB + 1, DST_P_MSB = DST_P_LSB + DSTPw-1, + CLASS_LSB = DST_P_MSB + 1, CLASS_MSB = CLASS_LSB + Cw -1, + MSB_CLASS = (C>1)? CLASS_MSB : DST_P_MSB, + WEIGHT_LSB= MSB_CLASS + 1, WEIGHT_MSB = WEIGHT_LSB + WEIGHTw -1, + /* verilator lint_off WIDTH */ + MSB_W = (SWA_ARBITER_TYPE== "WRRA")? WEIGHT_MSB : MSB_CLASS, + /* verilator lint_on WIDTH */ + BE_LSB = MSB_W + 1, BE_MSB = BE_LSB+ BEw-1, + MSB_BE = (BYTE_EN==1)? BE_MSB : MSB_W, + //the maximum data width that can be carried out with header flit + /* verilator lint_off WIDTH */ + HDR_MAX_DATw = (PCK_TYPE == "SINGLE_FLIT")? Fpay : Fpay - MSB_BE -1; + /* verilator lint_on WIDTH */ + + /* verilator lint_off WIDTH */ + localparam + DISTw = (TOPOLOGY=="FATTREE" || TOPOLOGY=="TREE" ) ? log2(2*L+1): log2(NR+1), + OVC_ALLOC_MODE= ((V==1 || B<=4) )? 1'b1 : 1'b0; + /* verilator lint_on WIDTH */ + + // 0: The new ovc is allocated only if its not nearly full. Results in a simpler sw_mask_gen logic + // 1: The new ovc is allocated only if its not full. Results in a little more complex sw_mask_gen logic + - -localparam - Vw= log2(V), - Cw= (C==0)? 1 : log2(C), - NEw = log2(NE), - Bw = log2(B), - WRRA_CONFIG_INDEX=0, - SMART_EN = (SMART_MAX !=0), - SMART_NUM= (SMART_EN) ? SMART_MAX : 1, - NEV = NE * V, - T4 = 0, - BEw = (BYTE_EN)? log2(Fpay/8) : 1; - - - - localparam CONGw= (CONGESTION_INDEX==3)? 3: - (CONGESTION_INDEX==5)? 3: - (CONGESTION_INDEX==7)? 3: - (CONGESTION_INDEX==9)? 3: - (CONGESTION_INDEX==10)? 4: - (CONGESTION_INDEX==12)? 3:2; - - - localparam - E_SRC_LSB =0, E_SRC_MSB = E_SRC_LSB + EAw-1, - E_DST_LSB = E_SRC_MSB +1, E_DST_MSB = E_DST_LSB + DAw-1, - DST_P_LSB = E_DST_MSB + 1, DST_P_MSB = DST_P_LSB + DSTPw-1, - CLASS_LSB = DST_P_MSB + 1, CLASS_MSB = CLASS_LSB + Cw -1, - MSB_CLASS = (C>1)? CLASS_MSB : DST_P_MSB, - WEIGHT_LSB= MSB_CLASS + 1, WEIGHT_MSB = WEIGHT_LSB + WEIGHTw -1, - /* verilator lint_off WIDTH */ - MSB_W = (SWA_ARBITER_TYPE== "WRRA")? WEIGHT_MSB : MSB_CLASS, - /* verilator lint_on WIDTH */ - BE_LSB = MSB_W + 1, BE_MSB = BE_LSB+ BEw-1, - MSB_BE = (BYTE_EN==1)? BE_MSB : MSB_W, - /* verilator lint_off WIDTH */ - //the maximum data width that can be carried out with header flit - HDR_MAX_DATw = (PCK_TYPE == "SINGLE_FLIT")? Fpay : Fpay - MSB_BE -1; - /* verilator lint_on WIDTH */ - - /* verilator lint_off WIDTH */ -localparam - DISTw = (TOPOLOGY=="FATTREE" || TOPOLOGY=="TREE" ) ? log2(2*L+1): log2(NR+1), - OVC_ALLOC_MODE= ((V==1 || B<=4) )? 1'b1 : 1'b0; - /* verilator lint_on WIDTH */ - - // 0: The new ovc is allocated only if its not nearly full. Results in a simpler sw_mask_gen logic - // 1: The new ovc is allocated only if its not full. Results in a little more complex sw_mask_gen logic - - - /****************** - * vsa : Virtual channel & Switch allocator +/****************** + * vsa : Virtual channel & Switch allocator * local two-stage router allocator *****************/ - typedef struct packed { - logic [V-1 : 0] ovc_is_allocated; - logic [V-1 : 0] ovc_is_released; - logic [V-1 : 0] ivc_num_getting_sw_grant; - logic [V-1 : 0] ivc_num_getting_ovc_grant; - logic [V-1 : 0] ivc_reset; - logic [V-1 : 0] buff_space_decreased; - logic [V*V-1: 0] ivc_granted_ovc_num; - } vsa_ctrl_t; - localparam VSA_CTRL_w = $bits(vsa_ctrl_t); - + typedef struct packed { + logic [V-1 : 0] ovc_is_allocated; + logic [V-1 : 0] ovc_is_released; + logic [V-1 : 0] ivc_num_getting_sw_grant; + logic [V-1 : 0] ivc_num_getting_ovc_grant; + logic [V-1 : 0] ivc_reset; + logic [V-1 : 0] buff_space_decreased; + logic [V*V-1: 0] ivc_granted_ovc_num; + } vsa_ctrl_t; + localparam VSA_CTRL_w = $bits(vsa_ctrl_t); + /********************* -* ssa : static straight allocator: -* enable single cycle latency for flits goes to the same direction -**********************/ - - typedef struct packed { - logic [V-1 : 0] ovc_is_allocated; - logic [V-1 : 0] ovc_is_released; - logic [V-1 : 0] ivc_num_getting_sw_grant; - logic [V-1 : 0] ivc_num_getting_ovc_grant; - logic [V-1 : 0] ivc_reset; - logic [V-1 : 0] buff_space_decreased; - logic [V-1 : 0] ivc_single_flit_pck; - logic [V-1 : 0] ovc_single_flit_pck; - bit ssa_flit_wr; - logic [V*V-1: 0] ivc_granted_ovc_num; - } ssa_ctrl_t; - localparam SSA_CTRL_w = $bits(ssa_ctrl_t); - - +* ssa : static straight allocator: +* enable single cycle latency for flits goes to the same direction +**********************/ + + typedef struct packed { + logic [V-1 : 0] ovc_is_allocated; + logic [V-1 : 0] ovc_is_released; + logic [V-1 : 0] ivc_num_getting_sw_grant; + logic [V-1 : 0] ivc_num_getting_ovc_grant; + logic [V-1 : 0] ivc_reset; + logic [V-1 : 0] buff_space_decreased; + logic [V-1 : 0] ivc_single_flit_pck; + logic [V-1 : 0] ovc_single_flit_pck; + bit ssa_flit_wr; + logic [V*V-1: 0] ivc_granted_ovc_num; + } ssa_ctrl_t; + localparam SSA_CTRL_w = $bits(ssa_ctrl_t); + /********************* * smart : straight bypass allocator: * enable multihub bypassing for flits goes to the same direction *********************/ - typedef struct packed { - logic [EAw-1 : 0] dest_e_addr; - logic ovc_is_assigned; - logic [Vw-1 : 0] assigned_ovc_bin; - } smart_ivc_info_t; - localparam SMART_IVC_w = $bits(smart_ivc_info_t); - - - - typedef struct packed { - bit smart_en; - bit hdr_flit_req; - logic [V-1 : 0] ivc_smart_en; - logic [DSTPw-1 : 0] lk_destport; - logic [DSTPw-1 : 0] destport; - logic [V-1 : 0] credit_out; - logic [V-1 : 0] buff_space_decreased; - logic [V-1 : 0] ovc_is_allocated; - logic [V-1 : 0] ovc_is_released; - logic [V-1 : 0] ivc_num_getting_ovc_grant; - logic [V-1 : 0] ivc_reset; - logic [V-1 : 0] mask_available_ovc; - logic [V-1 : 0] ivc_single_flit_pck; - logic [V-1 : 0] ovc_single_flit_pck; - logic [V*V-1: 0] ivc_granted_ovc_num; - } smart_ctrl_t; - localparam SMART_CTRL_w = $bits(smart_ctrl_t); - - /***************** - * port_info - * **************/ - typedef struct packed { - logic [V-1 : 0] ivc_req; // input vc is not empty - logic [V-1 : 0] swa_first_level_grant;// The vc number (one-hot) in an input port which get the first level switch allocator grant - logic [V-1 : 0] swa_grant; // The VC number in an input port which got the swa grant - logic [MAX_P-1 : 0] granted_oport_one_hot; //The granted output port num (one-hot) for an input port - logic any_ivc_get_swa_grant; - - } iport_info_t; - localparam IPORT_INFO_w = $bits(iport_info_t); - - typedef struct packed { - logic [V-1 : 0] non_smart_ovc_is_allocated; - //logic [V-1 : 0] ovc_is_released; - //logic [V-1 : 0] ovc_credit_increased; - //logic [V-1 : 0] ovc_credit_decreased; - //logic [V-1 : 0] ovc_avalable; - bit any_ovc_granted; - //bit crossbar_flit_wr; - - }oport_info_t; - localparam OPORT_INFO_w = $bits(oport_info_t); - - - - - - /********************* - * ivc - *******************/ - - - typedef struct packed { - //ivc - logic [EAw-1 : 0] dest_e_addr; - logic ovc_is_assigned; - logic [V-1 : 0] assigned_ovc_num; - logic [Vw-1 : 0] assigned_ovc_bin; - logic [MAX_P-1 : 0] destport_one_hot; - logic [DSTPw-1 : 0] dest_port_encoded; - logic ivc_req; // input vc is not empty - logic flit_is_tail; - logic assigned_ovc_not_full; - logic [V-1 : 0] candidate_ovc; - logic [Cw-1 : 0] class_num; - logic single_flit_pck; - - } ivc_info_t; - localparam IVC_INFO_w = $bits( ivc_info_t); - - localparam CREDITw = (LB>B)? log2(LB+1) : log2(B+1); - - //ovc info - typedef struct packed { - bit avalable; - bit status; //1 : is allocated 0 : not_allocated - logic [CREDITw-1 : 0] credit;//available credit in OVC - bit full; - bit nearly_full; - bit empty; - }ovc_info_t; - localparam OVC_INFO_w = $bits( ovc_info_t); - - - - - + typedef struct packed { + logic [EAw-1 : 0] dest_e_addr; + logic ovc_is_assigned; + logic [Vw-1 : 0] assigned_ovc_bin; + } smart_ivc_info_t; + localparam SMART_IVC_w = $bits(smart_ivc_info_t); + + typedef struct packed { + bit smart_en; + bit hdr_flit_req; + logic [V-1 : 0] ivc_smart_en; + logic [DSTPw-1 : 0] lk_destport; + logic [DSTPw-1 : 0] destport; + logic [V-1 : 0] credit_out; + logic [V-1 : 0] buff_space_decreased; + logic [V-1 : 0] ovc_is_allocated; + logic [V-1 : 0] ovc_is_released; + logic [V-1 : 0] ivc_num_getting_ovc_grant; + logic [V-1 : 0] ivc_reset; + logic [V-1 : 0] mask_available_ovc; + logic [V-1 : 0] ivc_single_flit_pck; + logic [V-1 : 0] ovc_single_flit_pck; + logic [V*V-1: 0] ivc_granted_ovc_num; + } smart_ctrl_t; + localparam SMART_CTRL_w = $bits(smart_ctrl_t); + +/***************** +* port_info +****************/ + typedef struct packed { + logic [V-1 : 0] ivc_req; // input vc is not empty + logic [V-1 : 0] swa_first_level_grant;// The vc number (one-hot) in an input port which get the first level switch allocator grant + logic [V-1 : 0] swa_grant; // The VC number in an input port which got the swa grant + logic [MAX_P-1 : 0] granted_oport_one_hot; //The granted output port num (one-hot) for an input port + logic any_ivc_get_swa_grant; + + } iport_info_t; + localparam IPORT_INFO_w = $bits(iport_info_t); + + typedef struct packed { + logic [V-1 : 0] non_smart_ovc_is_allocated; + //logic [V-1 : 0] ovc_is_released; + //logic [V-1 : 0] ovc_credit_increased; + //logic [V-1 : 0] ovc_credit_decreased; + //logic [V-1 : 0] ovc_avalable; + bit any_ovc_granted; + //bit crossbar_flit_wr; + + }oport_info_t; + localparam OPORT_INFO_w = $bits(oport_info_t); + +/********************* +* ivc +*******************/ + typedef struct packed { + //ivc + logic [EAw-1 : 0] dest_e_addr; + logic ovc_is_assigned; + logic [V-1 : 0] assigned_ovc_num; + logic [Vw-1 : 0] assigned_ovc_bin; + logic [MAX_P-1 : 0] destport_one_hot; + logic [DSTPw-1 : 0] dest_port_encoded; + logic ivc_req; // input vc is not empty + logic flit_is_tail; + logic assigned_ovc_not_full; + logic [V-1 : 0] candidate_ovc; + logic [Cw-1 : 0] class_num; + logic single_flit_pck; + + } ivc_info_t; + localparam IVC_INFO_w = $bits( ivc_info_t); + + localparam CREDITw = (LB>B)? log2(LB+1) : log2(B+1); + + //ovc info + typedef struct packed { + bit avalable; + bit status; //1 : is allocated 0 : not_allocated + logic [CREDITw-1 : 0] credit;//available credit in OVC + bit full; + bit nearly_full; + bit empty; + }ovc_info_t; + localparam OVC_INFO_w = $bits( ovc_info_t); + /********************* -* router_chanels +* router_chanels *********************/ - - typedef struct packed { - logic [EAw-1 : 0] src_e_addr; - logic [DAw-1 : 0] dest_e_addr; - logic [DSTPw-1 : 0] destport; - logic [Cw-1 : 0] message_class; - logic [WEIGHTw-1: 0] weight; - logic [BEw-1 : 0] be; - } hdr_flit_t; - localparam HDR_FLIT_w = $bits(hdr_flit_t); - - /* verilator lint_off WIDTH */ - localparam FPAYw = (PCK_TYPE == "SINGLE_FLIT")? Fpay + MSB_BE: Fpay; - /* verilator lint_on WIDTH */ - - typedef struct packed { - bit hdr_flag; - bit tail_flag; - logic [V-1 : 0] vc; - logic [FPAYw-1 : 0] payload; - } flit_t; - localparam FLIT_w = $bits(flit_t); - - localparam - Fw = FLIT_w, - NEFw = NE *Fw; - - typedef struct packed { - logic flit_wr; - logic [V-1 : 0] credit; - flit_t flit; - logic [CONGw-1 : 0] congestion; - } flit_chanel_t; - localparam FLIT_CHANEL_w = $bits(flit_chanel_t); - - localparam BYPASSw = log2(SMART_NUM+1); - typedef struct packed { - logic [SMART_NUM-1: 0] requests; - logic [V-1 : 0] ovc; - logic [EAw-1 : 0] dest_e_addr; - bit hdr_flit; - bit flit_in_bypassed; - logic [BYPASSw-1 : 0] bypassed_num; - } smart_chanel_t; - localparam SMART_CHANEL_w = $bits(smart_chanel_t); - - - localparam CRDTw = (B>LB) ? log2(B+1) : log2(LB+1); - typedef struct packed { - bit endp_port; // if it is one, it means the corresponding port is connected o an endpoint - logic [RAw-1: 0] neighbors_r_addr; - logic [V-1 :0] [CRDTw-1: 0] credit_init_val; // the connected port initial credit value. It is taken at reset time - logic [V-1 :0] credit_release_en; - } ctrl_chanel_t; - localparam CTRL_CHANEL_w = $bits(ctrl_chanel_t); - - - - typedef struct packed { - flit_chanel_t flit_chanel; - smart_chanel_t smart_chanel; - ctrl_chanel_t ctrl_chanel; - } smartflit_chanel_t; - localparam SMARTFLIT_CHANEL_w = $bits(smartflit_chanel_t); - - - - + + typedef struct packed { + logic [EAw-1 : 0] src_e_addr; + logic [DAw-1 : 0] dest_e_addr; + logic [DSTPw-1 : 0] destport; + logic [Cw-1 : 0] message_class; + logic [WEIGHTw-1: 0] weight; + logic [BEw-1 : 0] be; + } hdr_flit_t; + localparam HDR_FLIT_w = $bits(hdr_flit_t); + + /* verilator lint_off WIDTH */ + localparam FPAYw = (PCK_TYPE == "SINGLE_FLIT")? Fpay + MSB_BE: Fpay; + /* verilator lint_on WIDTH */ + + typedef struct packed { + bit hdr_flag; + bit tail_flag; + logic [V-1 : 0] vc; + logic [FPAYw-1 : 0] payload; + } flit_t; + localparam FLIT_w = $bits(flit_t); + + localparam + Fw = FLIT_w, + NEFw = NE *Fw; + + typedef struct packed { + logic flit_wr; + logic [V-1 : 0] credit; + flit_t flit; + logic [CONGw-1 : 0] congestion; + } flit_chanel_t; + localparam FLIT_CHANEL_w = $bits(flit_chanel_t); + + localparam BYPASSw = log2(SMART_NUM+1); + typedef struct packed { + logic [SMART_NUM-1: 0] requests; + logic [V-1 : 0] ovc; + logic [EAw-1 : 0] dest_e_addr; + bit hdr_flit; + bit flit_in_bypassed; + logic [BYPASSw-1 : 0] bypassed_num; + } smart_chanel_t; + localparam SMART_CHANEL_w = $bits(smart_chanel_t); + + localparam CRDTw = (B>LB) ? log2(B+1) : log2(LB+1); + typedef struct packed { + bit endp_port; // if it is one, it means the corresponding port is connected o an endpoint + logic [RAw-1: 0] neighbors_r_addr; + logic [V-1 :0] [CRDTw-1: 0] credit_init_val; // the connected port initial credit value. It is taken at reset time + logic [V-1 :0] credit_release_en; + } ctrl_chanel_t; + localparam CTRL_CHANEL_w = $bits(ctrl_chanel_t); + + typedef struct packed { + flit_chanel_t flit_chanel; + smart_chanel_t smart_chanel; + ctrl_chanel_t ctrl_chanel; + } smartflit_chanel_t; + localparam SMARTFLIT_CHANEL_w = $bits(smartflit_chanel_t); + + function automatic integer port_hetro_vc_num; + input integer router_id; + input integer router_port_num; //router port num + begin + port_hetro_vc_num = + (HETRO_VC == 0) ? V : + (HETRO_VC == 1) ? VC_CONFIG_TABLE [router_id][0] : + VC_CONFIG_TABLE [router_id][router_port_num]; + end + endfunction + /*********** * simulation * **********/ - - localparam DELAYw = 9; //Injector start delay counter width. 10 to 500 clk cycles delay randomly selected - - typedef struct packed { - integer ip_num; - bit send_enable; - integer percentage; // x10 - } hotspot_t; - - typedef struct packed { - integer value; - integer percentage; - }rnd_discrete_t; - - //packet injector interface - localparam PCK_INJ_Dw =64;//TODO to be defined by user - localparam PCK_SIZw= log2(MAX_PCK_SIZ+1); - - - - typedef struct packed { - logic [PCK_INJ_Dw-1 : 0] data; - logic [PCK_SIZw-1 : 0] size; - logic [DAw-1 : 0] endp_addr; - logic [Cw-1 : 0] class_num; - logic [WEIGHTw-1 : 0] init_weight; - logic [V-1 : 0] vc; - bit pck_wr; - bit [V-1 : 0] ready; - logic [DISTw-1 : 0] distance; - logic [15: 0] h2t_delay; - } pck_injct_t; + + localparam DELAYw = 9; //Injector start delay counter width. 10 to 500 clk cycles delay randomly selected + + typedef struct packed { + integer ip_num; + bit send_enable; + integer percentage; // x10 + } hotspot_t; + + typedef struct packed { + integer value; + integer percentage; + }rnd_discrete_t; + + //packet injector interface + localparam PCK_INJ_Dw =64;//TODO to be defined by user + localparam PCK_SIZw= log2(MAX_PCK_SIZ+1); + + typedef struct packed { + logic [PCK_INJ_Dw-1 : 0] data; + logic [PCK_SIZw-1 : 0] size; + logic [DAw-1 : 0] endp_addr; + logic [Cw-1 : 0] class_num; + logic [WEIGHTw-1 : 0] init_weight; + logic [V-1 : 0] vc; + bit pck_wr; + bit [V-1 : 0] ready; + logic [DISTw-1 : 0] distance; + logic [15: 0] h2t_delay; + } pck_injct_t; localparam PCK_INJCT_w = $bits(pck_injct_t); typedef struct packed { - logic [BYPASSw-1 : 0] bypassed_num; - bit flit_wr_i; - bit pck_wr_i; - bit flit_wr_o; - bit pck_wr_o; - bit flit_in_bypassed; - bit active_high_reset; // if asserted means ProNoC is configured with active high reset - bit empty; // if asseted means there is no flit in this router port + logic [BYPASSw-1 : 0] bypassed_num; + bit flit_wr_i; + bit pck_wr_i; + bit flit_wr_o; + bit pck_wr_o; + bit flit_in_bypassed; + bit active_high_reset; // if asserted means ProNoC is configured with active high reset + bit empty; // if asseted means there is no flit in this router port } router_event_t; localparam ROUTER_EVENT_w = $bits(router_event_t); - -`ifdef IMPORT_PRONOC_PCK + +`ifdef IMPORT_PRONOC_PCK endpackage : pronoc_pkg `endif - -`endif + +`endif //PRONOC_PKG From 22b6708b0df3234bbadb9767996bf2475fd37d84 Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 3 Feb 2025 01:38:59 +0100 Subject: [PATCH 005/107] add hetero ovc presence port --- .../synthetic_sim/src/deafult_noc_param | 4 +- .../Integration_test/synthetic_sim/src/src.pl | 2 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 28 +++++------ mpsoc/perl_gui/lib/perl/simulator.pl | 6 +-- mpsoc/rtl/src_noc/flit_buffer.sv | 8 ++-- mpsoc/rtl/src_noc/inout_ports.sv | 19 +++++--- mpsoc/rtl/src_noc/input_ports.sv | 46 ++++++++++++------- mpsoc/rtl/src_noc/noc_localparam.v | 12 ++--- mpsoc/rtl/src_noc/pronoc_pkg.sv | 22 +++++++-- mpsoc/rtl/src_noc/router_two_stage.sv | 4 +- mpsoc/smart-netrace/src/src.pl | 2 +- 11 files changed, 92 insertions(+), 61 deletions(-) diff --git a/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param b/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param index 3f5025a..2ecce91 100644 --- a/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param +++ b/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param @@ -36,7 +36,7 @@ $model = bless({ "CVw"=> "(C==0)? V : C * V", "CAST_TYPE" => "\"UNICAST\"", "MCAST_ENDP_LIST" => "'b1111", - "HETRO_VC"=> "0", + "HETERO_VC"=> "0", "MAX_ROUTER"=>"1", "MAX_PORT"=>"1", "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{0}", @@ -79,7 +79,7 @@ $model = bless({ "CVw", "CAST_TYPE", "MCAST_ENDP_LIST", - "HETRO_VC", + "HETERO_VC", "MAX_ROUTER", "MAX_PORT", "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]", diff --git a/mpsoc/Integration_test/synthetic_sim/src/src.pl b/mpsoc/Integration_test/synthetic_sim/src/src.pl index 70cef1b..e0bda9e 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/src.pl +++ b/mpsoc/Integration_test/synthetic_sim/src/src.pl @@ -621,7 +621,7 @@ sub check_sim_results{ my @errors = unix_grep("$file","ERROR:"); if (scalar @errors ){ - append_text_to_file($report,"\t Error in running simulation: @errors \n"); + append_text_to_file($report,"\t Error in running simulation:\n @errors \n"); $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="Failed"; $self->{'name'}{"$name"}{'traffic'}{$traffic}{'message'}="@errors"; return; diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index e21d47c..3aae2bd 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -1071,9 +1071,9 @@ sub noc_config{ $type= 'Spin-button'; #($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,$wrra_show,$noc_param,undef); - #HETRO_VC + #HETERO_VC $label='Heterogeneous VC En'; - $param='HETRO_VC'; + $param='HETERO_VC'; $default='0'; $content='0,1,2'; $type='Combo-box'; @@ -1088,35 +1088,35 @@ sub noc_config{ #VC_CONFIG_TABLE - my $hetro_en=$mpsoc->object_get_attribute($noc_param,'HETRO_VC'); + my $hetero_en=$mpsoc->object_get_attribute($noc_param,'HETERO_VC'); $label='Heterogeneous VC setting'; $param='int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]'; $default='\'{0}'; $content='0,1,2'; $type='Combo-box'; $info='Defines how a heterogeneous number of VCs are distributed in the NoC. - - HETRO_VC= 0: Uniform VC configuration. All routers and ports have + - HETERO_VC= 0: Uniform VC configuration. All routers and ports have the same number of VCs, and this parameter is not used. - - HETRO_VC= 1,2 : Specifies the VC count in a 2D parameter array, where: + - HETERO_VC= 1,2 : Specifies the VC count in a 2D parameter array, where: * The first dimension represents the router ID. * The second dimension represents the port number. - - For HETRO_VC = 1: All ports within a router have the same number of VCs, + - For HETERO_VC = 1: All ports within a router have the same number of VCs, so only the first element of each row is considered valid. - - For HETRO_VC = 2: Each port in every router can have a unique VC count.'; + - For HETERO_VC = 2: Each port in every router can have a unique VC count.'; $noc_param_comment{$param}="$info"; - if($hetro_en eq '0'){ + if($hetero_en eq '0'){ $mpsoc->object_add_attribute($noc_param,"MAX_ROUTER",1); $mpsoc->object_add_attribute($noc_param,"MAX_PORT",1); $mpsoc->object_add_attribute($noc_param,$param,$default); - }elsif($hetro_en eq '1'){ + }elsif($hetero_en eq '1'){ $mpsoc->object_add_attribute($noc_param,"MAX_ROUTER",$NR); $mpsoc->object_add_attribute($noc_param,"MAX_PORT",1); - $row=hetro_vc_widget($mpsoc,$row,$NR,1,$label,$info,$table,$noc_id,$param,$v); + $row=hetero_vc_widget($mpsoc,$row,$NR,1,$label,$info,$table,$noc_id,$param,$v); }else{ $mpsoc->object_add_attribute($noc_param,"MAX_ROUTER",$NR); $mpsoc->object_add_attribute($noc_param,"MAX_PORT",$MAX_P); - $row=hetro_vc_widget($mpsoc,$row,$NR,$MAX_P,$label,$info,$table,$noc_id,$param,$v); + $row=hetero_vc_widget($mpsoc,$row,$NR,$MAX_P,$label,$info,$table,$noc_id,$param,$v); } @@ -1154,7 +1154,7 @@ sub noc_config{ return $row; } -sub hetro_vc_widget{ +sub hetero_vc_widget{ my ($mpsoc,$row,$nr,$np,$label_text,$info,$table,$noc_id,$param,$v)=@_; my $b1= def_image_button("icons/setting.png","Set"); my $label=gen_label_in_left($label_text); @@ -1163,12 +1163,12 @@ sub hetro_vc_widget{ $row++; update_vc_list($mpsoc,$noc_id,$nr,$np,$v,$param,$info); $b1->signal_connect("clicked" => sub{ - set_hetro_vc_list($mpsoc,$noc_id,$nr,$np,$param,$v,$info); + set_hetero_vc_list($mpsoc,$noc_id,$nr,$np,$param,$v,$info); }); return $row; } -sub set_hetro_vc_list{ +sub set_hetero_vc_list{ my($mpsoc,$noc_id,$nr,$np,$param,$v,$info)=@_; my $noc_param="noc_param$noc_id"; my $vc_param="vc_param$noc_id"; diff --git a/mpsoc/perl_gui/lib/perl/simulator.pl b/mpsoc/perl_gui/lib/perl/simulator.pl index d07d34c..8493282 100755 --- a/mpsoc/perl_gui/lib/perl/simulator.pl +++ b/mpsoc/perl_gui/lib/perl/simulator.pl @@ -1305,7 +1305,7 @@ sub run_synthetic_simulation { my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); if (scalar @errors ){ - add_colored_info($info, "Error in running simulation: @errors \n",'red'); + add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); $simulate->object_add_attribute ($sample,"status","failed"); $simulate->object_add_attribute('status',undef,'ideal'); return; @@ -1482,7 +1482,7 @@ sub run_task_simulation{ my $stdout = load_file("$out_path/sim_out$r"); my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); if (scalar @errors ){ - add_colored_info($info, "Error in running simulation: @errors \n",'red'); + add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); $simulate->object_add_attribute ($sample,"status","failed"); $simulate->object_add_attribute('status',undef,'ideal'); return; @@ -1583,7 +1583,7 @@ sub run_trace_simulation{ $stdout = load_file("$out_path/sim_out"); my @errors = unix_grep("$out_path/sim_out","ERROR:"); if (scalar @errors ){ - add_colored_info($info, "Error in running simulation: @errors \n",'red'); + add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); $simulate->object_add_attribute ($sample,"status","failed"); $simulate->object_add_attribute('status',undef,'ideal'); return; diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index fd74ad7..e934b98 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -29,8 +29,7 @@ module flit_buffer #( - parameter ROUTER_ID = 0, - parameter SW_LOC = 0, + parameter V= 1, parameter B = 4 )( din, // Data in @@ -320,8 +319,7 @@ module flit_buffer assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][rd_ptr[i]-(B*i)] : 1'b1; /* verilator lint_on WIDTH */ end - end//FOR - + end// for V_ onehot_mux_1D #( .W(BVw), @@ -375,7 +373,7 @@ module flit_buffer end end //DEBUG_EN - for(i=0;i{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="Failed"; $self->{'name'}{"$name"}{'traffic'}{$traffic}{'message'}="@errors"; return; From 42b5e4a321478047366cb37f4ead09056ffd116c Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 3 Feb 2025 19:03:59 +0100 Subject: [PATCH 006/107] pass router_id as parameter ROUTER_ID to all routers when generating a NoC --- mpsoc/perl_gui/lib/perl/emulator.pl | 2164 +++++----- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 2 +- mpsoc/perl_gui/lib/perl/simulator.pl | 3496 ++++++++--------- .../perl_gui/lib/perl/topology_verilog_gen.pl | 2047 +++++----- mpsoc/rtl/src_noc/fattree_noc_top.sv | 319 +- mpsoc/rtl/src_noc/inout_ports.sv | 9 +- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 330 +- mpsoc/rtl/src_noc/noc_top.sv | 242 +- mpsoc/rtl/src_noc/packet_injector.sv | 1278 +++--- mpsoc/rtl/src_noc/router_top.sv | 9 +- mpsoc/rtl/src_noc/star_noc.sv | 163 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 2065 +++++----- mpsoc/rtl/src_noc/tree_noc_top.sv | 330 +- .../Tcustom1Rcustom_conventional_routing.v | 12 +- ...stom1Rcustom_conventional_routing_genvar.v | 44 +- .../Tcustom1Rcustom_look_ahead_routing.v | 58 +- ...custom1Rcustom_look_ahead_routing_genvar.v | 96 +- mpsoc/rtl/src_topology/custom1/custom1.png | Bin 83694 -> 137543 bytes mpsoc/rtl/src_topology/custom1/custom1_noc.sv | 768 ++-- .../custom1/custom1_noc_genvar.sv | 119 +- mpsoc/rtl/src_topology/custom_flist.f | 12 +- mpsoc/rtl/src_topology/param.obj | 28 +- .../topology/custom/custom1_noc.h | 10 +- 23 files changed, 6608 insertions(+), 6993 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/emulator.pl b/mpsoc/perl_gui/lib/perl/emulator.pl index b418461..d4269f3 100755 --- a/mpsoc/perl_gui/lib/perl/emulator.pl +++ b/mpsoc/perl_gui/lib/perl/emulator.pl @@ -38,13 +38,12 @@ use constant MAX_PATTERN => ((2**RAM_Aw)-(RAM_RESERVED_ADDR_NUM)); use constant RAM_SIZE => (2**RAM_Aw); - + #use constant MAX_PCK_NUM => (2**PCK_CNTw)-1; use constant MAX_PCK_NUM => (2**PCK_CNTw)-1; use constant MAX_PCK_SIZ => (2**PCK_SIZw)-1; use constant MAX_SIM_CLKs=> 1000000000; # simulation end at if clock counter reach this number - use constant MAX_RATIO => 1000;# 0->0 1->0.1 ... 1000->100 use constant EMULATION_TOP => "/mpsoc/rtl/src_emulate/emulator_top.v"; @@ -55,157 +54,151 @@ sub get_MAX_PCK_SIZ(){MAX_PCK_SIZ} sub check_inserted_ratios { - my $str=shift; - my @ratios; - - my @chunks=split(/\s*,\s*/,$str); - foreach my $p (@chunks){ - if($p !~ /^[0-9.:,]+$/){ message_dialog ("$p has invalid character(S)" ); return undef; } - my @range=split(':',$p); - my $size= scalar @range; - if($size==1){ # its a number - if ( $range[0] <= 0 || $range[0] >100 ) { message_dialog ("Injection ratio $range[0] is out of bounds: 1<=ratio=<100" ); return undef; } - push(@ratios,$range[0]); - }elsif($size ==3){# its a range - my($min,$max,$step)=@range; - if ( $min <= 0 || $min >100 ) { message_dialog ("Injection ratio $min in $p is out of bounds: 1<=ratio=<100" ); return undef; } - if ( $max <= 0 || $max >100 ) { message_dialog ("Injection ratio $max in $p is out of bounds: 1<=ratio=<100" ); return undef; } - for (my $i=$min; $i<=$max; $i=$i+$step){ - push(@ratios,$i); - } - - }else{ - message_dialog ("Injection ratio $p has an invalid format. The correct format for range is \[min\]:\[max\]:\[step\]" ); - return undef; - } - - }#foreach - my @r=uniq(sort {$a<=>$b} @ratios); - return \@r; - + my $str=shift; + my @ratios; + + my @chunks=split(/\s*,\s*/,$str); + foreach my $p (@chunks){ + if($p !~ /^[0-9.:,]+$/){ message_dialog ("$p has invalid character(S)" ); return undef; } + my @range=split(':',$p); + my $size= scalar @range; + if($size==1){ # its a number + if ( $range[0] <= 0 || $range[0] >100 ) { message_dialog ("Injection ratio $range[0] is out of bounds: 1<=ratio=<100" ); return undef; } + push(@ratios,$range[0]); + }elsif($size ==3){# its a range + my($min,$max,$step)=@range; + if ( $min <= 0 || $min >100 ) { message_dialog ("Injection ratio $min in $p is out of bounds: 1<=ratio=<100" ); return undef; } + if ( $max <= 0 || $max >100 ) { message_dialog ("Injection ratio $max in $p is out of bounds: 1<=ratio=<100" ); return undef; } + for (my $i=$min; $i<=$max; $i=$i+$step){ + push(@ratios,$i); + } + + }else{ + message_dialog ("Injection ratio $p has an invalid format. The correct format for range is \[min\]:\[max\]:\[step\]" ); + return undef; + } + + }#foreach + my @r=uniq(sort {$a<=>$b} @ratios); + return \@r; + } - sub get_injection_ratios{ - my ($emulate,$atrebute1,$atrebute2)=@_; - my $box =def_hbox(FALSE, 0); - my $init=$emulate->object_get_attribute($atrebute1,$atrebute2); - my $entry=gen_entry($init); - my $button=def_image_button("icons/right.png",'Check'); - $button->signal_connect("clicked" => sub { - my $text= $entry->get_text(); - my $r=check_inserted_ratios($text); - if(defined $r){ - my $all= join (',',@$r); - message_dialog ("$all" ); - } - - - }); - $entry->signal_connect ("changed" => sub { - my $text= $entry->get_text(); - $emulate->object_add_attribute($atrebute1,$atrebute2,$text); - - }); - $box->pack_start( $entry, 1,1, 0); - $box->pack_start( $button, 0, 1, 3); - return $box; + my ($emulate,$atrebute1,$atrebute2)=@_; + my $box =def_hbox(FALSE, 0); + my $init=$emulate->object_get_attribute($atrebute1,$atrebute2); + my $entry=gen_entry($init); + my $button=def_image_button("icons/right.png",'Check'); + $button->signal_connect("clicked" => sub { + my $text= $entry->get_text(); + my $r=check_inserted_ratios($text); + if(defined $r){ + my $all= join (',',@$r); + message_dialog ("$all" ); + } + }); + $entry->signal_connect ("changed" => sub { + my $text= $entry->get_text(); + $emulate->object_add_attribute($atrebute1,$atrebute2,$text); + }); + $box->pack_start( $entry, 1,1, 0); + $box->pack_start( $button, 0, 1, 3); + return $box; } - - sub get_noc_configuration{ - my ($emulate,$mode,$sample,$set_win) =@_; - if($mode eq "simulate") {get_simulator_noc_configuration(@_); return;} - get_emulator_noc_configuration(@_); + my ($emulate,$mode,$sample,$set_win) =@_; + if($mode eq "simulate") {get_simulator_noc_configuration(@_); return;} + get_emulator_noc_configuration(@_); } sub get_sof_file_full_addr{ - my ($emulate,$sample)=@_; - my $open_in = $emulate->object_get_attribute($sample,"sof_path"); - my $board = $emulate->object_get_attribute($sample,"FPGA_board"); - my $file = $emulate->object_get_attribute($sample,"sof_file"); - return undef if(!defined ${open_in} || !defined ${board} || !defined $file ); - my $sof = "${open_in}/${board}/$file"; - #print "\n$sof\n"; - return $sof; + my ($emulate,$sample)=@_; + my $open_in = $emulate->object_get_attribute($sample,"sof_path"); + my $board = $emulate->object_get_attribute($sample,"FPGA_board"); + my $file = $emulate->object_get_attribute($sample,"sof_file"); + return undef if(!defined ${open_in} || !defined ${board} || !defined $file ); + my $sof = "${open_in}/${board}/$file"; + #print "\n$sof\n"; + return $sof; } sub get_emulator_noc_configuration{ - my ($emulate,$mode,$sample,$set_win) =@_; - my $table=def_table(10,2,FALSE); - my $row=0; - - my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,shuffle,bit rotation,neighbor"; #TODO hot spot for emulator - - #search path - my $dir = Cwd::getcwd(); - my $open_in = abs_path("$ENV{PRONOC_WORK}/emulate/sof"); - attach_widget_to_table ($table,$row,gen_label_in_left("Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), - get_dir_in_object ($emulate,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; - $open_in = $emulate->object_get_attribute($sample,"sof_path"); - - - - #select the board - my($label,$param,$default,$content,$type,$info); - my @dirs = grep {-d} glob("$open_in/*"); - my $fpgas; - foreach my $dir (@dirs) { - my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); - $default=$name; - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - } - - attach_widget_to_table ($table,$row,gen_label_in_left("Select FPGA board:"),gen_button_message ("Select the FPGA board. You can add your own FPGA board by adding its configuration file to mpsoc/boards directory","icons/help.png"), - gen_combobox_object ($emulate,$sample, "FPGA_board", $fpgas, undef,'ref_set_win',1)); $row++; - - - #select the sram object file - my $board = $emulate->object_get_attribute($sample,"FPGA_board"); - my @files; - @files = glob "${open_in}/${board}/*" if(defined $board); - my $sof_files=""; - foreach my $file (@files){ - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - $sof_files="$sof_files,$name" if($suffix eq '.sof'); - } - attach_widget_to_table ($table,$row,gen_label_in_left("Sram Object File:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), - gen_combobox_object ($emulate,$sample, "sof_file", $sof_files, undef,undef,undef)); $row++; - - - - #attach_widget_to_table ($table,$row,gen_label_in_left("SoF file:"),gen_button_message ("Select the SRAM Object File (sof) for this NoC configration.","icons/help.png"), get_file_name_object ($emulate,$sample,"sof_file",'sof',$open_in)); $row++; - + my ($emulate,$mode,$sample,$set_win) =@_; + my $table=def_table(10,2,FALSE); + my $row=0; + + my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,shuffle,bit rotation,neighbor"; #TODO hot spot for emulator + + #search path + my $dir = Cwd::getcwd(); + my $open_in = abs_path("$ENV{PRONOC_WORK}/emulate/sof"); + attach_widget_to_table ($table,$row,gen_label_in_left("Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), + get_dir_in_object ($emulate,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; + $open_in = $emulate->object_get_attribute($sample,"sof_path"); + + + + #select the board + my($label,$param,$default,$content,$type,$info); + my @dirs = grep {-d} glob("$open_in/*"); + my $fpgas; + foreach my $dir (@dirs) { + my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); + $default=$name; + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + } + + attach_widget_to_table ($table,$row,gen_label_in_left("Select FPGA board:"),gen_button_message ("Select the FPGA board. You can add your own FPGA board by adding its configuration file to mpsoc/boards directory","icons/help.png"), + gen_combobox_object ($emulate,$sample, "FPGA_board", $fpgas, undef,'ref_set_win',1)); $row++; + + + #select the sram object file + my $board = $emulate->object_get_attribute($sample,"FPGA_board"); + my @files; + @files = glob "${open_in}/${board}/*" if(defined $board); + my $sof_files=""; + foreach my $file (@files){ + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + $sof_files="$sof_files,$name" if($suffix eq '.sof'); + } + attach_widget_to_table ($table,$row,gen_label_in_left("Sram Object File:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), + gen_combobox_object ($emulate,$sample, "sof_file", $sof_files, undef,undef,undef)); $row++; + + + + #attach_widget_to_table ($table,$row,gen_label_in_left("SoF file:"),gen_button_message ("Select the SRAM Object File (sof) for this NoC configration.","icons/help.png"), get_file_name_object ($emulate,$sample,"sof_file",'sof',$open_in)); $row++; + my @emulateinfo = ( - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef}, + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef}, - { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>undef}, + { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>undef}, { label=>"Packet size in flit:", param_name=>'PCK_SIZE', type=>'Spin-button', default_val=>4, content=>"2,".MAX_PCK_SIZ.",1", info=>undef, param_parent=>$sample, ref_delay=>undef}, - { label=>"Packet number limit per node:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>1000000, content=>"2,".MAX_PCK_NUM.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef}, + { label=>"Packet number limit per node:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>1000000, content=>"2,".MAX_PCK_NUM.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef}, { label=>"Emulation clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>MAX_SIM_CLKs, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef}, - + ); - my @siminfo = ( - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + my @siminfo = ( + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, + { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - { label=>"Packet size in flit:", param_name=>'PCK_SIZE', type=>'Spin-button', default_val=>4, content=>"2,".MAX_PCK_SIZ.",1", info=>undef, param_parent=>$sample, ref_delay=>undef}, + { label=>"Packet size in flit:", param_name=>'PCK_SIZE', type=>'Spin-button', default_val=>4, content=>"2,".MAX_PCK_SIZ.",1", info=>undef, param_parent=>$sample, ref_delay=>undef}, - { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,".MAX_PCK_NUM.",1", info=>"Simulation will stop when total numbr of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,".MAX_PCK_NUM.",1", info=>"Simulation will stop when total numbr of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - ); + { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + ); my $hot_num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); @@ -213,316 +206,316 @@ sub get_emulator_noc_configuration{ my $max= ($hot_num>0)? 100/$hot_num: 20; my @hotspot_info=( - { label=>'Hot Spot num:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, - content=>"1,5,1", info=>"Number of hot spot nodes in the network", - param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}, - { label=>'Hot Spot traffic percentage:', param_name=>'HOTSPOT_PERCENTAGE', type=>'Spin-button', default_val=>1, - content=>"1, $max,1", info=>"If it is set as n then each node sends n % of its traffic to each hotspot node", - param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - { label=>'Hot Spot nodes send enable:', param_name=>'HOTSPOT_SEND', type=>'Combo-box', default_val=>1, - content=>"0,1", info=>"If it is set as 0 then hot spot nodes only recieves packet from other nodes and do not send packets to others", - param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - - ); - - - my @info= ($mode eq "simulate")? @siminfo : @emulateinfo; - - my $coltmp=0; - foreach my $d ( @info) { - ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - my $traffic=$emulate->object_get_attribute($sample,"traffic"); - - if ($traffic eq 'hot spot'){ - foreach my $d ( @hotspot_info) { - ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - my $num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); - for (my $i=0;$i<$num;$i++){ - my $m=$i+1; - ($row,$coltmp)=add_param_widget ($emulate, "Hotspot $m tile num:", "HOTSPOT_CORE_$m", 0, 'Spin-button', "0,256,1", - "Defne the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node ", $table,$row,undef,1,$sample); - - } - - } - my $l= "Injection ratios in flits/clk/Endpoint (%). + { label=>'Hot Spot num:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, + content=>"1,5,1", info=>"Number of hot spot nodes in the network", + param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}, + { label=>'Hot Spot traffic percentage:', param_name=>'HOTSPOT_PERCENTAGE', type=>'Spin-button', default_val=>1, + content=>"1, $max,1", info=>"If it is set as n then each node sends n % of its traffic to each hotspot node", + param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + + { label=>'Hot Spot nodes send enable:', param_name=>'HOTSPOT_SEND', type=>'Combo-box', default_val=>1, + content=>"0,1", info=>"If it is set as 0 then hot spot nodes only recieves packet from other nodes and do not send packets to others", + param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + + + ); + + + my @info= ($mode eq "simulate")? @siminfo : @emulateinfo; + + my $coltmp=0; + foreach my $d ( @info) { + ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + } + my $traffic=$emulate->object_get_attribute($sample,"traffic"); + + if ($traffic eq 'hot spot'){ + foreach my $d ( @hotspot_info) { + ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + } + my $num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); + for (my $i=0;$i<$num;$i++){ + my $m=$i+1; + ($row,$coltmp)=add_param_widget ($emulate, "Hotspot $m tile num:", "HOTSPOT_CORE_$m", 0, 'Spin-button', "0,256,1", + "Defne the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node ", $table,$row,undef,1,$sample); + + } + + } + my $l= "Injection ratios in flits/clk/Endpoint (%). E.g. Injection ratio 10% means each endpoint inject one flit every 10 cycles. You can define individual ratios seprating by comma (\',\') or define a range of injection ratios with \$min:\$max:\$step format. As an example defining 2,3,4:10:2 will result in (2,3,4,6,8,10) injection ratios. " ; - my $u=get_injection_ratios ($emulate,$sample,"ratios"); - - attach_widget_to_table ($table,$row,gen_label_in_left("Injection ratios:"),gen_button_message ($l,"icons/help.png") , $u); $row++; - - my $scrolled_win = add_widget_to_scrolled_win($table); - - my $ok = def_image_button('icons/select.png','OK'); - my $mtable = def_table(10, 1, TRUE); - - $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable-> attach ($ok , 0, 1, 9, 10,'expand','shrink',2,2); - - add_widget_to_scrolled_win ($mtable,$set_win); - $set_win->show_all(); - - $set_win ->signal_connect (destroy => sub{ - - $emulate->object_add_attribute("active_setting",undef,undef); - }); - - - - $ok->signal_connect("clicked"=> sub{ - #check if sof file has been selected - my $s=get_sof_file_full_addr($emulate,$sample); - #check if injection ratios are valid - my $r=$emulate->object_get_attribute($sample,"ratios"); - if(defined $s && defined $r) { - $set_win->hide; - $emulate->object_add_attribute("active_setting",undef,undef); - set_gui_status($emulate,"ref",1); - } else { - - if(!defined $s){ - my $m=($mode eq 'simulate') ? "Please select NoC verilated file" : "Please select sof file!"; - message_dialog($m); - } else { - message_dialog("Please define valid injection ratio(s)!"); - } - } - }); - - -} - + my $u=get_injection_ratios ($emulate,$sample,"ratios"); + + attach_widget_to_table ($table,$row,gen_label_in_left("Injection ratios:"),gen_button_message ($l,"icons/help.png") , $u); $row++; + + my $scrolled_win = add_widget_to_scrolled_win($table); + + my $ok = def_image_button('icons/select.png','OK'); + my $mtable = def_table(10, 1, TRUE); + + $mtable->attach_defaults($scrolled_win,0,1,0,9); + $mtable-> attach ($ok , 0, 1, 9, 10,'expand','shrink',2,2); + + add_widget_to_scrolled_win ($mtable,$set_win); + $set_win->show_all(); + + $set_win ->signal_connect (destroy => sub{ + + $emulate->object_add_attribute("active_setting",undef,undef); + }); + + + + $ok->signal_connect("clicked"=> sub{ + #check if sof file has been selected + my $s=get_sof_file_full_addr($emulate,$sample); + #check if injection ratios are valid + my $r=$emulate->object_get_attribute($sample,"ratios"); + if(defined $s && defined $r) { + $set_win->hide; + $emulate->object_add_attribute("active_setting",undef,undef); + set_gui_status($emulate,"ref",1); + } else { + + if(!defined $s){ + my $m=($mode eq 'simulate') ? "Please select NoC verilated file" : "Please select sof file!"; + message_dialog($m); + } else { + message_dialog("Please define valid injection ratio(s)!"); + } + } + }); + + +} + ##################### -# gen_widgets_column +# gen_widgets_column ################### sub gen_emulation_column { - my ($emulate,$mode, $row_num,$info,$set_win,@charts)=@_; - my $table=def_table($row_num,10,FALSE); - if(!defined $set_win){ - $set_win=def_popwin_size(40,80,"NoC configuration setting",'percent'); - $set_win->signal_connect (delete_event => sub {$emulate->object_add_attribute("active_setting",undef,undef); $set_win->hide_on_delete }); - - } else{ - my @childs = $set_win->get_children; - foreach my $c (@childs){ $c->destroy;} - } - my $scrolled_win = gen_scr_win_with_adjst ($emulate,"emulation_column"); - add_widget_to_scrolled_win($table,$scrolled_win); - my $row=0; - - #title - my $title_l =($mode eq "simulate" ) ? "NoC Simulator" : "NoC Emulator"; - my $title=gen_label_in_center($title_l); - $table->attach ($title , 0, 10, $row, $row+1,'expand','shrink',2,2); $row++; - add_Hsep_to_table($table,0,10,$row);$row++; - - - - - my %order; - $order{'+/-'}=0; - $order{'Setting'}=1; - $order{'Run'}=2; - $order{'Name'}=3; - $order{'Color'}=4; - $order{'Clear'}=5; - $order{'Traffic'}=6; - $order{'Done'}=7; - - foreach my $t (sort keys %order){ - $table->attach (gen_label_in_center($t), $order{$t}, $order{$t}+1, $row, $row+1,'expand','shrink',2,2); - } - - my $traffics="Random,Transposed 1,Transposed 2,Tornado"; - - - $row++; - - - - #my $i=0; - my $active=$emulate->object_get_attribute("active_setting",undef); - my @samples; - @samples =$emulate->object_get_attribute_order("samples"); - - - - foreach my $ss (@samples){ - - - my $sample=$ss; - #my $sample="sample$i"; - #my $n=$i; - - my $name=$emulate->object_get_attribute($sample,"line_name"); - my $l; - my $s=($mode eq "simulate" ) ? 1 : get_sof_file_full_addr($emulate,$sample); - #check if injection ratios are valid - my $r=$emulate->object_get_attribute($sample,"ratios"); - if(defined $s && defined $name){ - - $l=def_image_button('icons/diagram.png',$name); - $l-> signal_connect("clicked" => sub{ - - __PACKAGE__->mk_accessors(qw{noc_param}); - my $temp = __PACKAGE__->new(); - - - - my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); - return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my $ref=$emulate->object_get_attribute($sample,"noc_info"); - if (defined $ref){ - my %noc_info= %$ref; - foreach my $p (sort keys %noc_info){ - $temp->object_add_attribute('noc_param',$p,$noc_info{$p}); - } - } - - show_topology_diagram ($temp); - }); - - my $traffic = def_button("Pattern"); - $traffic-> signal_connect("clicked" => sub{ - my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); - return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - $emulate->object_add_attribute('noc_param','T1',$T1); - $emulate->object_add_attribute('noc_param','T2',$T2); - $emulate->object_add_attribute('noc_param','T3',$T3); - $emulate->object_add_attribute('noc_param','TOPOLOGY',$topology); - my $pattern=""; - my $traffictype=$emulate->object_get_attribute($sample,"TRAFFIC_TYPE"); - $pattern=get_synthetic_traffic_pattern($emulate, $sample) if($traffictype eq "Synthetic"); - $pattern=" Custom traffic based on input file. " if($traffictype eq "Task-graph"); - - my $window = def_popwin_size(40,40,"Traffic pattern",'percent'); - my ($outbox,$tview)= create_txview(); - show_info($tview,"$pattern"); - $window->add ($outbox); - $window->show_all(); - - }); - - - $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); - $table->attach ($traffic, $order{'Traffic'}, $order{'Traffic'}+1, $row, $row+1,'expand','shrink',2,2); - - - } else { - $l=gen_label_in_left("Define NoC configuration"); - $l->set_markup("Define NoC configuration"); - $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); - } - - - #remove - my $remove=def_image_button("icons/cancel.png"); - $table->attach ($remove,$order{'+/-'},$order{'+/-'}+1, $row, $row+1,'expand','shrink',2,2); - $remove->signal_connect("clicked"=> sub{ - $emulate->object_delete_attribute_order("samples",$sample); - set_gui_status($emulate,"ref",2); - }); - - #setting - my $set=def_image_button("icons/setting.png"); - $table->attach ($set, $order{'Setting'}, $order{'Setting'}+1, $row, $row+1,'expand','shrink',2,2); - - - if(defined $active){#The setting windows ask for refershing so open it again - get_noc_configuration($emulate,$mode,$sample,$set_win) if ($active eq $sample); - } - - - - $set->signal_connect("clicked"=> sub{ - $emulate->object_add_attribute("active_setting",undef,$sample); - get_noc_configuration($emulate,$mode,$sample,$set_win); - }); - - - - my $color_num=$emulate->object_get_attribute($sample,"color"); - if(!defined $color_num){ - $color_num = (scalar @samples) +1; - $emulate->object_add_attribute($sample,"color",$color_num); - } - my $color=def_colored_button(" ",$color_num); - $table->attach ($color, $order{'Color'}, $order{'Color'}+1, $row, $row+1,'fill','fill',2,2); - - $color->signal_connect("clicked"=> sub{ - get_color_window($emulate,$sample,"color"); - }); - - #clear line - my $clear = def_image_button('icons/clear.png'); - $clear->signal_connect("clicked"=> sub{ - foreach my $chart (@charts){ - $emulate->object_add_attribute ($sample,"$chart->{result_name}",undef); - - #print "\$emulate->object_add_attribute ($sample,$chart->{result_name}_result,undef);"; - - } - set_gui_status($emulate,"ref",2); - }); - $table->attach ($clear, $order{'Clear'}, $order{'Clear'}+1, $row, $row+1,'expand','shrink',2,2); - #run/pause - my $run = def_image_button('icons/run.png',undef); - $table->attach ($run, $order{'Run'}, $order{'Run'}+1, $row, $row+1,'expand','shrink',2,2); - $run->signal_connect("clicked"=> sub{ - $emulate->object_add_attribute ($sample,"status","run"); - #start the emulator if it is not running - my $status= $emulate->object_get_attribute('status',undef); - if($status ne 'run'){ - - run_emulator($emulate,$info) if($mode eq 'emulate'); - run_simulator($emulate,$info) if($mode eq 'simulate'); - set_gui_status($emulate,"ref",2); - } - - }); - - my $image = gen_noc_status_image($emulate,$sample); - $table->attach ($image, $order{'Done'},$order{'Done'}+1, $row, $row+1,'expand','shrink',2,2); - - $row++; - - } - # add new simulation - - my $add=def_image_button("icons/plus.png",' A_dd ',FALSE,1); - $table->attach ($add, $order{'+/-'},$order{'+/-'}+2, $row, $row+1,'expand','shrink',2,2); - - - - $add->signal_connect("clicked"=> sub{ - my $n=$emulate->object_get_attribute("id",undef); - $n=0 if (!defined $n); - my $sample="sample$n"; - $n++; - $emulate->object_add_attribute("id",undef,$n); - $emulate->object_add_attribute("active_setting",undef,$sample); - #get_noc_configuration($emulate,$mode,$sample,$set_win); - $emulate->object_add_attribute_order("samples",$sample); - set_gui_status($emulate,"ref",1); - - }); - - - - return ($scrolled_win,$set_win); -} + my ($emulate,$mode, $row_num,$info,$set_win,@charts)=@_; + my $table=def_table($row_num,10,FALSE); + if(!defined $set_win){ + $set_win=def_popwin_size(40,80,"NoC configuration setting",'percent'); + $set_win->signal_connect (delete_event => sub {$emulate->object_add_attribute("active_setting",undef,undef); $set_win->hide_on_delete }); + + } else{ + my @childs = $set_win->get_children; + foreach my $c (@childs){ $c->destroy;} + } + my $scrolled_win = gen_scr_win_with_adjst ($emulate,"emulation_column"); + add_widget_to_scrolled_win($table,$scrolled_win); + my $row=0; + + #title + my $title_l =($mode eq "simulate" ) ? "NoC Simulator" : "NoC Emulator"; + my $title=gen_label_in_center($title_l); + $table->attach ($title , 0, 10, $row, $row+1,'expand','shrink',2,2); $row++; + add_Hsep_to_table($table,0,10,$row);$row++; + + + + + my %order; + $order{'+/-'}=0; + $order{'Setting'}=1; + $order{'Run'}=2; + $order{'Name'}=3; + $order{'Color'}=4; + $order{'Clear'}=5; + $order{'Traffic'}=6; + $order{'Done'}=7; + + foreach my $t (sort keys %order){ + $table->attach (gen_label_in_center($t), $order{$t}, $order{$t}+1, $row, $row+1,'expand','shrink',2,2); + } + + my $traffics="Random,Transposed 1,Transposed 2,Tornado"; + + + $row++; + + + + #my $i=0; + my $active=$emulate->object_get_attribute("active_setting",undef); + my @samples; + @samples =$emulate->object_get_attribute_order("samples"); + + + + foreach my $ss (@samples){ + + + my $sample=$ss; + #my $sample="sample$i"; + #my $n=$i; + + my $name=$emulate->object_get_attribute($sample,"line_name"); + my $l; + my $s=($mode eq "simulate" ) ? 1 : get_sof_file_full_addr($emulate,$sample); + #check if injection ratios are valid + my $r=$emulate->object_get_attribute($sample,"ratios"); + if(defined $s && defined $name){ + + $l=def_image_button('icons/diagram.png',$name); + $l-> signal_connect("clicked" => sub{ + + __PACKAGE__->mk_accessors(qw{noc_param}); + my $temp = __PACKAGE__->new(); + + + + my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); + return if $st==0; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my $ref=$emulate->object_get_attribute($sample,"noc_info"); + if (defined $ref){ + my %noc_info= %$ref; + foreach my $p (sort keys %noc_info){ + $temp->object_add_attribute('noc_param',$p,$noc_info{$p}); + } + } + + show_topology_diagram ($temp); + }); + + my $traffic = def_button("Pattern"); + $traffic-> signal_connect("clicked" => sub{ + my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); + return if $st==0; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + $emulate->object_add_attribute('noc_param','T1',$T1); + $emulate->object_add_attribute('noc_param','T2',$T2); + $emulate->object_add_attribute('noc_param','T3',$T3); + $emulate->object_add_attribute('noc_param','TOPOLOGY',$topology); + my $pattern=""; + my $traffictype=$emulate->object_get_attribute($sample,"TRAFFIC_TYPE"); + $pattern=get_synthetic_traffic_pattern($emulate, $sample) if($traffictype eq "Synthetic"); + $pattern=" Custom traffic based on input file. " if($traffictype eq "Task-graph"); + + my $window = def_popwin_size(40,40,"Traffic pattern",'percent'); + my ($outbox,$tview)= create_txview(); + show_info($tview,"$pattern"); + $window->add ($outbox); + $window->show_all(); + + }); + + + $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); + $table->attach ($traffic, $order{'Traffic'}, $order{'Traffic'}+1, $row, $row+1,'expand','shrink',2,2); + + + } else { + $l=gen_label_in_left("Define NoC configuration"); + $l->set_markup("Define NoC configuration"); + $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); + } + + + #remove + my $remove=def_image_button("icons/cancel.png"); + $table->attach ($remove,$order{'+/-'},$order{'+/-'}+1, $row, $row+1,'expand','shrink',2,2); + $remove->signal_connect("clicked"=> sub{ + $emulate->object_delete_attribute_order("samples",$sample); + set_gui_status($emulate,"ref",2); + }); + + #setting + my $set=def_image_button("icons/setting.png"); + $table->attach ($set, $order{'Setting'}, $order{'Setting'}+1, $row, $row+1,'expand','shrink',2,2); + + + if(defined $active){#The setting windows ask for refershing so open it again + get_noc_configuration($emulate,$mode,$sample,$set_win) if ($active eq $sample); + } + + + + $set->signal_connect("clicked"=> sub{ + $emulate->object_add_attribute("active_setting",undef,$sample); + get_noc_configuration($emulate,$mode,$sample,$set_win); + }); + + + + my $color_num=$emulate->object_get_attribute($sample,"color"); + if(!defined $color_num){ + $color_num = (scalar @samples) +1; + $emulate->object_add_attribute($sample,"color",$color_num); + } + my $color=def_colored_button(" ",$color_num); + $table->attach ($color, $order{'Color'}, $order{'Color'}+1, $row, $row+1,'fill','fill',2,2); + + $color->signal_connect("clicked"=> sub{ + get_color_window($emulate,$sample,"color"); + }); + + #clear line + my $clear = def_image_button('icons/clear.png'); + $clear->signal_connect("clicked"=> sub{ + foreach my $chart (@charts){ + $emulate->object_add_attribute ($sample,"$chart->{result_name}",undef); + + #print "\$emulate->object_add_attribute ($sample,$chart->{result_name}_result,undef);"; + + } + set_gui_status($emulate,"ref",2); + }); + $table->attach ($clear, $order{'Clear'}, $order{'Clear'}+1, $row, $row+1,'expand','shrink',2,2); + #run/pause + my $run = def_image_button('icons/run.png',undef); + $table->attach ($run, $order{'Run'}, $order{'Run'}+1, $row, $row+1,'expand','shrink',2,2); + $run->signal_connect("clicked"=> sub{ + $emulate->object_add_attribute ($sample,"status","run"); + #start the emulator if it is not running + my $status= $emulate->object_get_attribute('status',undef); + if($status ne 'run'){ + + run_emulator($emulate,$info) if($mode eq 'emulate'); + run_simulator($emulate,$info) if($mode eq 'simulate'); + set_gui_status($emulate,"ref",2); + } + + }); + + my $image = gen_noc_status_image($emulate,$sample); + $table->attach ($image, $order{'Done'},$order{'Done'}+1, $row, $row+1,'expand','shrink',2,2); + + $row++; + + } + # add new simulation + + my $add=def_image_button("icons/plus.png",' A_dd ',FALSE,1); + $table->attach ($add, $order{'+/-'},$order{'+/-'}+2, $row, $row+1,'expand','shrink',2,2); + + + + $add->signal_connect("clicked"=> sub{ + my $n=$emulate->object_get_attribute("id",undef); + $n=0 if (!defined $n); + my $sample="sample$n"; + $n++; + $emulate->object_add_attribute("id",undef,$n); + $emulate->object_add_attribute("active_setting",undef,$sample); + #get_noc_configuration($emulate,$mode,$sample,$set_win); + $emulate->object_add_attribute_order("samples",$sample); + set_gui_status($emulate,"ref",1); + + }); + + + + return ($scrolled_win,$set_win); +} @@ -531,45 +524,45 @@ sub gen_emulation_column { ########## sub check_sample{ - my ($emulate,$sample,$info)=@_; - my $status=1; - my $sof=get_sof_file_full_addr($emulate,$sample); - - - - # ckeck if sample have sof file - if(!defined $sof){ - #add_info($info, "Error: SoF file has not set for $sample!\n"); - add_colored_info($info, "Error: SoF file has not set for $sample!\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); - $status=0; - } else { - # ckeck if sof file has info file - my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); - my $sof_info= "$path$name.inf"; - - # print "\n $sof \t $sof_info\n"; - - if(!(-f $sof_info)){ - add_colored_info($info, "Error: Could not find $name.inf file in $path. An information file is required for each sof file containig the device name and NoC configuration. Press F3 for more help.\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); - $status=0; - }else { #add info - my $pp= do $sof_info ; - - my $p=$pp->{'noc_param'}; - - $status=0 if $@; - message_dialog("Error reading: $@",'error') if $@; - if ($status==1){ - $emulate->object_add_attribute ($sample,"noc_info",$p) ; - - - } - } - } - - return $status; + my ($emulate,$sample,$info)=@_; + my $status=1; + my $sof=get_sof_file_full_addr($emulate,$sample); + + + + # ckeck if sample have sof file + if(!defined $sof){ + #add_info($info, "Error: SoF file has not set for $sample!\n"); + add_colored_info($info, "Error: SoF file has not set for $sample!\n",'red'); + $emulate->object_add_attribute ($sample,"status","failed"); + $status=0; + } else { + # ckeck if sof file has info file + my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); + my $sof_info= "$path$name.inf"; + + # print "\n $sof \t $sof_info\n"; + + if(!(-f $sof_info)){ + add_colored_info($info, "Error: Could not find $name.inf file in $path. An information file is required for each sof file containig the device name and NoC configuration. Press F3 for more help.\n",'red'); + $emulate->object_add_attribute ($sample,"status","failed"); + $status=0; + }else { #add info + my $pp= do $sof_info ; + + my $p=$pp->{'noc_param'}; + + $status=0 if $@; + message_dialog("Error reading: $@",'error') if $@; + if ($status==1){ + $emulate->object_add_attribute ($sample,"noc_info",$p) ; + + + } + } + } + + return $status; } @@ -584,142 +577,142 @@ sub check_sample{ # images ########## sub get_status_gif{ - my $emulate=shift; - my $status= $emulate->object_get_attribute('status',undef); - if($status eq 'ideal'){ - return show_gif ("icons/ProNoC.png"); - } elsif ($status eq 'run') { - my($width,$hight)=max_win_size(); - my $image=($width>=1600)? "icons/hamster_l.gif": - ($width>=1200)? "icons/hamster_m.gif": "icons/hamster_s.gif"; - - return show_gif ($image); - } elsif ($status eq 'programmer_failed') { - return show_gif ("icons/Error.png"); - } - -} + my $emulate=shift; + my $status= $emulate->object_get_attribute('status',undef); + if($status eq 'ideal'){ + return show_gif ("icons/ProNoC.png"); + } elsif ($status eq 'run') { + my($width,$hight)=max_win_size(); + my $image=($width>=1600)? "icons/hamster_l.gif": + ($width>=1200)? "icons/hamster_m.gif": "icons/hamster_s.gif"; + + return show_gif ($image); + } elsif ($status eq 'programmer_failed') { + return show_gif ("icons/Error.png"); + } + +} sub gen_noc_status_image { - my ($emulate,$sample)=@_; - my $status= $emulate->object_get_attribute ($sample,"status"); - $status='' if(!defined $status); - my $image; - my $box = def_hbox(TRUE,1); - $image = new_image_from_file ("icons/load.gif") if($status eq "run"); - $image = def_icon("icons/button_ok.png") if($status eq "done"); - $image = def_icon("icons/warning.png") if($status eq "failed"); - - if (defined $image) { - $box->pack_start (add_frame_to_image($image), FALSE, FALSE, 0); - } - return $box; - + my ($emulate,$sample)=@_; + my $status= $emulate->object_get_attribute ($sample,"status"); + $status='' if(!defined $status); + my $image; + my $box = def_hbox(TRUE,1); + $image = new_image_from_file ("icons/load.gif") if($status eq "run"); + $image = def_icon("icons/button_ok.png") if($status eq "done"); + $image = def_icon("icons/warning.png") if($status eq "failed"); + + if (defined $image) { + $box->pack_start (add_frame_to_image($image), FALSE, FALSE, 0); + } + return $box; + } ############ -# run_emulator +# run_emulator ########### sub run_emulator { - my ($emulate,$info)=@_; - #my $graph_name="latency_ratio"; - #return if(!check_samples($emulate,$info)); - $emulate->object_add_attribute('status',undef,'run'); - set_gui_status($emulate,"ref",1); - show_colored_info($info, "start emulation\n",'blue'); - -# #search for available usb blaster -# my $cmd = "jtagconfig"; -# my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); -# my @matches= ($stdout =~ /USB-Blaster.*/g); -# my $usb_blaster=$matches[0]; -# if (!defined $usb_blaster){ -# add_info($info, "jtagconfig could not find any USB blaster cable: $stdout \n"); -# $emulate->object_add_attribute('status',undef,'programmer_failed'); -# set_gui_status($emulate,"ref",2); -# #/***/ -# return; -# }else{ -# add_info($info, "find $usb_blaster\n"); -# } - my @samples =$emulate->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - my $status=$emulate->object_get_attribute ($sample,"status"); - next if($status ne "run"); - next if(!check_sample($emulate,$sample,$info)); - my $r= $emulate->object_get_attribute($sample,"ratios"); - my @ratios=@{check_inserted_ratios($r)}; - #$emulate->object_add_attribute ("sample$i","status","run"); - my $sof=get_sof_file_full_addr($emulate,$sample); - add_info($info, "Programe FPGA device using $sof.sof\n"); - my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); - my $programmer="$path/program_device.sh"; - my $jtag_intfc="$path/jtag_intfc.sh"; - if((-f $programmer)==0){ - add_colored_info ($info, " Error: file \"$programmer\" dose not exist. \n",'red'); - $emulate->object_add_attribute('status',undef,'programmer_failed'); - $emulate->object_add_attribute ($sample,"status","failed"); - set_gui_status($emulate,"ref",2); - last; - } - if((-f $jtag_intfc)==0){ - add_colored_info ($info, " Error: file \"$jtag_intfc\" dose not exist. \n",'red'); - $emulate->object_add_attribute('status',undef,'programmer_failed'); - $emulate->object_add_attribute ($sample,"status","failed"); - set_gui_status($emulate,"ref",2); - last; - } - my $cmd = "bash $programmer $sof.sof"; - - - #my $Quartus_bin= $ENV{QUARTUS_BIN}; - - - #my $cmd = "$Quartus_bin/quartus_pgm -c \"$usb_blaster\" -m jtag -o \"p;$sof\""; - - #my $output = `$cmd 2>&1 1>/dev/null`; # either with backticks - - #/***/ - my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); - if($exit){#programming FPGA board has failed - $emulate->object_add_attribute('status',undef,'programmer_failed'); - add_colored_info($info, "$stdout\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); - set_gui_status($emulate,"ref",2); - next; - } - #print "$stdout\n"; - - # load noc configuration - foreach my $ratio_in (@ratios){ - - add_info($info, "Configure packet generators for injection ratio of $ratio_in \% \n"); - if(!programe_pck_gens($emulate,$sample,$ratio_in,$info,$jtag_intfc)){ - add_colored_info($info, "Error in programe_pck_gens function\n",'red'); - next; - } - - - my $r=read_pack_gen($emulate,$sample,$info,$jtag_intfc,$ratio_in); - next if (!defined $r); - - - - set_gui_status($emulate,"ref",2); - - } - $emulate->object_add_attribute ($sample,"status","done"); - - } - - add_colored_info($info, "End emulation!\n",'blue'); - $emulate->object_add_attribute('status',undef,'ideal'); - set_gui_status($emulate,"ref",1); + my ($emulate,$info)=@_; + #my $graph_name="latency_ratio"; + #return if(!check_samples($emulate,$info)); + $emulate->object_add_attribute('status',undef,'run'); + set_gui_status($emulate,"ref",1); + show_colored_info($info, "start emulation\n",'blue'); + +# #search for available usb blaster +# my $cmd = "jtagconfig"; +# my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); +# my @matches= ($stdout =~ /USB-Blaster.*/g); +# my $usb_blaster=$matches[0]; +# if (!defined $usb_blaster){ +# add_info($info, "jtagconfig could not find any USB blaster cable: $stdout \n"); +# $emulate->object_add_attribute('status',undef,'programmer_failed'); +# set_gui_status($emulate,"ref",2); +# #/***/ +# return; +# }else{ +# add_info($info, "find $usb_blaster\n"); +# } + my @samples =$emulate->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + my $status=$emulate->object_get_attribute ($sample,"status"); + next if($status ne "run"); + next if(!check_sample($emulate,$sample,$info)); + my $r= $emulate->object_get_attribute($sample,"ratios"); + my @ratios=@{check_inserted_ratios($r)}; + #$emulate->object_add_attribute ("sample$i","status","run"); + my $sof=get_sof_file_full_addr($emulate,$sample); + add_info($info, "Programe FPGA device using $sof.sof\n"); + my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); + my $programmer="$path/program_device.sh"; + my $jtag_intfc="$path/jtag_intfc.sh"; + if((-f $programmer)==0){ + add_colored_info ($info, " Error: file \"$programmer\" dose not exist. \n",'red'); + $emulate->object_add_attribute('status',undef,'programmer_failed'); + $emulate->object_add_attribute ($sample,"status","failed"); + set_gui_status($emulate,"ref",2); + last; + } + if((-f $jtag_intfc)==0){ + add_colored_info ($info, " Error: file \"$jtag_intfc\" dose not exist. \n",'red'); + $emulate->object_add_attribute('status',undef,'programmer_failed'); + $emulate->object_add_attribute ($sample,"status","failed"); + set_gui_status($emulate,"ref",2); + last; + } + my $cmd = "bash $programmer $sof.sof"; + + + #my $Quartus_bin= $ENV{QUARTUS_BIN}; + + + #my $cmd = "$Quartus_bin/quartus_pgm -c \"$usb_blaster\" -m jtag -o \"p;$sof\""; + + #my $output = `$cmd 2>&1 1>/dev/null`; # either with backticks + + #/***/ + my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); + if($exit){#programming FPGA board has failed + $emulate->object_add_attribute('status',undef,'programmer_failed'); + add_colored_info($info, "$stdout\n",'red'); + $emulate->object_add_attribute ($sample,"status","failed"); + set_gui_status($emulate,"ref",2); + next; + } + #print "$stdout\n"; + + # load noc configuration + foreach my $ratio_in (@ratios){ + + add_info($info, "Configure packet generators for injection ratio of $ratio_in \% \n"); + if(!programe_pck_gens($emulate,$sample,$ratio_in,$info,$jtag_intfc)){ + add_colored_info($info, "Error in programe_pck_gens function\n",'red'); + next; + } + + + my $r=read_pack_gen($emulate,$sample,$info,$jtag_intfc,$ratio_in); + next if (!defined $r); + + + + set_gui_status($emulate,"ref",2); + + } + $emulate->object_add_attribute ($sample,"status","done"); + + } + + add_colored_info($info, "End emulation!\n",'blue'); + $emulate->object_add_attribute('status',undef,'ideal'); + set_gui_status($emulate,"ref",1); } @@ -728,159 +721,144 @@ sub run_emulator { ############## -# process_notebook_gen +# process_notebook_gen ############## sub process_notebook_gen{ - my ($emulate,$info,$mode,$set_win,@charts)=@_; - my $notebook = gen_notebook(); - $notebook->set_tab_pos ('left'); - $notebook->set_scrollable(TRUE); - #$notebook->can_focus(FALSE); - - my $page1; - ($page1,$set_win)=gen_emulation_column($emulate, $mode,10,$info,$set_win,@charts); - $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run emulator ")) if($mode eq "emulate"); - $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run simulator ")) if($mode eq "simulate"); - - - my $page2=get_noc_setting_gui ($emulate,$info,$mode); - my $tt=($mode eq "emulate")? " _Generate NoC \nEmulation Model" : " _Generate NoC \nSimulation Model" ; - $notebook->append_page ($page2,gen_label_with_mnemonic ($tt)); - - - - my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($emulate,"process_sc_win")); - $scrolled_win->show_all; - my $page_num=$emulate->object_get_attribute ("process_notebook","currentpage"); - $notebook->set_current_page ($page_num) if(defined $page_num); - $notebook->signal_connect( 'switch-page'=> sub{ - $emulate->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber - - }); - - return ($scrolled_win,$set_win); - + my ($emulate,$info,$mode,$set_win,@charts)=@_; + my $notebook = gen_notebook(); + $notebook->set_tab_pos ('left'); + $notebook->set_scrollable(TRUE); + #$notebook->can_focus(FALSE); + + my $page1; + ($page1,$set_win)=gen_emulation_column($emulate, $mode,10,$info,$set_win,@charts); + $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run emulator ")) if($mode eq "emulate"); + $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run simulator ")) if($mode eq "simulate"); + + + my $page2=get_noc_setting_gui ($emulate,$info,$mode); + my $tt=($mode eq "emulate")? " _Generate NoC \nEmulation Model" : " _Generate NoC \nSimulation Model" ; + $notebook->append_page ($page2,gen_label_with_mnemonic ($tt)); + + + + my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($emulate,"process_sc_win")); + $scrolled_win->show_all; + my $page_num=$emulate->object_get_attribute ("process_notebook","currentpage"); + $notebook->set_current_page ($page_num) if(defined $page_num); + $notebook->signal_connect( 'switch-page'=> sub{ + $emulate->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber + + }); + + return ($scrolled_win,$set_win); + } sub get_noc_setting_gui { - my ($emulate,$info_text,$mode)=@_; - my $table=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; - - - my $scrolled_win = gen_scr_win_with_adjst ($emulate,"noc_setting_gui"); - add_widget_to_scrolled_win($table,$scrolled_win); - my $row=noc_config ($emulate,$table,$info_text); - - my($label,$param,$default,$content,$type,$info); - my @dirs = grep {-d} glob("../boards/Altera/*"); - my $fpgas; - foreach my $dir (@dirs) { - my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); - $default=$name; - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - } - - my @fpgainfo; - if($mode eq "emulate"){ - @fpgainfo = ( - { label=>'Pck. injector FIFO Width:', param_name=>'TIMSTMP_FIFO_NUM', type=>'Spin-button', default_val=>16, content=>"2,128,2", info=>"Packet injectors' timestamp FIFO width. In case a packet cannot be injected according to the desired injection ratio, the current system time is saved in a FIFO and then at injection time it will be read and attached to the packet. The larger FIFO width results in more accurate latency calculation at the cost of higher area overhead." , param_parent=>'fpga_param', ref_delay=> undef}, - { label=>'Save as:', param_name=>'SAVE_NAME', type=>"Entry", default_val=>'emulate1', content=>undef, info=>undef, param_parent=>'fpga_param', ref_delay=>undef}, - { label=>"Project directory", param_name=>"SOF_DIR", type=>"DIR_path", default_val=>"$ENV{'PRONOC_WORK'}/emulate", content=>undef, info=>"Define the working directory for generating .sof file", param_parent=>'fpga_param',ref_delay=>undef }, - ); - - } - else { - @fpgainfo = ( - { label=>'Pck. injector FIFO Width:', param_name=>'TIMSTMP_FIFO_NUM', type=>'Spin-button', default_val=>16, content=>"2,128,2", info=>"Packet injectors' timestamp FIFO width. In case a packet cannot be injected according to the desired injection ratio, the current system time is saved in a FIFO and then at injection time it will be read and attached to the packet. The larger FIFO width results in more accurate latency calculation." , param_parent=>'fpga_param', ref_delay=> undef}, - { label=>'Save as:', param_name=>'SAVE_NAME', type=>"Entry", default_val=>'simulate1', content=>undef, info=>undef, param_parent=>'sim_param', ref_delay=>undef}, - { label=>"Project directory", param_name=>"BIN_DIR", type=>"DIR_path", default_val=>"$ENV{'PRONOC_WORK'}/simulate", content=>undef, info=>"Define the working directory for generating simulation executable binarry file", param_parent=>'sim_param',ref_delay=>undef }, - - ); - } - - my $coltmp=0; - foreach my $d (@fpgainfo) { - ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}); - } - - my $maintable=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; - - my $generate = def_image_button('icons/gen.png','Gener_ate',FALSE,1); - my $diagram = def_image_button('icons/diagram.png','Diagram'); - my $import = def_image_button('icons/import.png','I_mport',FALSE,1); - set_tip($import ,"Import NoC configuration from file"); - - $maintable->attach_defaults ($scrolled_win, 0,10, 0, 9); - $maintable->attach_defaults (gen_Hsep(), 0,10, 8, 9); - $maintable->attach ($generate, 0,2, 9, 10,'expand','shrink',2,2); - $maintable->attach ($diagram, 2,4, 9, 10,'expand','shrink',2,2); - $maintable->attach ($import, 4,6, 9, 10,'expand','shrink',2,2); - - + my ($emulate,$info_text,$mode)=@_; + my $table=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; + my $scrolled_win = gen_scr_win_with_adjst ($emulate,"noc_setting_gui"); + add_widget_to_scrolled_win($table,$scrolled_win); + my $row=noc_config ($emulate,$table,$info_text); + my($label,$param,$default,$content,$type,$info); + my @dirs = grep {-d} glob("../boards/Altera/*"); + my $fpgas; + foreach my $dir (@dirs) { + my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); + $default=$name; + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + } + my @fpgainfo; + if($mode eq "emulate"){ + @fpgainfo = ( + { label=>'Pck. injector FIFO Width:', param_name=>'TIMSTMP_FIFO_NUM', type=>'Spin-button', default_val=>16, content=>"2,128,2", info=>"Packet injectors' timestamp FIFO width. In case a packet cannot be injected according to the desired injection ratio, the current system time is saved in a FIFO and then at injection time it will be read and attached to the packet. The larger FIFO width results in more accurate latency calculation at the cost of higher area overhead." , param_parent=>'fpga_param', ref_delay=> undef}, + { label=>'Save as:', param_name=>'SAVE_NAME', type=>"Entry", default_val=>'emulate1', content=>undef, info=>undef, param_parent=>'fpga_param', ref_delay=>undef}, + { label=>"Project directory", param_name=>"SOF_DIR", type=>"DIR_path", default_val=>"$ENV{'PRONOC_WORK'}/emulate", content=>undef, info=>"Define the working directory for generating .sof file", param_parent=>'fpga_param',ref_delay=>undef }, + ); + } + else { + @fpgainfo = ( + { label=>'Pck. injector FIFO Width:', param_name=>'TIMSTMP_FIFO_NUM', type=>'Spin-button', default_val=>16, content=>"2,128,2", info=>"Packet injectors' timestamp FIFO width. In case a packet cannot be injected according to the desired injection ratio, the current system time is saved in a FIFO and then at injection time it will be read and attached to the packet. The larger FIFO width results in more accurate latency calculation." , param_parent=>'fpga_param', ref_delay=> undef}, + { label=>'Save as:', param_name=>'SAVE_NAME', type=>"Entry", default_val=>'simulate1', content=>undef, info=>undef, param_parent=>'sim_param', ref_delay=>undef}, + { label=>"Project directory", param_name=>"BIN_DIR", type=>"DIR_path", default_val=>"$ENV{'PRONOC_WORK'}/simulate", content=>undef, info=>"Define the working directory for generating simulation executable binarry file", param_parent=>'sim_param',ref_delay=>undef }, + ); + } + my $coltmp=0; + foreach my $d (@fpgainfo) { + ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}); + } + my $maintable=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; + my $generate = def_image_button('icons/gen.png','Gener_ate',FALSE,1); + my $diagram = def_image_button('icons/diagram.png','Diagram'); + my $import = def_image_button('icons/import.png','I_mport',FALSE,1); + set_tip($import ,"Import NoC configuration from file"); + $maintable->attach_defaults ($scrolled_win, 0,10, 0, 9); + $maintable->attach_defaults (gen_Hsep(), 0,10, 8, 9); + $maintable->attach ($generate, 0,2, 9, 10,'expand','shrink',2,2); + $maintable->attach ($diagram, 2,4, 9, 10,'expand','shrink',2,2); + $maintable->attach ($import, 4,6, 9, 10,'expand','shrink',2,2); $diagram-> signal_connect("clicked" => sub{ show_topology_diagram ($emulate); - }); + }); $generate->signal_connect ('clicked'=> sub{ - generate_sof_file($emulate,$info_text) if($mode eq "emulate"); - generate_sim_bin_file($emulate,$info_text) if($mode eq "simulate"); - - }); - - $import-> signal_connect("clicked" => sub{ - import_noc_info_file($emulate,$mode); - }); - - $scrolled_win->show_all; - return $maintable; + generate_sof_file($emulate,$info_text) if($mode eq "emulate"); + generate_sim_bin_file($emulate,$info_text) if($mode eq "simulate"); + }); + $import-> signal_connect("clicked" => sub{ + import_noc_info_file($emulate,$mode); + }); + $scrolled_win->show_all; + return $maintable; } sub import_noc_info_file{ - my ($self,$mode)=@_; - my $file; - my $dialog = gen_file_dialog(undef,'inf'); - - my $open_in = ($mode ne "emulate" ) ? abs_path("$ENV{'PRONOC_WORK'}/simulate") : abs_path("$ENV{'PRONOC_WORK'}/emulate"); - $dialog->set_current_folder ($open_in); - if ( "ok" eq $dialog->run ) { - my $status=1; - $file = $dialog->get_filename; - my $pp= do $file ; - my $p=$pp->{'noc_param'}; - $status=0 if $@; - message_dialog("Error reading: $@") if $@; - if ($status==1){ - $self->object_add_attribute ("noc_param",undef,$p); - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - my $attr1 = ($mode ne "emulate" ) ? 'sim_param' : 'fpga_param'; - $self->object_add_attribute ($attr1,'SAVE_NAME',$name); - - set_gui_status($self,"ref",1); - } - } - $dialog->destroy; + my ($self,$mode)=@_; + my $file; + my $dialog = gen_file_dialog(undef,'inf'); + + my $open_in = ($mode ne "emulate" ) ? abs_path("$ENV{'PRONOC_WORK'}/simulate") : abs_path("$ENV{'PRONOC_WORK'}/emulate"); + $dialog->set_current_folder ($open_in); + if ( "ok" eq $dialog->run ) { + my $status=1; + $file = $dialog->get_filename; + my $pp= do $file ; + my $p=$pp->{'noc_param'}; + $status=0 if $@; + message_dialog("Error reading: $@") if $@; + if ($status==1){ + $self->object_add_attribute ("noc_param",undef,$p); + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + my $attr1 = ($mode ne "emulate" ) ? 'sim_param' : 'fpga_param'; + $self->object_add_attribute ($attr1,'SAVE_NAME',$name); + + set_gui_status($self,"ref",1); + } + } + $dialog->destroy; } ########## -# generate_sof_file +# generate_sof_file ########## sub generate_sof_file { - my ($self,$info)=@_; - my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); - my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; - my $top = "$target_dir/src_verilog/${name}_top.v"; - - if (!defined $name){ - message_dialog("Please define the Save as filed!"); - return; - } - - #copy all noc source codes - my @files = ( + my ($self,$info)=@_; + my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); + my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; + my $top = "$target_dir/src_verilog/${name}_top.v"; + + if (!defined $name){ + message_dialog("Please define the Save as filed!"); + return; + } + + #copy all noc source codes + my @files = ( '/mpsoc/rtl/src_emulate/rtl/', '/mpsoc/rtl/src_peripheral/jtag/jtag_wb/', '/mpsoc/rtl/src_peripheral/ram/', @@ -890,251 +868,251 @@ sub generate_sof_file { '/mpsoc/rtl/src_topology/', '/mpsoc/rtl/src_noc/'); - my $dir = Cwd::getcwd(); - my $project_dir = abs_path("$dir/../../"); - my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("mkdir -p $target_dir/src_verilog" ); - copy_file_and_folders(\@files,$project_dir,"$target_dir/src_verilog/lib/"); - - - #generate parameters for emulator_top.v file - gen_noc_localparam_v_file($self,"$target_dir/src_verilog/lib/src_noc/"); - - open(FILE, ">$top") || die "Can not open: $!"; - print FILE create_emulate_top($self,$name,$top); - close(FILE) || die "Error closing file: $!"; - select_compiler($self,$name,$top,$target_dir,\&save_the_sof_file); - + my $dir = Cwd::getcwd(); + my $project_dir = abs_path("$dir/../../"); + my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("mkdir -p $target_dir/src_verilog" ); + copy_file_and_folders(\@files,$project_dir,"$target_dir/src_verilog/lib/"); + + + #generate parameters for emulator_top.v file + gen_noc_localparam_v_file($self,"$target_dir/src_verilog/lib/src_noc/"); + + open(FILE, ">$top") || die "Can not open: $!"; + print FILE create_emulate_top($self,$name,$top); + close(FILE) || die "Error closing file: $!"; + select_compiler($self,$name,$top,$target_dir,\&save_the_sof_file); + return; } sub create_emulate_top{ - my ($self,$name,$top)=@_; - my $top_v= get_license_header("$top"); + my ($self,$name,$top)=@_; + my $top_v= get_license_header("$top"); -$top_v ="$top_v +$top_v ="$top_v -`timescale 1ns/1ps +`timescale 1ns/1ps module ${name}_top( - output done_led, - output noc_reset_led, - output jtag_reset_led, - input reset, - input clk + output done_led, + output noc_reset_led, + output jtag_reset_led, + input reset, + input clk ); - localparam - STATISTIC_VJTAG_INDEX=124, - PATTERN_VJTAG_INDEX=125, - COUNTER_VJTAG_INDEX=126, - DONE_RESET_VJTAG_INDEX=127; - - - - - wire reset_noc, reset_injector, reset_noc_sync, reset_injector_sync, done; - wire jtag_reset_injector, jtag_reset_noc; - wire start_o; - wire done_time_limit; - - assign done_led = done | done_time_limit; - assign noc_reset_led= reset_noc; - assign jtag_reset_led = reset_injector; - - - - // two reset sources which can be controled using jtag. One for reseting NoC another packet injectors - jtag_source_probe #( - .VJTAG_INDEX(DONE_RESET_VJTAG_INDEX), - .Dw(2) //source/probe width in bits - )the_reset( - .probe({done_time_limit,done}), - .source({jtag_reset_injector,jtag_reset_noc}) - ); - - - assign reset_noc = (jtag_reset_noc | reset); - assign reset_injector = (jtag_reset_injector | reset); - - altera_reset_synchronizer noc_rst_sync - ( - .reset_in(reset_noc), - .clk(clk), - .reset_out(reset_noc_sync) - ); - - - altera_reset_synchronizer inject_rst_sync - ( - .reset_in(reset_injector), - .clk(clk), - .reset_out(reset_injector_sync) - ); - - //noc emulator - - noc_emulator #( - .STATISTIC_VJTAG_INDEX(STATISTIC_VJTAG_INDEX), - .PATTERN_VJTAG_INDEX(PATTERN_VJTAG_INDEX), - .NOC_ID(0) - ) - noc_emulate_top - ( - .reset(reset_noc_sync), - .jtag_ctrl_reset(reset_injector_sync), - .clk(clk), - .start_o(start_o), - .done(done) - ); - - - - //clock counter - - function integer log2; + localparam + STATISTIC_VJTAG_INDEX=124, + PATTERN_VJTAG_INDEX=125, + COUNTER_VJTAG_INDEX=126, + DONE_RESET_VJTAG_INDEX=127; + + + + + wire reset_noc, reset_injector, reset_noc_sync, reset_injector_sync, done; + wire jtag_reset_injector, jtag_reset_noc; + wire start_o; + wire done_time_limit; + + assign done_led = done | done_time_limit; + assign noc_reset_led= reset_noc; + assign jtag_reset_led = reset_injector; + + + + // two reset sources which can be controled using jtag. One for reseting NoC another packet injectors + jtag_source_probe #( + .VJTAG_INDEX(DONE_RESET_VJTAG_INDEX), + .Dw(2) //source/probe width in bits + )the_reset( + .probe({done_time_limit,done}), + .source({jtag_reset_injector,jtag_reset_noc}) + ); + + + assign reset_noc = (jtag_reset_noc | reset); + assign reset_injector = (jtag_reset_injector | reset); + + altera_reset_synchronizer noc_rst_sync + ( + .reset_in(reset_noc), + .clk(clk), + .reset_out(reset_noc_sync) + ); + + + altera_reset_synchronizer inject_rst_sync + ( + .reset_in(reset_injector), + .clk(clk), + .reset_out(reset_injector_sync) + ); + + //noc emulator + + noc_emulator #( + .STATISTIC_VJTAG_INDEX(STATISTIC_VJTAG_INDEX), + .PATTERN_VJTAG_INDEX(PATTERN_VJTAG_INDEX), + .NOC_ID(0) + ) + noc_emulate_top + ( + .reset(reset_noc_sync), + .jtag_ctrl_reset(reset_injector_sync), + .clk(clk), + .start_o(start_o), + .done(done) + ); + + + + //clock counter + + function integer log2; input integer number; begin log2=(number <=1) ? 1: 0; while(2**log2= clk_limit); + + localparam MAX_SIM_CLKs = 1_000_000_000; + localparam CLK_CNTw = log2(MAX_SIM_CLKs+1); + + reg [CLK_CNTw-1 : 0] clk_counter; + wire [CLK_CNTw-1 : 0] clk_limit; + reg start; + always @(posedge clk or posedge reset_injector_sync) begin + if(reset_injector_sync)begin + clk_counter <= {CLK_CNTw{1'b0}}; + start<=1'b0; + end else begin + if(start_o) start<=1'b1; + if(done==1'b0 && start ) clk_counter<=clk_counter +1'b1; + end + end + + jtag_source_probe #( + .VJTAG_INDEX(COUNTER_VJTAG_INDEX), + .Dw(CLK_CNTw) //source/probe width in bits + )the_clk_counter( + .probe(clk_counter), + .source(clk_limit) + ); + + assign done_time_limit = (clk_counter >= clk_limit); endmodule "; - return $top_v; + return $top_v; } sub save_the_sof_file{ - my $self=shift; - my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); - my $sofdir="$ENV{PRONOC_WORK}/emulate/sof"; - my $fpga_board=$self->object_get_attribute('compile','board'); - my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; + my $self=shift; + my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); + my $sofdir="$ENV{PRONOC_WORK}/emulate/sof"; + my $fpga_board=$self->object_get_attribute('compile','board'); + my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; - mkpath("$sofdir/$fpga_board/",1,01777); - open(FILE, ">$sofdir/$fpga_board/$name.inf") || die "Can not open: $!"; - print FILE perl_file_header("$name.inf"); - my %pp; - $pp{'noc_param'}= $self->{'noc_param'}; - $pp{'fpga_param'}= $self->{'fpga_param'}; - print FILE Data::Dumper->Dump([\%pp],["emulate_info"]); - close(FILE) || die "Error closing file: $!"; + mkpath("$sofdir/$fpga_board/",1,01777); + open(FILE, ">$sofdir/$fpga_board/$name.inf") || die "Can not open: $!"; + print FILE perl_file_header("$name.inf"); + my %pp; + $pp{'noc_param'}= $self->{'noc_param'}; + $pp{'fpga_param'}= $self->{'fpga_param'}; + print FILE Data::Dumper->Dump([\%pp],["emulate_info"]); + close(FILE) || die "Error closing file: $!"; - #find $dir_name -name \*.sof -exec cp '{}' $sofdir/$fpga_board/$save_name.sof" - my @files = File::Find::Rule->file() + #find $dir_name -name \*.sof -exec cp '{}' $sofdir/$fpga_board/$save_name.sof" + my @files = File::Find::Rule->file() ->name( '*.sof' ) ->in( "$target_dir" ); - copy($files[0],"$sofdir/$fpga_board/$name.sof") or do { - my $err= "Error copy($files[0] , $sofdir/$fpga_board/$name.sof"; - print "$err\n"; - message_dialog($err,'error'); - return; - }; - #copy the board's programming and jtag interface files - - my $board_name=$self->object_get_attribute('compile','board'); - #copy board jtag_intfc.sh file - copy("../boards/Altera/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh"); - #print "../boards/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh\n"; - #add argument run to jtag_interface file - my $runarg=' + copy($files[0],"$sofdir/$fpga_board/$name.sof") or do { + my $err= "Error copy($files[0] , $sofdir/$fpga_board/$name.sof"; + print "$err\n"; + message_dialog($err,'error'); + return; + }; + #copy the board's programming and jtag interface files + + my $board_name=$self->object_get_attribute('compile','board'); + #copy board jtag_intfc.sh file + copy("../boards/Altera/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh"); + #print "../boards/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh\n"; + #add argument run to jtag_interface file + my $runarg=' if [ $# -ne 0 ] then $JTAG_INTFC $1 fi '; - append_text_to_file ("$sofdir/$fpga_board/jtag_intfc.sh",$runarg ); - - - + append_text_to_file ("$sofdir/$fpga_board/jtag_intfc.sh",$runarg ); + + + - #copy board program_device.sh file - copy("../boards/Altera/$board_name/program_device.sh","$sofdir/$fpga_board/program_device.sh"); - - + #copy board program_device.sh file + copy("../boards/Altera/$board_name/program_device.sh","$sofdir/$fpga_board/program_device.sh"); + + - message_dialog("sof file has been generated successfully"); + message_dialog("sof file has been generated successfully"); } ########## -# save_emulation +# save_emulation ########## sub save_emulation { - my ($emulate)=@_; - # read emulation name - my $name=$emulate->object_get_attribute ("emulate_name",undef); - my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; - if ($s == 0){ - message_dialog("Please set emulation name!"); - return 0; - } - # Write object file - open(FILE, ">lib/emulate/$name.EML") || die "Can not open: $!"; - print FILE perl_file_header("$name.EML"); - print FILE Data::Dumper->Dump([\%$emulate],["emulate"]); - close(FILE) || die "Error closing file: $!"; - message_dialog("Emulation saved as lib/emulate/$name.EML!"); - return 1; + my ($emulate)=@_; + # read emulation name + my $name=$emulate->object_get_attribute ("emulate_name",undef); + my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; + if ($s == 0){ + message_dialog("Please set emulation name!"); + return 0; + } + # Write object file + open(FILE, ">lib/emulate/$name.EML") || die "Can not open: $!"; + print FILE perl_file_header("$name.EML"); + print FILE Data::Dumper->Dump([\%$emulate],["emulate"]); + close(FILE) || die "Error closing file: $!"; + message_dialog("Emulation saved as lib/emulate/$name.EML!"); + return 1; } ############# -# load_emulation +# load_emulation ############ sub load_emulation { - my ($emulate,$info)=@_; - my $file; - my $dialog = gen_file_dialog (undef, 'EML'); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/emulate"); - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.EML'){ - - my ($pp,$r,$err) = regen_object($file); - if ($r ){ - add_colored_info($info,"**Error reading $file file: $err\n",'red'); - $dialog->destroy; - return; - } - - clone_obj($emulate,$pp); - #message_dialog("done!"); - } + my ($emulate,$info)=@_; + my $file; + my $dialog = gen_file_dialog (undef, 'EML'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/lib/emulate"); + + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.EML'){ + + my ($pp,$r,$err) = regen_object($file); + if ($r ){ + add_colored_info($info,"**Error reading $file file: $err\n",'red'); + $dialog->destroy; + return; + } + + clone_obj($emulate,$pp); + #message_dialog("done!"); + } } $dialog->destroy; } @@ -1142,81 +1120,81 @@ sub load_emulation { sub update_result { - my ($self,$sample,$name,$x,$y,$z)=@_; - my $ref=$self->object_get_attribute ($sample,$name); - my %results; - %results= %{$ref} if(defined $ref); - if(!defined $z) {$results{$x}=$y;} - else {$results{$x}{$y}=$z;} - $self->object_add_attribute ($sample,$name,\%results); -} + my ($self,$sample,$name,$x,$y,$z)=@_; + my $ref=$self->object_get_attribute ($sample,$name); + my %results; + %results= %{$ref} if(defined $ref); + if(!defined $z) {$results{$x}=$y;} + else {$results{$x}{$y}=$z;} + $self->object_add_attribute ($sample,$name,\%results); +} sub gen_sim_parameter_h { - my ($param_h,$includ_h,$ne,$nr,$router_p,$fifow)=@_; - - $param_h =~ s/\d\'b/ /g; - my $text= " + my ($param_h,$includ_h,$ne,$nr,$router_p,$fifow)=@_; + + $param_h =~ s/\d\'b/ /g; + my $text= " #ifndef INCLUDE_PARAM - #define INCLUDE_PARAM \n \n - - $param_h - - #define NE $ne - #define NR $nr - #define ROUTER_P_NUM $router_p - - extern Vtraffic *traffic[NE]; - extern Vpck_inj *pck_inj[NE]; - extern int reset,clk; - - //simulation parameter - #define MAX_RATIO ".MAX_RATIO." - #define AVG_LATENCY_METRIC \"HEAD_2_TAIL\" - #define TIMSTMP_FIFO_NUM $fifow - - $includ_h + #define INCLUDE_PARAM \n \n + + $param_h + + #define NE $ne + #define NR $nr + #define ROUTER_P_NUM $router_p + + extern Vtraffic *traffic[NE]; + extern Vpck_inj *pck_inj[NE]; + extern int reset,clk; + + //simulation parameter + #define MAX_RATIO ".MAX_RATIO." + #define AVG_LATENCY_METRIC \"HEAD_2_TAIL\" + #define TIMSTMP_FIFO_NUM $fifow + + $includ_h \n \n \#endif" ; - return $text; -} + return $text; +} sub gen_noc_sim_param { - my $simulate=shift; - my $fifow=$simulate->object_get_attribute('fpga_param','TIMSTMP_FIFO_NUM'); - - $fifow= '16' if (!defined $fifow); - - return " - //simulation parameter - //localparam MAX_RATIO = ".MAX_RATIO."; - localparam MAX_PCK_NUM = ".MAX_SIM_CLKs."; - localparam MAX_PCK_SIZ = ".MAX_PCK_SIZ."; - localparam MAX_SIM_CLKs= ".MAX_SIM_CLKs."; - localparam TIMSTMP_FIFO_NUM = $fifow; - "; - + my $simulate=shift; + my $fifow=$simulate->object_get_attribute('fpga_param','TIMSTMP_FIFO_NUM'); + + $fifow= '16' if (!defined $fifow); + + return " + //simulation parameter + //localparam MAX_RATIO = ".MAX_RATIO."; + localparam MAX_PCK_NUM = ".MAX_SIM_CLKs."; + localparam MAX_PCK_SIZ = ".MAX_PCK_SIZ."; + localparam MAX_SIM_CLKs= ".MAX_SIM_CLKs."; + localparam TIMSTMP_FIFO_NUM = $fifow; + "; + } sub gen_noc_localparam_v_file { - my ($self,$dst_path,$sample,$noc_id)=@_; - $noc_id="" if(!defined $noc_id); - # generate NoC parameter file - my ($noc_param,$pass_param)=gen_noc_param_v($self,$sample,$noc_id); - my $header=autogen_warning().get_license_header("noc_localparam.v"); - open(FILE, ">${dst_path}/noc_localparam.v") || die "Can not open: $!"; - my $sim =gen_noc_sim_param($self); - print FILE "$header - - \`ifdef NOC_LOCAL_PARAM \n \n - $noc_param - - $sim - + my ($self,$dst_path,$sample,$noc_id)=@_; + $noc_id="" if(!defined $noc_id); + # generate NoC parameter file + my ($noc_param,$pass_param)=gen_noc_param_v($self,$sample,$noc_id); + my $header=autogen_warning().get_license_header("noc_localparam.v"); + open(FILE, ">${dst_path}/noc_localparam.v") || die "Can not open: $!"; + my $sim =gen_noc_sim_param($self); + print FILE "$header + + \`ifdef NOC_LOCAL_PARAM \n \n + $noc_param + + $sim + \n \n \`endif"; - close FILE; + close FILE; } @@ -1224,126 +1202,126 @@ sub gen_noc_localparam_v_file { # main ############ sub emulator_main{ - - add_color_to_gd(); - my $emulate= emulator->emulator_new(); - set_gui_status($emulate,"ideal",0); - $emulate->object_add_attribute('compile','compilers',"QuartusII"); - my $left_table = def_table (25, 6, FALSE); - my $right_table =def_table (25, 6, FALSE); - my $main_table = def_table (25, 12, FALSE); - my ($infobox,$info)= create_txview(); - - - - my @pages =( - {page_name=>" Avg. throughput/latency", page_num=>0}, - {page_name=>" Injected Packet ", page_num=>1}, - {page_name=>" Worst-Case Delay ",page_num=>2}, - {page_name=>" Execution Time ",page_num=>3}, - ); - - my @charts = ( - { type=>"2D_line", page_num=>0, graph_name=> "Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Latency (clock)', Z_Title=>undef, Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Throughput", result_name => "throughput_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Throughput (flits/clock (%))', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Received", result_name => "packet_rsvd_result", X_Title=>'Core ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Sent", result_name => "packet_sent_result", X_Title=>'Core ID' , Y_Title=>'Sent Packets Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>2, graph_name=> "Received", result_name => "worst_delay_rsvd_result",X_Title=>'Core ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, - { type=>"2D_line", page_num=>3, graph_name=> "-", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Emulation Time (clk)', Z_Title=>undef}, - ); - - my ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate", undef,@charts); - my $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); + + add_color_to_gd(); + my $emulate= emulator->emulator_new(); + set_gui_status($emulate,"ideal",0); + $emulate->object_add_attribute('compile','compilers',"QuartusII"); + my $left_table = def_table (25, 6, FALSE); + my $right_table =def_table (25, 6, FALSE); + my $main_table = def_table (25, 12, FALSE); + my ($infobox,$info)= create_txview(); + + + + my @pages =( + {page_name=>" Avg. throughput/latency", page_num=>0}, + {page_name=>" Injected Packet ", page_num=>1}, + {page_name=>" Worst-Case Delay ",page_num=>2}, + {page_name=>" Execution Time ",page_num=>3}, + ); + + my @charts = ( + { type=>"2D_line", page_num=>0, graph_name=> "Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Latency (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Throughput", result_name => "throughput_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Throughput (flits/clock (%))', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Received", result_name => "packet_rsvd_result", X_Title=>'Core ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Sent", result_name => "packet_sent_result", X_Title=>'Core ID' , Y_Title=>'Sent Packets Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>2, graph_name=> "Received", result_name => "worst_delay_rsvd_result",X_Title=>'Core ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, + { type=>"2D_line", page_num=>3, graph_name=> "-", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Emulation Time (clk)', Z_Title=>undef}, + ); + + my ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate", undef,@charts); + my $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); - $main_table->set_row_spacings (4); - $main_table->set_col_spacings (1); - - my $generate = def_image_button('icons/forward.png','Run all'); - my $open = def_image_button('icons/browse.png','Load'); - my $diagram = def_image_button('icons/diagram.png','Diagram'); - - my ($entrybox,$entry) = def_h_labeled_entry('Save as:',undef); - - $entry->signal_connect( 'changed'=> sub{ - my $name=$entry->get_text(); - $emulate->object_add_attribute ("emulate_name",undef,$name); - }); - my $save = def_image_button('icons/save.png','Save'); - $entrybox->pack_end($save, FALSE, FALSE,0); - - my $image = get_status_gif($emulate); - my $v1=gen_vpaned($conf_box,.45,$image); - my $v2=gen_vpaned($infobox,.2,$chart); - my $h1=gen_hpaned($v1,.4,$v2); - - #$table->attach_defaults ($event_box, $col, $col+1, $row, $row+1); - $main_table->attach_defaults ($h1 , 0, 12, 0,24); - $main_table->attach ($open,0, 2, 24,25,'expand','shrink',2,2); -# $main_table->attach ($diagram, 2, 4, 24,25,'expand','shrink',2,2); - $main_table->attach ($entrybox,4, 7, 24,25,'expand','shrink',2,2); - $main_table->attach ($generate, 7, 9, 24,25,'expand','shrink',2,2); - - #check soc status every 0.5 second. referesh device table if there is any changes - Glib::Timeout->add (100, sub{ - my ($state,$timeout)= get_gui_status($emulate); - - if ($timeout>0){ - $timeout--; - set_gui_status($emulate,$state,$timeout); - return TRUE; - } - if($state eq "ideal"){ - return TRUE; - - } - - - #refresh GUI - my $name=$emulate->object_get_attribute ("emulate_name",undef); - $entry->set_text($name) if(defined $name); - $conf_box->destroy(); - $chart->destroy(); - $image->destroy(); - $image = get_status_gif($emulate); - ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate",$set_win, @charts); - $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); - $v1 -> pack1($conf_box, TRUE, TRUE); - $v1 -> pack2($image, TRUE, TRUE); - $v2 -> pack2($chart, TRUE, TRUE); - $conf_box->show_all(); - $main_table->show_all(); - set_gui_status($emulate,"ideal",0); - - return TRUE; - - } ); - - $diagram-> signal_connect("clicked" => sub{ + $main_table->set_row_spacings (4); + $main_table->set_col_spacings (1); + + my $generate = def_image_button('icons/forward.png','Run all'); + my $open = def_image_button('icons/browse.png','Load'); + my $diagram = def_image_button('icons/diagram.png','Diagram'); + + my ($entrybox,$entry) = def_h_labeled_entry('Save as:',undef); + + $entry->signal_connect( 'changed'=> sub{ + my $name=$entry->get_text(); + $emulate->object_add_attribute ("emulate_name",undef,$name); + }); + my $save = def_image_button('icons/save.png','Save'); + $entrybox->pack_end($save, FALSE, FALSE,0); + + my $image = get_status_gif($emulate); + my $v1=gen_vpaned($conf_box,.45,$image); + my $v2=gen_vpaned($infobox,.2,$chart); + my $h1=gen_hpaned($v1,.4,$v2); + + #$table->attach_defaults ($event_box, $col, $col+1, $row, $row+1); + $main_table->attach_defaults ($h1 , 0, 12, 0,24); + $main_table->attach ($open,0, 2, 24,25,'expand','shrink',2,2); +# $main_table->attach ($diagram, 2, 4, 24,25,'expand','shrink',2,2); + $main_table->attach ($entrybox,4, 7, 24,25,'expand','shrink',2,2); + $main_table->attach ($generate, 7, 9, 24,25,'expand','shrink',2,2); + + #check soc status every 0.5 second. referesh device table if there is any changes + Glib::Timeout->add (100, sub{ + my ($state,$timeout)= get_gui_status($emulate); + + if ($timeout>0){ + $timeout--; + set_gui_status($emulate,$state,$timeout); + return TRUE; + } + if($state eq "ideal"){ + return TRUE; + + } + + + #refresh GUI + my $name=$emulate->object_get_attribute ("emulate_name",undef); + $entry->set_text($name) if(defined $name); + $conf_box->destroy(); + $chart->destroy(); + $image->destroy(); + $image = get_status_gif($emulate); + ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate",$set_win, @charts); + $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); + $v1 -> pack1($conf_box, TRUE, TRUE); + $v1 -> pack2($image, TRUE, TRUE); + $v2 -> pack2($chart, TRUE, TRUE); + $conf_box->show_all(); + $main_table->show_all(); + set_gui_status($emulate,"ideal",0); + + return TRUE; + + } ); + + $diagram-> signal_connect("clicked" => sub{ show_topology_diagram ($emulate); - }); - - $generate-> signal_connect("clicked" => sub{ - my @samples =$emulate->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - $emulate->object_add_attribute ($sample,"status","run"); - } - run_emulator($emulate,$info); - }); - - - $open-> signal_connect("clicked" => sub{ - load_emulation($emulate,$info); - set_gui_status($emulate,"ref",5); - }); - - $save-> signal_connect("clicked" => sub{ - save_emulation($emulate); - set_gui_status($emulate,"ref",5); - }); - - - - return add_widget_to_scrolled_win($main_table); + }); + + $generate-> signal_connect("clicked" => sub{ + my @samples =$emulate->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + $emulate->object_add_attribute ($sample,"status","run"); + } + run_emulator($emulate,$info); + }); + + + $open-> signal_connect("clicked" => sub{ + load_emulation($emulate,$info); + set_gui_status($emulate,"ref",5); + }); + + $save-> signal_connect("clicked" => sub{ + save_emulation($emulate); + set_gui_status($emulate,"ref",5); + }); + + + + return add_widget_to_scrolled_win($main_table); } diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index 3aae2bd..6d02704 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -1091,7 +1091,7 @@ sub noc_config{ my $hetero_en=$mpsoc->object_get_attribute($noc_param,'HETERO_VC'); $label='Heterogeneous VC setting'; $param='int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]'; - $default='\'{0}'; + $default='\'{\'{0}}'; $content='0,1,2'; $type='Combo-box'; $info='Defines how a heterogeneous number of VCs are distributed in the NoC. diff --git a/mpsoc/perl_gui/lib/perl/simulator.pl b/mpsoc/perl_gui/lib/perl/simulator.pl index 8493282..acf1de6 100755 --- a/mpsoc/perl_gui/lib/perl/simulator.pl +++ b/mpsoc/perl_gui/lib/perl/simulator.pl @@ -5,8 +5,6 @@ use FindBin; use lib $FindBin::Bin; - - use GD::Graph::Data; use emulator; use GD::Graph::colour qw/:colours/; @@ -23,310 +21,243 @@ require "readme_gen.pl"; require "graph.pl"; - use List::MoreUtils qw(uniq); - - - sub generate_sim_bin_file { - my ($simulate,$info_text) =@_; - #check simulator envirement - my $simulator =$simulate->object_get_attribute("Simulator"); - #TODO generate .sim file only for modelsim simulator - - $simulate->object_add_attribute('status',undef,'run'); - set_gui_status($simulate,"ref",1); - - my ($nr,$ne,$router_p,$ref_tops,$includ_h)= get_noc_verilator_top_modules_info($simulate); - my %tops = %{$ref_tops}; - - $tops{Vtraffic} = "--top-module traffic_gen_top"; - $tops{Vpck_inj} = "--top-module packet_injector_verilator"; - my $target_dir= "$ENV{PRONOC_WORK}/simulate"; - - - my $project_dir = get_project_dir()."/mpsoc/"; - my $src_verilator_dir="$project_dir/src_verilator"; - my $src_c="$project_dir/src_c"; - my $src_noc_dir="$project_dir/rtl/src_noc"; - my $script_dir="$project_dir/script"; - my $testbench_file= "$src_verilator_dir/simulator.cpp"; - - my $target_verilog_dr ="$target_dir/src_verilog"; - my $obj_dir ="$target_dir/verilator/obj_dir/"; - - rmtree("$target_dir/verilator"); - rmtree("$target_verilog_dr"); - mkpath("$target_verilog_dr/",1,01777); - - #copy src_verilator files - my @files_list = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$src_verilator_dir" ); - - #make sure source files have key word 'module' - my @files; - foreach my $p (@files_list){ - push (@files,$p) if(check_file_has_string($p,'module')); - } - push (@files,$src_noc_dir); - push (@files,"$project_dir/rtl/arbiter.v"); - push (@files,"$project_dir/rtl/main_comp.v"); - push (@files,"$project_dir/rtl/pronoc_def.v"); - - - #my @files=( - # $src_noc_dir, - # "$src_verilator_dir/noc_connection.sv", - # "$src_verilator_dir/mesh_torus_noc_connection.sv", - # "$src_verilator_dir/router_verilator.v", - # "$src_verilator_dir/traffic_gen_verilator.v" - #); - - copy_file_and_folders (\@files,$project_dir,$target_verilog_dr); - copy_file_and_folders (\@files,$project_dir,"$target_dir/modelsim/src_verilog/"); - - my $target_modelsim_dr ="$target_dir/modelsim/src_modelsim"; - my $src_modelsim_dir="$project_dir/rtl/src_modelsim"; - rmtree("$target_modelsim_dr"); - mkpath("$target_modelsim_dr/",1,01777); - - #copy src_verilator files - @files_list = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$src_modelsim_dir" ); - - #make sure source files have key word 'module' - @files=(); - foreach my $p (@files_list){ - push (@files,$p) if(check_file_has_string($p,'module')); - } - copy_file_and_folders (\@files,$project_dir,$target_modelsim_dr); - - - - - #check if we have a custom topology - my $topology=$simulate->object_get_attribute('noc_param','TOPOLOGY'); - if ($topology eq '"CUSTOM"'){ - my $name=$simulate->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); - $name=~s/["]//gs; - my $dir1= get_project_dir()."/mpsoc/rtl/src_topology/$name"; - my $dir2= get_project_dir()."/mpsoc/rtl/src_topology/common"; - my @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$dir1" ); - copy_file_and_folders (\@files,$project_dir,$target_verilog_dr); - copy_file_and_folders (\@files,$project_dir,"$target_dir/modelsim/src_verilog/"); - - @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$dir2" ); - - copy_file_and_folders (\@files,$project_dir,$target_verilog_dr); - copy_file_and_folders (\@files,$project_dir,"$target_dir/modelsim/src_verilog/"); - - - - } - # generate NoC parameter file - my $fifow=$simulate->object_get_attribute('fpga_param','TIMSTMP_FIFO_NUM'); - gen_noc_localparam_v_file($simulate,"$target_verilog_dr/src_noc"); - - #generate routers with different port num - my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); - my $result = verilator_compilation (\%tops,$target_dir,$info_text,$cpu_num); - - - if ($result){ - add_colored_info($info_text,"Veriator model has been generated successfully!\n",'blue'); - }else { - add_colored_info($info_text,"Verilator compilation failed!\n","red"); - $simulate->object_add_attribute('status',undef,'programmer_failed'); - set_gui_status($simulate,"ref",1); - print "gen-ended!\n"; - return; - } - - my $r; - #copy nettrace synful - dircopy("$src_c/netrace-1.0","$obj_dir/netrace-1.0") or $r=$!; - dircopy("$src_c/synfull","$obj_dir/synful") or $r=$!; - add_colored_info($info_text,"ERROR: $r\n","red") if(defined $r ) ; - - - #copy simulation c header files - @files = File::Find::Rule->file() - ->name( '*.h') - ->in( "$src_verilator_dir" ); - - copy_file_and_folders (\@files,$project_dir,$obj_dir); - copy($testbench_file,"$obj_dir/testbench.cpp"); - - - - #compile the testbench - my $param_h=gen_noc_param_h($simulate); - my $text = gen_sim_parameter_h($param_h,$includ_h,$ne,$nr,$router_p,$fifow); - - - open(FILE, ">$obj_dir/parameter.h") || die "Can not open: $!"; - print FILE "$text"; - - close FILE; - - - - #$result = run_make_file("$obj_dir/",$info_text,'lib'); - my $lib_num=0; - add_colored_info($info_text,"Makefie will use the maximum number of $cpu_num core(s) in parallel for compilation\n",'green'); - my $length=scalar (keys %tops); - my $cmd=""; - foreach my $top (sort keys %tops) { - $cmd.= "lib$lib_num & "; - $lib_num++; - if( $lib_num % $cpu_num == 0 || $lib_num == $length){ - $cmd.="wait\n"; - $result = run_make_file("$obj_dir/",$info_text,$cmd); - if ($result ==0){ - $simulate->object_add_attribute('status',undef,'programmer_failed'); - set_gui_status($simulate,"ref",1); - print "gen-ended!\n"; - return; - } - $cmd=""; - }else { - $cmd.=" make "; - } - } - - - - - run_make_file("$obj_dir/",$info_text); - if ($result ==0){ - $simulate->object_add_attribute('status',undef,'programmer_failed'); - set_gui_status($simulate,"ref",1); - print "gen-ended!\n"; - return; - } - - - - - #my $end = localtime; - - - - #save the binarry file - my $bin= "$obj_dir/testbench"; - my $path=$simulate->object_get_attribute ('sim_param',"BIN_DIR"); - my $name=$simulate->object_get_attribute ('sim_param',"SAVE_NAME"); - - #create project directory if it does not exist - my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("mkdir -p $path" ); - if($exit != 0 ){ print "$stdout\n"; print "gen-ended!\n"; message_dialog($stdout,'error'); return;} - - - - #check if the verilation was successful - if ((-e $bin)==0) {#something goes wrong - #message_dialog("Verilator compilation was unsuccessful please check the $path/$name.log files for more information",'error'); - add_colored_info($info_text,"Verilator compilation failed!\n","red"); - $simulate->object_add_attribute('status',undef,'programmer_failed'); - set_gui_status($simulate,"ref",1); - print "gen-ended!\n"; - return; - } - - - #copy ($bin,"$path/$name") or die "Can not copy: $!"; - ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("cp -f $bin $path/$name"); - if($exit != 0 ){ print "$stdout\n"; print "gen-ended!\n"; message_dialog($stdout,'error'); return;} - - #save noc info - open(FILE, ">$path/$name.inf") || die "Can not open: $!"; - print FILE perl_file_header("$name.inf"); - my %pp; - $pp{'noc_param'}= $simulate->{'noc_param'}; - $pp{'sim_param'}= $simulate->{'sim_param'}; - print FILE Data::Dumper->Dump([\%pp],["emulate_info"]); - close(FILE) || die "Error closing file: $!"; - - print "gen-ended successfully!\n"; - message_dialog("The simulation binary file has been successfully generated in $path!"); - - $simulate->object_add_attribute('status',undef,'ideal'); - set_gui_status($simulate,"ref",1); - - #make project dir - #my $dir= $simulate->object_get_attribute ("sim_param","BIN_DIR"); - #my $name=$simulate->object_get_attribute ("sim_param","SAVE_NAME"); - #my $path= "$dir/$name"; - #add_info($info_text, "$src_verilator_dir!\n"); - #mkpath("$path",1,01777); + my ($simulate,$info_text) =@_; + #check simulator envirement + my $simulator =$simulate->object_get_attribute("Simulator"); + $simulate->object_add_attribute('status',undef,'run'); + set_gui_status($simulate,"ref",1); + my ($nr,$ne,$router_p,$ref_tops,$includ_h)= get_noc_verilator_top_modules_info($simulate); + my %tops = %{$ref_tops}; + + $tops{Vtraffic} = "--top-module traffic_gen_top"; + $tops{Vpck_inj} = "--top-module packet_injector_verilator"; + my $target_dir= "$ENV{PRONOC_WORK}/simulate"; + + my $project_dir = get_project_dir()."/mpsoc/"; + my $src_verilator_dir="$project_dir/src_verilator"; + my $src_c="$project_dir/src_c"; + my $src_noc_dir="$project_dir/rtl/src_noc"; + my $script_dir="$project_dir/script"; + my $testbench_file= "$src_verilator_dir/simulator.cpp"; + my $target_verilog_dr ="$target_dir/src_verilog"; + my $obj_dir ="$target_dir/verilator/obj_dir/"; + + rmtree("$target_dir/verilator") if($simulate eq 'Verilator'); + rmtree("$target_verilog_dr"); + mkpath("$target_verilog_dr/",1,01777); + + #copy src_verilator files + my @files_list = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$src_verilator_dir" ); + #make sure source files have key word 'module' + my @files; + foreach my $p (@files_list){ + push (@files,$p) if(check_file_has_string($p,'module')); + } + push (@files,$src_noc_dir); + push (@files,"$project_dir/rtl/arbiter.v"); + push (@files,"$project_dir/rtl/main_comp.v"); + push (@files,"$project_dir/rtl/pronoc_def.v"); + + copy_file_and_folders (\@files,$project_dir,$target_verilog_dr); + copy_file_and_folders (\@files,$project_dir,"$target_dir/modelsim/src_verilog/"); + my $target_modelsim_dr ="$target_dir/modelsim/src_modelsim"; + my $src_modelsim_dir="$project_dir/rtl/src_modelsim"; + if($simulator ne 'Verilator'){ + rmtree("$target_modelsim_dr"); + mkpath("$target_modelsim_dr/",1,01777); + #copy src_verilator files + @files_list = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$src_modelsim_dir" ); + #make sure source files have key word 'module' + @files=(); + foreach my $p (@files_list){ + push (@files,$p) if(check_file_has_string($p,'module')); + } + copy_file_and_folders (\@files,$project_dir,$target_modelsim_dr); + } + + #check if we have a custom topology + my $topology=$simulate->object_get_attribute('noc_param','TOPOLOGY'); + if ($topology eq '"CUSTOM"'){ + my $name=$simulate->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); + $name=~s/["]//gs; + my $dir1= get_project_dir()."/mpsoc/rtl/src_topology/$name"; + my $dir2= get_project_dir()."/mpsoc/rtl/src_topology/common"; + my @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$dir1" ); + copy_file_and_folders (\@files,$project_dir,$target_verilog_dr); + copy_file_and_folders (\@files,$project_dir,"$target_dir/modelsim/src_verilog/") if($simulator ne 'Verilator'); + + @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$dir2" ); + copy_file_and_folders (\@files,$project_dir,$target_verilog_dr); + copy_file_and_folders (\@files,$project_dir,"$target_dir/modelsim/src_verilog/")if($simulator ne 'Verilator'); + } + # generate NoC parameter file + my $fifow=$simulate->object_get_attribute('fpga_param','TIMSTMP_FIFO_NUM'); + gen_noc_localparam_v_file($simulate,"$target_verilog_dr/src_noc"); + my $path=$simulate->object_get_attribute ('sim_param',"BIN_DIR"); + my $name=$simulate->object_get_attribute ('sim_param',"SAVE_NAME"); + + if($simulator eq 'Verilator'){ + #generate routers with different port num + my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); + my $result = verilator_compilation (\%tops,$target_dir,$info_text,$cpu_num); + + if ($result){ + add_colored_info($info_text,"Veriator model has been generated successfully!\n",'blue'); + }else { + add_colored_info($info_text,"Verilator compilation failed!\n","red"); + $simulate->object_add_attribute('status',undef,'programmer_failed'); + set_gui_status($simulate,"ref",1); + print "gen-ended!\n"; + return; + } + + my $r; + #copy nettrace synful + dircopy("$src_c/netrace-1.0","$obj_dir/netrace-1.0") or $r=$!; + dircopy("$src_c/synfull","$obj_dir/synful") or $r=$!; + add_colored_info($info_text,"ERROR: $r\n","red") if(defined $r ) ; + + #copy simulation c header files + @files = File::Find::Rule->file() + ->name( '*.h') + ->in( "$src_verilator_dir" ); + + copy_file_and_folders (\@files,$project_dir,$obj_dir); + copy($testbench_file,"$obj_dir/testbench.cpp"); + + #compile the testbench + my $param_h=gen_noc_param_h($simulate); + my $text = gen_sim_parameter_h($param_h,$includ_h,$ne,$nr,$router_p,$fifow); + open(FILE, ">$obj_dir/parameter.h") || die "Can not open: $!"; + print FILE "$text"; + close FILE; + + #$result = run_make_file("$obj_dir/",$info_text,'lib'); + my $lib_num=0; + add_colored_info($info_text,"Makefie will use the maximum number of $cpu_num core(s) in parallel for compilation\n",'green'); + my $length=scalar (keys %tops); + my $cmd=""; + foreach my $top (sort keys %tops) { + $cmd.= "lib$lib_num & "; + $lib_num++; + if( $lib_num % $cpu_num == 0 || $lib_num == $length){ + $cmd.="wait\n"; + $result = run_make_file("$obj_dir/",$info_text,$cmd); + if ($result ==0){ + $simulate->object_add_attribute('status',undef,'programmer_failed'); + set_gui_status($simulate,"ref",1); + return; + } + $cmd=""; + }else { + $cmd.=" make "; + } + } + + run_make_file("$obj_dir/",$info_text); + if ($result ==0){ + $simulate->object_add_attribute('status',undef,'programmer_failed'); + set_gui_status($simulate,"ref",1); + return; + } + #my $end = localtime; + #save the binarry file + my $bin= "$obj_dir/testbench"; + + #create project directory if it does not exist + my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("mkdir -p $path" ); + if($exit != 0 ){ print "$stdout\n"; print "gen-ended!\n"; message_dialog($stdout,'error'); return;} + + #check if the verilation was successful + if ((-e $bin)==0) {#something goes wrong + #message_dialog("Verilator compilation was unsuccessful please check the $path/$name.log files for more information",'error'); + add_colored_info($info_text,"Verilator compilation failed!\n","red"); + $simulate->object_add_attribute('status',undef,'programmer_failed'); + set_gui_status($simulate,"ref",1); + return; + } + #copy ($bin,"$path/$name") or die "Can not copy: $!"; + ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("cp -f $bin $path/$name"); + if($exit != 0 ){ print "$stdout\n"; message_dialog($stdout,'error'); return;} + } + #save noc info + open(FILE, ">$path/$name.inf") || die "Can not open: $!"; + print FILE perl_file_header("$name.inf"); + my %pp; + $pp{'noc_param'}= $simulate->{'noc_param'}; + $pp{'sim_param'}= $simulate->{'sim_param'}; + print FILE Data::Dumper->Dump([\%pp],["emulate_info"]); + close(FILE) || die "Error closing file: $!"; + message_dialog("The simulation binary file has been successfully generated in $path!"); + $simulate->object_add_attribute('status',undef,'ideal'); + set_gui_status($simulate,"ref",1); } - - - - - ########## -# save_simulation +# save_simulation ########## sub save_simulation { - my ($simulate)=@_; - # read emulation name - my $name=$simulate->object_get_attribute ("simulate_name",undef); - my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; - if ($s == 0){ - message_dialog("Please set Simulation name!"); - return 0; - } - # Write object file - open(FILE, ">lib/simulate/$name.SIM") || die "Can not open: $!"; - print FILE perl_file_header("$name.SIM"); - print FILE Data::Dumper->Dump([\%$simulate],["simulate"]); - close(FILE) || die "Error closing file: $!"; - message_dialog("Simulation has saved as lib/simulate/$name.SIM!"); - return 1; + my ($simulate)=@_; + # read emulation name + my $name=$simulate->object_get_attribute ("simulate_name",undef); + my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; + if ($s == 0){ + message_dialog("Please set Simulation name!"); + return 0; + } + # Write object file + open(FILE, ">lib/simulate/$name.SIM") || die "Can not open: $!"; + print FILE perl_file_header("$name.SIM"); + print FILE Data::Dumper->Dump([\%$simulate],["simulate"]); + close(FILE) || die "Error closing file: $!"; + message_dialog("Simulation has saved as lib/simulate/$name.SIM!"); + return 1; } ############# -# load_simulation +# load_simulation ############ sub load_simulation { - my ($simulate,$info)=@_; - my $file; - my $dialog = gen_file_dialog (undef, 'SIM'); - - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/simulate"); - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.SIM'){ - my ($pp,$r,$err) = regen_object($file); - if ($r){ - add_colored_info($info,"**Error reading $file file: $err\n",'red'); - $dialog->destroy; - return; - } - #deactivate running simulations - $pp->object_add_attribute('status',undef,'ideal'); - my @samples =$pp->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - my $st=$pp->object_get_attribute ($sample,"status"); - $pp->object_add_attribute ($sample,"status",'done');# if ($st eq "run"); - } - clone_obj($simulate,$pp); - #message_dialog("done!"); - } + my ($simulate,$info)=@_; + my $file; + my $dialog = gen_file_dialog (undef, 'SIM'); + + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/lib/simulate"); + + + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.SIM'){ + my ($pp,$r,$err) = regen_object($file); + if ($r){ + add_colored_info($info,"**Error reading $file file: $err\n",'red'); + $dialog->destroy; + return; + } + #deactivate running simulations + $pp->object_add_attribute('status',undef,'ideal'); + my @samples =$pp->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + my $st=$pp->object_get_attribute ($sample,"status"); + $pp->object_add_attribute ($sample,"status",'done');# if ($st eq "run"); + } + clone_obj($simulate,$pp); + #message_dialog("done!"); + } } $dialog->destroy; } @@ -335,165 +266,165 @@ sub load_simulation { sub check_hotspot_parameters{ - my ($self,$sample)=@_; - my $num=$self->object_get_attribute($sample,"HOTSPOT_NUM"); - my $result; - if (defined $num){ - my @hotspots; - my $acuum=0; - for (my $i=0;$i<$num;$i++){ - my $w1 = $self->object_get_attribute($sample,"HOTSPOT_CORE_$i"); - if( grep (/^\Q$w1\E$/,@hotspots)){ - $result="Error: Tile $w1 has been selected for Two or more than two hotspot nodes.\n"; - } - push( @hotspots,$w1); - my $w2 = $self->object_get_attribute($sample,"HOTSPOT_PERCENT_$i"); - $acuum+=$w2; - - } - if ($acuum > 100){ - $result="Error: The traffic summation of all hotspot nodes is $acuum. The hotspot summation must be <=100"; - - } - } - return $result; + my ($self,$sample)=@_; + my $num=$self->object_get_attribute($sample,"HOTSPOT_NUM"); + my $result; + if (defined $num){ + my @hotspots; + my $acuum=0; + for (my $i=0;$i<$num;$i++){ + my $w1 = $self->object_get_attribute($sample,"HOTSPOT_CORE_$i"); + if( grep (/^\Q$w1\E$/,@hotspots)){ + $result="Error: Tile $w1 has been selected for Two or more than two hotspot nodes.\n"; + } + push( @hotspots,$w1); + my $w2 = $self->object_get_attribute($sample,"HOTSPOT_PERCENT_$i"); + $acuum+=$w2; + + } + if ($acuum > 100){ + $result="Error: The traffic summation of all hotspot nodes is $acuum. The hotspot summation must be <=100"; + + } + } + return $result; } sub get_district_avg { - my ($self,$sample)=@_; - my $vt=$self->object_get_attribute($sample,"DISCRETE_RANGE"); - $vt = "2,3,4,5" unless (defined $vt); - my $pt=$self->object_get_attribute($sample,"PROBEB_RANGE"); - $pt= "25,25,25,25" unless (defined $pt); - - my $avg=0; - my @valus = split(',',$vt); - my @probs = split(',',$pt); - my $i=0; - my $sum=0; - my $min=10000000; - my $max=0; - foreach my $v (@valus) { - return ("-","The $v is not numeric value") unless (is_integer($v)); - $sum+= $probs[$i]; - $avg+=$v*$probs[$i]; - $i++; - $min=$v if($min>$v); - $max=$v if($max<$v); - } - return ("-","The summation of probebilities are $sum which is not equal 100.") if($sum!=100); - $avg/=100; - - $self->object_add_attribute ($sample,"MIN_PCK_SIZE",$min); - $self->object_add_attribute ($sample,"MAX_PCK_SIZE",$max); - return ($avg,undef); + my ($self,$sample)=@_; + my $vt=$self->object_get_attribute($sample,"DISCRETE_RANGE"); + $vt = "2,3,4,5" unless (defined $vt); + my $pt=$self->object_get_attribute($sample,"PROBEB_RANGE"); + $pt= "25,25,25,25" unless (defined $pt); + + my $avg=0; + my @valus = split(',',$vt); + my @probs = split(',',$pt); + my $i=0; + my $sum=0; + my $min=10000000; + my $max=0; + foreach my $v (@valus) { + return ("-","The $v is not numeric value") unless (is_integer($v)); + $sum+= $probs[$i]; + $avg+=$v*$probs[$i]; + $i++; + $min=$v if($min>$v); + $max=$v if($max<$v); + } + return ("-","The summation of probebilities are $sum which is not equal 100.") if($sum!=100); + $avg/=100; + + $self->object_add_attribute ($sample,"MIN_PCK_SIZE",$min); + $self->object_add_attribute ($sample,"MAX_PCK_SIZE",$max); + return ($avg,undef); } sub get_simulator_noc_configuration{ - my ($self,$mode,$sample,$set_win) =@_; - - my $table=def_table(10,2,FALSE); - my $row=0; - - - my $scrolled_win = add_widget_to_scrolled_win ($table,gen_scr_win_with_adjst($self,'noc_conf_scr_win')); - - my $ok = def_image_button('icons/select.png','_OK',FALSE,1); - my $import = def_image_button('icons/import.png','I_mport',FALSE,1); - my $save = def_image_button('icons/save.png','_Export',FALSE,1); - - $save ->signal_connect("clicked"=> sub{ - my $dialog=save_file_dialog ("Enter configuration file name",'conf'); - #$dialog->set_current_folder ($open_in) if(defined $open_in); - if ( "ok" eq $dialog->run ) { - my $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - my $t=$self->object_get_attribute($sample); - open(FILE, ">$path/${name}.conf") || die "Can not open: $!"; - print FILE Data::Dumper->Dump([\$t],['config']); - close FILE; - } - $dialog->destroy(); - }); - - $import ->signal_connect("clicked"=> sub{ - my $dialog=save_file_dialog ("Enter configuration file name",'conf'); - #$dialog->set_current_folder ($open_in) if(defined $open_in); - if ( "ok" eq $dialog->run ) { - my $file = $dialog->get_filename; - my $pp= do $file ; - my $status=1; - $status=0 if $@; - message_dialog("Error reading: $@") if $@; - if ($status==1){ - $self->object_add_attribute ("$sample",undef,$$pp); - set_gui_status($self,'ref_set_win',1); - } - } - $dialog->destroy(); - }); - - - - my $mtable = def_table(10, 3, TRUE); - - $mtable->attach_defaults($scrolled_win,0,3,0,9); - $mtable-> attach ($ok , 1, 2, 9, 10,'expand','shrink',2,2); - $mtable-> attach ($import , 0, 1, 9, 10,'expand','shrink',2,2); - $mtable-> attach ($save , 2, 3, 9, 10,'expand','shrink',2,2); - - - - $set_win ->signal_connect (destroy => sub{ - $self->object_add_attribute("active_setting",undef,undef); - - }); - - - my $dir = Cwd::getcwd(); - my $open_in = abs_path("$ENV{PRONOC_WORK}/simulate"); - - - attach_widget_to_table ($table,$row,gen_label_in_left(" Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), - get_dir_in_object ($self,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; - - $open_in = $self->object_get_attribute($sample,"sof_path"); - - - - my @files = glob "$open_in/*"; - my $exe_files=""; - foreach my $file (@files){ - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.inf'){ - $exe_files="$exe_files,$name"; - } - } - my $model_obj = gen_combobox_object ($self,$sample, "sof_file", $exe_files, undef,'ref_set_win',1); - attach_widget_to_table ($table,$row,gen_label_in_left(" Verilated Model:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), - $model_obj); $row++; + my ($self,$mode,$sample,$set_win) =@_; + + my $table=def_table(10,2,FALSE); + my $row=0; + + + my $scrolled_win = add_widget_to_scrolled_win ($table,gen_scr_win_with_adjst($self,'noc_conf_scr_win')); + + my $ok = def_image_button('icons/select.png','_OK',FALSE,1); + my $import = def_image_button('icons/import.png','I_mport',FALSE,1); + my $save = def_image_button('icons/save.png','_Export',FALSE,1); + + $save ->signal_connect("clicked"=> sub{ + my $dialog=save_file_dialog ("Enter configuration file name",'conf'); + #$dialog->set_current_folder ($open_in) if(defined $open_in); + if ( "ok" eq $dialog->run ) { + my $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + my $t=$self->object_get_attribute($sample); + open(FILE, ">$path/${name}.conf") || die "Can not open: $!"; + print FILE Data::Dumper->Dump([\$t],['config']); + close FILE; + } + $dialog->destroy(); + }); + + $import ->signal_connect("clicked"=> sub{ + my $dialog=save_file_dialog ("Enter configuration file name",'conf'); + #$dialog->set_current_folder ($open_in) if(defined $open_in); + if ( "ok" eq $dialog->run ) { + my $file = $dialog->get_filename; + my $pp= do $file ; + my $status=1; + $status=0 if $@; + message_dialog("Error reading: $@") if $@; + if ($status==1){ + $self->object_add_attribute ("$sample",undef,$$pp); + set_gui_status($self,'ref_set_win',1); + } + } + $dialog->destroy(); + }); + + + + my $mtable = def_table(10, 3, TRUE); + + $mtable->attach_defaults($scrolled_win,0,3,0,9); + $mtable-> attach ($ok , 1, 2, 9, 10,'expand','shrink',2,2); + $mtable-> attach ($import , 0, 1, 9, 10,'expand','shrink',2,2); + $mtable-> attach ($save , 2, 3, 9, 10,'expand','shrink',2,2); + + + + $set_win ->signal_connect (destroy => sub{ + $self->object_add_attribute("active_setting",undef,undef); + + }); + + + my $dir = Cwd::getcwd(); + my $open_in = abs_path("$ENV{PRONOC_WORK}/simulate"); + + + attach_widget_to_table ($table,$row,gen_label_in_left(" Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), + get_dir_in_object ($self,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; + + $open_in = $self->object_get_attribute($sample,"sof_path"); + + + + my @files = glob "$open_in/*"; + my $exe_files=""; + foreach my $file (@files){ + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.inf'){ + $exe_files="$exe_files,$name"; + } + } + my $model_obj = gen_combobox_object ($self,$sample, "sof_file", $exe_files, undef,'ref_set_win',1); + attach_widget_to_table ($table,$row,gen_label_in_left(" Verilated Model:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), + $model_obj); $row++; my $cast_type= '"UNICAST"'; #get simulation parameters here - my $s=$self->object_get_attribute($sample,"sof_file"); - if (defined $s){ - my ($infobox,$info)= create_txview(); - my $sof=get_sim_bin_path($self,$sample,$info); - my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); - my $sof_info= "$path$name.inf"; - - my $pp= do $sof_info ; - my $p=$pp->{'noc_param'}; - $cast_type = $p->{'CAST_TYPE'}; - $cast_type= '"UNICAST"' if (!defined $cast_type); - } + my $s=$self->object_get_attribute($sample,"sof_file"); + if (defined $s){ + my ($infobox,$info)= create_txview(); + my $sof=get_sim_bin_path($self,$sample,$info); + my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); + my $sof_info= "$path$name.inf"; + + my $pp= do $sof_info ; + my $p=$pp->{'noc_param'}; + $cast_type = $p->{'CAST_TYPE'}; + $cast_type= '"UNICAST"' if (!defined $cast_type); + } my $trf_info = "Select of the following traffic models: 1- Synthetic 2- Task-graph : The task graph traffic pattern can be generated - using ProNoC trace generator + using ProNoC trace generator 3- Netrace: Dependency-Tracking Trace-Based Network-on-Chip Simulation. For downloading the trace files and more @@ -516,715 +447,714 @@ sub get_simulator_noc_configuration{ my $max_sim_clk = get_MAX_SIM_CLKs(); my $pck_info = "Select how injected packet size are selected. - random-range: The injected packet size is randomly selected between given minimum and maximum packet size. - random-discrete: The injected packet size is randomly selected among given district valuse."; - - if($traffictype eq "Synthetic"){ - - my $min=$self->object_get_attribute($sample,'MIN_PCK_SIZE'); - my $max=$self->object_get_attribute($sample,'MAX_PCK_SIZE'); - $min=5 if(!defined $min); - $max=5 if(!defined $max); - $max= $min if($max< $min); - my $avg=floor(($min+$max)/2); - my $msg; - my $max_pck_size = get_MAX_PCK_SIZ(); - - my $NE; - my ($infobox,$info)= create_txview(); - - - my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,hot spot,shuffle,bit rotation,neighbor,custom"; - my @synthinfo = ( - - - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - - - { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - - { label=>"Packet size (#flit)", param_name=>'PCK_SIZ_SEL', type=>'Combo-box', default_val=>'random-range', content=>"random-range,random-discrete", info=>$pck_info, param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - - ); - my $coltmp=0; - - foreach my $d (@synthinfo) { - - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - - } - - my $t=$self->object_get_attribute($sample,"PCK_SIZ_SEL"); - if($t eq 'random-range' ){ - - @synthinfo = ( - { label=>"Min pck size :", param_name=>'MIN_PCK_SIZE', type=>'Spin-button', default_val=>5, content=>"1,$max,1", info=>"Minimum packet size in flit. The injected packet size is randomly selected between minimum and maximum packet size", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, - { label=>"Max pck size :", param_name=>'MAX_PCK_SIZE', type=>'Spin-button', default_val=>5, content=>"$min,$max_pck_size,1", info=>"Maximum packet size in flit. The injected packet size is randomly selected between minimum and maximum packet size", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, - { label=>"Avg. Packet size:", param_name=>'PCK_SIZE', type=>'Fixed', default_val=>$avg, content=>"$avg", info=>undef, param_parent=>$sample, ref_delay=>undef}, - ); - - }else{ - #$self->object_add_attribute ($sample,"MIN_PCK_SIZE",2);#will be updated by get_district_avg - my $vt=$self->object_get_attribute($sample,"DISCRETE_RANGE"); - $vt = "2,3,4,5" unless (defined $vt); - my $pt=$self->object_get_attribute($sample,"PROBEB_RANGE"); - $pt= "25,25,25,25" unless (defined $pt); - - #($avg,$msg) = get_district_avg($self,$sample); - - - @synthinfo = ( - { label=>"pck size discrete range: ", param_name=>'DISCRETE_RANGE', type=>'Entry', default_val=>$vt, content=>undef, info=>"Set discrete set of number as packet size separated by \",\" (v1,v2,v3 ..). The injected packet size is randomly selected among these discrete values", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, - { label=>"pck size probebility(%): ", param_name=>'PROBEB_RANGE' , type=>'Entry', default_val=>$pt, content=>undef, info=>"Set the probability separated by \",\" (p1,p2,p3 ..). The probabilities pi must satisfy two requirements: every probability pi is a number between 0 and 100, and the sum of all the probabilities is 100.", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, - # { label=>"Avg. Packet size:", param_name=>'PCK_SIZE', type=>'Fixed', default_val=>$avg, content=>"$avg", info=>undef, param_parent=>$sample, ref_delay=>undef}, - ); - - - } - - foreach my $d (@synthinfo){ - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - if(defined $msg){ - my $error= def_image_button("icons/cancel.png"); - $table->attach ($error , 6, 7, $row-1,$row,'shrink','shrink',2,2); - } - - - my $traffic=$self->object_get_attribute($sample,"traffic"); - - my $st = check_sim_sample($self,$sample,$info); - if ($st==0){ - $NE=100; - }else{ - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NEe, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - $NE=$NEe; - } - - - if ($traffic eq 'custom'){ - - - my $htable=def_table(10,2,FALSE); - - my $d= { label=>'number of active nodes:', param_name=>'CUSTOM_SRC_NUM', type=>'Spin-button', default_val=>1, content=>"1,$NE,1", info=>"Number of active nodes which injects packets to the NoC", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); - $htable->attach ( gen_label_in_left ("Source "), 0, 1, $row,$row+1,'fill','shrink',2,2); - $htable->attach ( gen_label_in_left (" -> "), 1, 2, $row,$row+1,'fill','shrink',2,2); - $htable->attach ( gen_label_in_left ("Destination"), 2, 3, $row,$row+1,'fill','shrink',2,2); - - $row++; - - - my $tiles="0"; - for (my $i=1;$i<$NE;$i++){$tiles.=",$i";} - - - for (my $i=0;$i<$num;$i++){ - my $w1 = gen_combobox_object ($self,$sample,"SRC_$i",$tiles, $i,undef,undef); - my $w2 = gen_combobox_object ($self,$sample,"DST_$i",$tiles, $i+1,undef,undef); - $htable->attach ($w1 , 0, 1, $row,$row+1,'shrink','shrink',2,2); - $htable->attach ($w2 , 2, 3, $row,$row+1,'shrink','shrink',2,2); - $row++; - - } - $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; - - } - - - if ($cast_type ne '"UNICAST"'){ - my $min=$self->object_get_attribute($sample,'MCAST_PCK_SIZ_MIN'); - my $max=$self->object_get_attribute($sample,'MCAST_PCK_SIZ_MAX'); - $min=5 if(!defined $min); - $max=5 if(!defined $max); - $max= $min if($max< $min); - - - my $s = ($cast_type eq '"BROADCAST_FULL"' || $cast_type eq '"BROADCAST_PARTIAL"')? "Broadcast" : "Milticast"; - my $info1= "Define the percentage ratio of $s traffic towards Unicast traffic"; - my $info2= "Define how destinations is selected in Multicast packets"; - ($row,$coltmp)=add_param_widget ($self, "$s Node Select" , "MCAST_TRAFFIC_TYPE" , "Uniform-Random", 'Combo-box', "Uniform-Random", $info1, $table,$row,undef,1, $sample); - ($row,$coltmp)=add_param_widget ($self, "$s Traffic Ratio", "MCAST_TRAFFIC_RATIO", 5 , 'Spin-button', "0,100,1" , $info2, $table,$row,undef,1, $sample); - - ($row,$coltmp)=add_param_widget ($self, "$s min pck size", "MCAST_PCK_SIZ_MIN", 5 , 'Spin-button', "1,$max,1" , $info2, $table,$row,undef,1, $sample,1,'ref_set_win'); - - ($row,$coltmp)=add_param_widget ($self, "$s max pck size", "MCAST_PCK_SIZ_MAX", 5 , 'Spin-button', "$min,100,1" , $info2, $table,$row,undef,1, $sample,1,'ref_set_win'); - - - - } - - - - - my $d= { label=>'number of message class:', param_name=>'MESSAGE_CLASS', type=>'Spin-button', default_val=>0, content=>"0,256,1", info=>"Number of packet message classes. Each message class can be configured to use specefic subset of avilable VCs", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - my $num=$self->object_get_attribute($sample,"MESSAGE_CLASS"); - if($num>0){ - my $htable=def_table(10,2,FALSE); - $htable->attach ( gen_label_in_left ("Class num "), 0, 1, $row,$row+1,'fill','shrink',2,2); - $htable->attach ( gen_label_in_left (" - "), 1, 2, $row,$row+1,'fill','shrink',2,2); - $htable->attach ( gen_label_in_left ("Traffic(%)"), 2, 3, $row,$row+1,'fill','shrink',2,2); - $row++; - - for (my $i=0;$i<$num;$i++){ - $htable->attach ( gen_label_in_left ("$i"), 0, 1, $row,$row+1,'fill','shrink',2,2); - my $w1 = gen_spin_object ($self,$sample,"CLASS_$i","0,100,1", 100/$num,undef,undef); - $htable->attach ( $w1, 2, 3, $row,$row+1,'fill','shrink',2,2); - $row++; - } - $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; - } - - - - if ($traffic eq 'hot spot'){ - my $htable=def_table(10,2,FALSE); - - my $d= { label=>'number of Hot Spot nodes:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, content=>"1,256,1", info=>"Number of hot spot nodes in the network", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - - my $l1=gen_label_help("Define the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node"," Hot Spot tile number \%"); - my $l2=gen_label_help("If it is set as \"n\" then each node sends n % of its traffic to each hotspot node"," Hot Spot traffic \%"); - my $l3=gen_label_help("If it is checked then hot spot node also sends packets to other nodes otherwise it only receives packets from other nodes"," send enable"); - - $htable->attach ($l1 , 0, 1, $row,$row+1,'fill','shrink',2,2); - $htable->attach ($l2 , 1, 2, $row,$row+1,'fill','shrink',2,2); - $htable->attach ($l3 , 2,3, $row,$row+1,'fill','shrink',2,2); - $row++; - - my $num=$self->object_get_attribute($sample,"HOTSPOT_NUM"); - for (my $i=0;$i<$num;$i++){ - my $w1 = gen_spin_object ($self,$sample,"HOTSPOT_CORE_$i","0,256,1", $i,undef,undef); - my $w2 = gen_spin_object ($self,$sample,"HOTSPOT_PERCENT_$i","0.1,100,0.1", 0.1,undef,undef); - my $w3 = gen_check_box_object ($self,$sample,"HOTSPOT_SEND_EN_$i", 0,undef,undef); - $htable->attach ($w1 , 0, 1, $row,$row+1,'fill','shrink',2,2); - $htable->attach ($w2 ,1, 2, $row,$row+1,'fill','shrink',2,2); - $htable->attach ($w3 , 2,3, $row,$row+1,'fill','shrink',2,2); - $row++; - - } - - $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; - - - - - - - - } - my $l= "Define injection ratios. You can define individual ratios separating by comma (\',\') or define a range of injection ratios with \$min:\$max:\$step format. - As an example defining 2,3,4:10:2 will result in (2,3,4,6,8,10) injection ratios." ; - my $u=get_injection_ratios ($self,$sample,"ratios"); - - attach_widget_to_table ($table,$row,gen_label_in_left(" Injection ratios:"),gen_button_message ($l,"icons/help.png") , $u); $row++; - - $ok->signal_connect("clicked"=> sub{ - #check if sof file has been selected - my $s=$self->object_get_attribute($sample,"sof_file"); - #check if injection ratios are valid - my $r=$self->object_get_attribute($sample,"ratios"); - - my $h; - - my $t=$self->object_get_attribute($sample,"PCK_SIZ_SEL"); - unless ($t eq 'random-range' ){ - ($avg,$msg) = get_district_avg($self,$sample); - if(defined $msg){ - message_dialog($msg); - return; - } - } - - if ($traffic eq 'hot spot'){ - $h= check_hotspot_parameters($self,$sample); - } - - my $v; - if(defined $r ){ - $v=check_inserted_ratios($r); - } - - if(defined $s && defined $r && defined $v && !defined $h) { - #$set_win->destroy; - $set_win->hide(); - $self->object_add_attribute("active_setting",undef,undef); - set_gui_status($self,"ref",1); - } else { - - if(!defined $s){ - my $m= "Please select NoC verilated file"; - message_dialog($m); - } elsif (! defined $r) { - message_dialog("Please define valid injection ratio(s)!"); - } elsif (defined $h){ - message_dialog("$h"); - } - } - }); - - } - - - if($traffictype eq "Task-graph"){ - - my @custominfo = ( - #{ label=>"Verilated Model", param_name=>'sof_file', type=>'Combo-box', default_val=>undef, content=>$exe_files, info=>"Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - { label=>"Number of Files", param_name=>"TRAFFIC_FILE_NUM", type=>'Spin-button', default_val=>1, content=>"1,100,1", info=>"Select number of input files", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - - { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - ); - - foreach my $d (@custominfo) { - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - - } - - - my $open_in = "$ENV{'PRONOC_WORK'}/traffic_pattern"; - - - - my $num=$self->object_get_attribute($sample,"TRAFFIC_FILE_NUM"); - for (my $i=0; $i<$num; $i++){ - attach_widget_to_table ($table,$row,gen_label_in_left("traffic pattern file $i:"),gen_button_message ("Select the traffic pattern input file. Any custom traffic based on application task graphs can be generated using ProNoC Trace Generator tool.","icons/help.png"), get_file_name_object ($self,$sample,"traffic_file$i",undef,$open_in)); $row++; - } - - - - - - $ok->signal_connect("clicked"=> sub{ - #check if sof file has been selected - my $s=$self->object_get_attribute($sample,"sof_file"); - if(!defined $s){ - message_dialog("Please select NoC verilated file"); - return; - } - - #check if traffic files have been selected - for (my $i=0; $i<$num; $i++){ - my $f=$self->object_get_attribute($sample,"traffic_file$i"); - if(!defined $f){ - my $m= "Please select traffic_file$i"; - message_dialog($m); - return; - } - - } - #$set_win->destroy; - $set_win->hide(); - $self->object_add_attribute("active_setting",undef,undef); - set_gui_status($self,"ref",1); - - }); - - - } - - - if($traffictype eq "SynFull"){ - #get the synful model names - my $models_dir = get_project_dir()."/mpsoc/src_c/synfull/generated-models/"; - my ($flist)=get_file_list_by_extention ("$models_dir",".model"); - - - my $model_obj = gen_combobox_object ($self,$sample, "MODEL_NAME", $flist, undef,undef,undef); - attach_widget_to_table ($table,$row,gen_label_in_left(" Traffic Model name:"),gen_button_message ("Select an application traffic model.","icons/help.png"), - $model_obj); $row++; - - - - my @custominfo = ( - { label=>"Synful Flit-size:(Bytes)", param_name=>'SYNFUL_FLITw', type=>'Spin-button', default_val=>4, content=>"4,72,4", info=>"The synful flit size in Byte. It defines the number of flits that should be set to ProNoC for each synful packets. The ProNoC packet size is : - \t Ceil( synful packet size/synful flit size). ", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Markov Chain Random seed:", param_name=>'RND_SEED', type=>'Spin-button', default_val=>53432145, content=>"0,999999999,1", info=>"The seed valus is passe to synfull random number generator.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Exit at steady state:", param_name=>'EXIT_STEADY', type=>'Check-box', default_val=>0, content=>"1", info=>"Exit the simulation when it reaches to a steady state.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - - - ); - - - - foreach my $d (@custominfo) { - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - - } - - $ok->signal_connect("clicked"=> sub{ - #check if sof file has been selected - my $s=$self->object_get_attribute($sample,"MODEL_NAME"); - if(!defined $s){ - message_dialog("Please select a SynFull traffic model"); - return; - } - - - #$set_win->destroy; - $set_win->hide(); - $self->object_add_attribute("active_setting",undef,undef); - set_gui_status($self,"ref",1); - - }); - - - - }#SynFull - - - if($traffictype eq "Netrace"){ - #get the synful model names - my $models_dir = "$ENV{PRONOC_WORK}/simulate/netrace"; - my ($flist)=get_file_list_by_extention ("$models_dir",".bz2"); - - my $model_obj = gen_combobox_object ($self,$sample, "MODEL_NAME", $flist, undef,undef,undef); - my $download=def_image_button("icons/download.png",'Download'); - my $box =def_hbox(FALSE, 0); - $box->pack_start( $model_obj , 1,1, 0); - $box->pack_start( $download, 0, 1, 3); - - attach_widget_to_table ($table,$row,gen_label_in_left(" Trace name:"),gen_button_message ("Select a netrace trace file. You can download traces using download button.","icons/help.png"), - $box); - - - $row++; - - - - my @custominfo = ( - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - #{ label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"ignore dependencies:", param_name=>'IGNORE_DPNDCY', type=>'Check-box', default_val=>0, content=>"1", info=>"Ignore dependency between packets", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Enable reader throttling:", param_name=>'READER_THRL', type=>'Check-box', default_val=>0, content=>"1", info=>"If Reader throttling is enabled, simulators offloads much of the work of reading and tracking packets to the Netrace reader, + random-range: The injected packet size is randomly selected between given minimum and maximum packet size. + random-discrete: The injected packet size is randomly selected among given district valuse."; + + if($traffictype eq "Synthetic"){ + + my $min=$self->object_get_attribute($sample,'MIN_PCK_SIZE'); + my $max=$self->object_get_attribute($sample,'MAX_PCK_SIZE'); + $min=5 if(!defined $min); + $max=5 if(!defined $max); + $max= $min if($max< $min); + my $avg=floor(($min+$max)/2); + my $msg; + my $max_pck_size = get_MAX_PCK_SIZ(); + + my $NE; + my ($infobox,$info)= create_txview(); + + + my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,hot spot,shuffle,bit rotation,neighbor,custom"; + my @synthinfo = ( + + + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + + + + { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + + { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + + { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, + + { label=>"Packet size (#flit)", param_name=>'PCK_SIZ_SEL', type=>'Combo-box', default_val=>'random-range', content=>"random-range,random-discrete", info=>$pck_info, param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, + + ); + my $coltmp=0; + + foreach my $d (@synthinfo) { + + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + + } + + my $t=$self->object_get_attribute($sample,"PCK_SIZ_SEL"); + if($t eq 'random-range' ){ + + @synthinfo = ( + { label=>"Min pck size :", param_name=>'MIN_PCK_SIZE', type=>'Spin-button', default_val=>5, content=>"1,$max,1", info=>"Minimum packet size in flit. The injected packet size is randomly selected between minimum and maximum packet size", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, + { label=>"Max pck size :", param_name=>'MAX_PCK_SIZE', type=>'Spin-button', default_val=>5, content=>"$min,$max_pck_size,1", info=>"Maximum packet size in flit. The injected packet size is randomly selected between minimum and maximum packet size", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, + { label=>"Avg. Packet size:", param_name=>'PCK_SIZE', type=>'Fixed', default_val=>$avg, content=>"$avg", info=>undef, param_parent=>$sample, ref_delay=>undef}, + ); + + }else{ + #$self->object_add_attribute ($sample,"MIN_PCK_SIZE",2);#will be updated by get_district_avg + my $vt=$self->object_get_attribute($sample,"DISCRETE_RANGE"); + $vt = "2,3,4,5" unless (defined $vt); + my $pt=$self->object_get_attribute($sample,"PROBEB_RANGE"); + $pt= "25,25,25,25" unless (defined $pt); + + #($avg,$msg) = get_district_avg($self,$sample); + + + @synthinfo = ( + { label=>"pck size discrete range: ", param_name=>'DISCRETE_RANGE', type=>'Entry', default_val=>$vt, content=>undef, info=>"Set discrete set of number as packet size separated by \",\" (v1,v2,v3 ..). The injected packet size is randomly selected among these discrete values", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, + { label=>"pck size probebility(%): ", param_name=>'PROBEB_RANGE' , type=>'Entry', default_val=>$pt, content=>undef, info=>"Set the probability separated by \",\" (p1,p2,p3 ..). The probabilities pi must satisfy two requirements: every probability pi is a number between 0 and 100, and the sum of all the probabilities is 100.", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, + # { label=>"Avg. Packet size:", param_name=>'PCK_SIZE', type=>'Fixed', default_val=>$avg, content=>"$avg", info=>undef, param_parent=>$sample, ref_delay=>undef}, + ); + + + } + + foreach my $d (@synthinfo){ + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + } + if(defined $msg){ + my $error= def_image_button("icons/cancel.png"); + $table->attach ($error , 6, 7, $row-1,$row,'shrink','shrink',2,2); + } + + + my $traffic=$self->object_get_attribute($sample,"traffic"); + + my $st = check_sim_sample($self,$sample,$info); + if ($st==0){ + $NE=100; + }else{ + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($NEe, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + $NE=$NEe; + } + + + if ($traffic eq 'custom'){ + + + my $htable=def_table(10,2,FALSE); + + my $d= { label=>'number of active nodes:', param_name=>'CUSTOM_SRC_NUM', type=>'Spin-button', default_val=>1, content=>"1,$NE,1", info=>"Number of active nodes which injects packets to the NoC", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); + $htable->attach ( gen_label_in_left ("Source "), 0, 1, $row,$row+1,'fill','shrink',2,2); + $htable->attach ( gen_label_in_left (" -> "), 1, 2, $row,$row+1,'fill','shrink',2,2); + $htable->attach ( gen_label_in_left ("Destination"), 2, 3, $row,$row+1,'fill','shrink',2,2); + + $row++; + + + my $tiles="0"; + for (my $i=1;$i<$NE;$i++){$tiles.=",$i";} + + + for (my $i=0;$i<$num;$i++){ + my $w1 = gen_combobox_object ($self,$sample,"SRC_$i",$tiles, $i,undef,undef); + my $w2 = gen_combobox_object ($self,$sample,"DST_$i",$tiles, $i+1,undef,undef); + $htable->attach ($w1 , 0, 1, $row,$row+1,'shrink','shrink',2,2); + $htable->attach ($w2 , 2, 3, $row,$row+1,'shrink','shrink',2,2); + $row++; + + } + $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; + + } + + + if ($cast_type ne '"UNICAST"'){ + my $min=$self->object_get_attribute($sample,'MCAST_PCK_SIZ_MIN'); + my $max=$self->object_get_attribute($sample,'MCAST_PCK_SIZ_MAX'); + $min=5 if(!defined $min); + $max=5 if(!defined $max); + $max= $min if($max< $min); + + + my $s = ($cast_type eq '"BROADCAST_FULL"' || $cast_type eq '"BROADCAST_PARTIAL"')? "Broadcast" : "Milticast"; + my $info1= "Define the percentage ratio of $s traffic towards Unicast traffic"; + my $info2= "Define how destinations is selected in Multicast packets"; + ($row,$coltmp)=add_param_widget ($self, "$s Node Select" , "MCAST_TRAFFIC_TYPE" , "Uniform-Random", 'Combo-box', "Uniform-Random", $info1, $table,$row,undef,1, $sample); + ($row,$coltmp)=add_param_widget ($self, "$s Traffic Ratio", "MCAST_TRAFFIC_RATIO", 5 , 'Spin-button', "0,100,1" , $info2, $table,$row,undef,1, $sample); + + ($row,$coltmp)=add_param_widget ($self, "$s min pck size", "MCAST_PCK_SIZ_MIN", 5 , 'Spin-button', "1,$max,1" , $info2, $table,$row,undef,1, $sample,1,'ref_set_win'); + + ($row,$coltmp)=add_param_widget ($self, "$s max pck size", "MCAST_PCK_SIZ_MAX", 5 , 'Spin-button', "$min,100,1" , $info2, $table,$row,undef,1, $sample,1,'ref_set_win'); + + + + } + + + + + my $d= { label=>'number of message class:', param_name=>'MESSAGE_CLASS', type=>'Spin-button', default_val=>0, content=>"0,256,1", info=>"Number of packet message classes. Each message class can be configured to use specefic subset of avilable VCs", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + my $num=$self->object_get_attribute($sample,"MESSAGE_CLASS"); + if($num>0){ + my $htable=def_table(10,2,FALSE); + $htable->attach ( gen_label_in_left ("Class num "), 0, 1, $row,$row+1,'fill','shrink',2,2); + $htable->attach ( gen_label_in_left (" - "), 1, 2, $row,$row+1,'fill','shrink',2,2); + $htable->attach ( gen_label_in_left ("Traffic(%)"), 2, 3, $row,$row+1,'fill','shrink',2,2); + $row++; + + for (my $i=0;$i<$num;$i++){ + $htable->attach ( gen_label_in_left ("$i"), 0, 1, $row,$row+1,'fill','shrink',2,2); + my $w1 = gen_spin_object ($self,$sample,"CLASS_$i","0,100,1", 100/$num,undef,undef); + $htable->attach ( $w1, 2, 3, $row,$row+1,'fill','shrink',2,2); + $row++; + } + $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; + } + + + + if ($traffic eq 'hot spot'){ + my $htable=def_table(10,2,FALSE); + + my $d= { label=>'number of Hot Spot nodes:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, content=>"1,256,1", info=>"Number of hot spot nodes in the network", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + + my $l1=gen_label_help("Define the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node"," Hot Spot tile number \%"); + my $l2=gen_label_help("If it is set as \"n\" then each node sends n % of its traffic to each hotspot node"," Hot Spot traffic \%"); + my $l3=gen_label_help("If it is checked then hot spot node also sends packets to other nodes otherwise it only receives packets from other nodes"," send enable"); + + $htable->attach ($l1 , 0, 1, $row,$row+1,'fill','shrink',2,2); + $htable->attach ($l2 , 1, 2, $row,$row+1,'fill','shrink',2,2); + $htable->attach ($l3 , 2,3, $row,$row+1,'fill','shrink',2,2); + $row++; + + my $num=$self->object_get_attribute($sample,"HOTSPOT_NUM"); + for (my $i=0;$i<$num;$i++){ + my $w1 = gen_spin_object ($self,$sample,"HOTSPOT_CORE_$i","0,256,1", $i,undef,undef); + my $w2 = gen_spin_object ($self,$sample,"HOTSPOT_PERCENT_$i","0.1,100,0.1", 0.1,undef,undef); + my $w3 = gen_check_box_object ($self,$sample,"HOTSPOT_SEND_EN_$i", 0,undef,undef); + $htable->attach ($w1 , 0, 1, $row,$row+1,'fill','shrink',2,2); + $htable->attach ($w2 ,1, 2, $row,$row+1,'fill','shrink',2,2); + $htable->attach ($w3 , 2,3, $row,$row+1,'fill','shrink',2,2); + $row++; + + } + + $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; + + + + + + + + } + my $l= "Define injection ratios. You can define individual ratios separating by comma (\',\') or define a range of injection ratios with \$min:\$max:\$step format. + As an example defining 2,3,4:10:2 will result in (2,3,4,6,8,10) injection ratios." ; + my $u=get_injection_ratios ($self,$sample,"ratios"); + + attach_widget_to_table ($table,$row,gen_label_in_left(" Injection ratios:"),gen_button_message ($l,"icons/help.png") , $u); $row++; + + $ok->signal_connect("clicked"=> sub{ + #check if sof file has been selected + my $s=$self->object_get_attribute($sample,"sof_file"); + #check if injection ratios are valid + my $r=$self->object_get_attribute($sample,"ratios"); + + my $h; + + my $t=$self->object_get_attribute($sample,"PCK_SIZ_SEL"); + unless ($t eq 'random-range' ){ + ($avg,$msg) = get_district_avg($self,$sample); + if(defined $msg){ + message_dialog($msg); + return; + } + } + + if ($traffic eq 'hot spot'){ + $h= check_hotspot_parameters($self,$sample); + } + + my $v; + if(defined $r ){ + $v=check_inserted_ratios($r); + } + + if(defined $s && defined $r && defined $v && !defined $h) { + #$set_win->destroy; + $set_win->hide(); + $self->object_add_attribute("active_setting",undef,undef); + set_gui_status($self,"ref",1); + } else { + + if(!defined $s){ + my $m= "Please select NoC verilated file"; + message_dialog($m); + } elsif (! defined $r) { + message_dialog("Please define valid injection ratio(s)!"); + } elsif (defined $h){ + message_dialog("$h"); + } + } + }); + + } + + + if($traffictype eq "Task-graph"){ + + my @custominfo = ( + #{ label=>"Verilated Model", param_name=>'sof_file', type=>'Combo-box', default_val=>undef, content=>$exe_files, info=>"Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + + { label=>"Number of Files", param_name=>"TRAFFIC_FILE_NUM", type=>'Spin-button', default_val=>1, content=>"1,100,1", info=>"Select number of input files", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, + + { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + ); + + foreach my $d (@custominfo) { + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + + } + + + my $open_in = "$ENV{'PRONOC_WORK'}/traffic_pattern"; + + + + my $num=$self->object_get_attribute($sample,"TRAFFIC_FILE_NUM"); + for (my $i=0; $i<$num; $i++){ + attach_widget_to_table ($table,$row,gen_label_in_left("traffic pattern file $i:"),gen_button_message ("Select the traffic pattern input file. Any custom traffic based on application task graphs can be generated using ProNoC Trace Generator tool.","icons/help.png"), get_file_name_object ($self,$sample,"traffic_file$i",undef,$open_in)); $row++; + } + + + + + + $ok->signal_connect("clicked"=> sub{ + #check if sof file has been selected + my $s=$self->object_get_attribute($sample,"sof_file"); + if(!defined $s){ + message_dialog("Please select NoC verilated file"); + return; + } + + #check if traffic files have been selected + for (my $i=0; $i<$num; $i++){ + my $f=$self->object_get_attribute($sample,"traffic_file$i"); + if(!defined $f){ + my $m= "Please select traffic_file$i"; + message_dialog($m); + return; + } + + } + #$set_win->destroy; + $set_win->hide(); + $self->object_add_attribute("active_setting",undef,undef); + set_gui_status($self,"ref",1); + + }); + + + } + + + if($traffictype eq "SynFull"){ + #get the synful model names + my $models_dir = get_project_dir()."/mpsoc/src_c/synfull/generated-models/"; + my ($flist)=get_file_list_by_extention ("$models_dir",".model"); + + + my $model_obj = gen_combobox_object ($self,$sample, "MODEL_NAME", $flist, undef,undef,undef); + attach_widget_to_table ($table,$row,gen_label_in_left(" Traffic Model name:"),gen_button_message ("Select an application traffic model.","icons/help.png"), + $model_obj); $row++; + + + + my @custominfo = ( + { label=>"Synful Flit-size:(Bytes)", param_name=>'SYNFUL_FLITw', type=>'Spin-button', default_val=>4, content=>"4,72,4", info=>"The synful flit size in Byte. It defines the number of flits that should be set to ProNoC for each synful packets. The ProNoC packet size is : + \t Ceil( synful packet size/synful flit size). ", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"Markov Chain Random seed:", param_name=>'RND_SEED', type=>'Spin-button', default_val=>53432145, content=>"0,999999999,1", info=>"The seed valus is passe to synfull random number generator.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"Exit at steady state:", param_name=>'EXIT_STEADY', type=>'Check-box', default_val=>0, content=>"1", info=>"Exit the simulation when it reaches to a steady state.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + + + + ); + + + + foreach my $d (@custominfo) { + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + + } + + $ok->signal_connect("clicked"=> sub{ + #check if sof file has been selected + my $s=$self->object_get_attribute($sample,"MODEL_NAME"); + if(!defined $s){ + message_dialog("Please select a SynFull traffic model"); + return; + } + + + #$set_win->destroy; + $set_win->hide(); + $self->object_add_attribute("active_setting",undef,undef); + set_gui_status($self,"ref",1); + + }); + + + + }#SynFull + + + if($traffictype eq "Netrace"){ + #get the synful model names + my $models_dir = "$ENV{PRONOC_WORK}/simulate/netrace"; + my ($flist)=get_file_list_by_extention ("$models_dir",".bz2"); + + my $model_obj = gen_combobox_object ($self,$sample, "MODEL_NAME", $flist, undef,undef,undef); + my $download=def_image_button("icons/download.png",'Download'); + my $box =def_hbox(FALSE, 0); + $box->pack_start( $model_obj , 1,1, 0); + $box->pack_start( $download, 0, 1, 3); + + attach_widget_to_table ($table,$row,gen_label_in_left(" Trace name:"),gen_button_message ("Select a netrace trace file. You can download traces using download button.","icons/help.png"), + $box); + + + $row++; + + + + my @custominfo = ( + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + #{ label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"ignore dependencies:", param_name=>'IGNORE_DPNDCY', type=>'Check-box', default_val=>0, content=>"1", info=>"Ignore dependency between packets", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"Enable reader throttling:", param_name=>'READER_THRL', type=>'Check-box', default_val=>0, content=>"1", info=>"If Reader throttling is enabled, simulators offloads much of the work of reading and tracking packets to the Netrace reader, which simplifies the code in the network simulator.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"trace file start region:", param_name=>'START_RGN', type=>'Spin-button', default_val=>0, content=>"0,10000,1", info=>undef, param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Netrace to Pronoc clk ratio:", param_name=>'SPEED_UP', type=>'Spin-button', default_val=>1, content=>"1,99,1", info=>"The ratio of netrace frequency to pronoc.The higher value results in higher injection ratio to the NoC. Default is one\n", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - - - - - - ); - - - - foreach my $d (@custominfo) { - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - - } - - $ok->signal_connect("clicked"=> sub{ - #check if sof file has been selected - my $s=$self->object_get_attribute($sample,"MODEL_NAME"); - if(!defined $s){ - message_dialog("Please select a SynFull traffic model"); - return; - } - - - #$set_win->destroy; - $set_win->hide(); - $self->object_add_attribute("active_setting",undef,undef); - set_gui_status($self,"ref",1); - - }); - - $download->signal_connect("clicked"=> sub{ download_netrace("$models_dir") }); - - - - }#netrace - - - - - - - add_widget_to_scrolled_win ($mtable,$set_win); - - $set_win->show_all(); - - + { label=>"trace file start region:", param_name=>'START_RGN', type=>'Spin-button', default_val=>0, content=>"0,10000,1", info=>undef, param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"Netrace to Pronoc clk ratio:", param_name=>'SPEED_UP', type=>'Spin-button', default_val=>1, content=>"1,99,1", info=>"The ratio of netrace frequency to pronoc.The higher value results in higher injection ratio to the NoC. Default is one\n", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + + + + + + + ); + + + + foreach my $d (@custominfo) { + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + + } + + $ok->signal_connect("clicked"=> sub{ + #check if sof file has been selected + my $s=$self->object_get_attribute($sample,"MODEL_NAME"); + if(!defined $s){ + message_dialog("Please select a SynFull traffic model"); + return; + } + + + #$set_win->destroy; + $set_win->hide(); + $self->object_add_attribute("active_setting",undef,undef); + set_gui_status($self,"ref",1); + + }); + + $download->signal_connect("clicked"=> sub{ download_netrace("$models_dir") }); + + + + }#netrace + + + + + + + add_widget_to_scrolled_win ($mtable,$set_win); + + $set_win->show_all(); + + } ############ -# run_simulator +# run_simulator ########### sub run_simulator { - my ($simulate,$info)=@_; - #return if(!check_samples($emulate,$info)); - $simulate->object_add_attribute('status',undef,'run'); - set_gui_status($simulate,"ref",1); - show_info($info, "Start Simulation\n"); - my $name=$simulate->object_get_attribute ("simulate_name",undef); - - #unlink $log; # remove old log file - - my @samples =$simulate->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - my $status=$simulate->object_get_attribute ($sample,"status"); - next if($status ne "run"); - next if(!check_sim_sample($simulate,$sample,$info)); - my $traffictype=$simulate->object_get_attribute($sample,"TRAFFIC_TYPE"); - if($traffictype eq "Synthetic") {run_synthetic_simulation($simulate,$info,$sample,$name);} - elsif($traffictype eq "Task-graph"){run_task_simulation($simulate,$info,$sample,$name) ;} - else {run_trace_simulation($simulate,$info,$sample,$name);} - - } - - add_info($info, "Simulation is done!\n"); - printf "Simulation is done!\n"; - $simulate->object_add_attribute('status',undef,'ideal'); - set_gui_status($simulate,"ref",1); -} + my ($simulate,$info)=@_; + #return if(!check_samples($emulate,$info)); + $simulate->object_add_attribute('status',undef,'run'); + set_gui_status($simulate,"ref",1); + show_info($info, "Start Simulation\n"); + my $name=$simulate->object_get_attribute ("simulate_name",undef); + + #unlink $log; # remove old log file + + my @samples =$simulate->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + my $status=$simulate->object_get_attribute ($sample,"status"); + next if($status ne "run"); + next if(!check_sim_sample($simulate,$sample,$info)); + my $traffictype=$simulate->object_get_attribute($sample,"TRAFFIC_TYPE"); + if($traffictype eq "Synthetic") {run_synthetic_simulation($simulate,$info,$sample,$name);} + elsif($traffictype eq "Task-graph"){run_task_simulation($simulate,$info,$sample,$name) ;} + else {run_trace_simulation($simulate,$info,$sample,$name);} + + } + + add_info($info, "Simulation is done!\n"); + printf "Simulation is done!\n"; + $simulate->object_add_attribute('status',undef,'ideal'); + set_gui_status($simulate,"ref",1); +} sub run_synthetic_simulation { - my ($simulate,$info,$sample,$name)=@_; - - - my %traffic= ( - 'tornado' => 'TORNADO', - 'transposed 1' => "TRANSPOSE1", - 'transposed 2' => "TRANSPOSE2", - 'bit reverse' => "BIT_REVERSE", - 'bit complement' => "BIT_COMPLEMENT", - 'random' => "RANDOM", - 'hot spot' => "HOTSPOT", - 'shuffle' => "SHUFFLE", - 'bit rotation' => "BIT_ROTATE", - 'neighbor' => "NEIGHBOR", - 'custom' => "CUSTOM" - ); - - my $simulator =$simulate->object_get_attribute("Simulator"); - my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; - my $out_path ="$ENV{PRONOC_WORK}/simulate/"; - my $r= $simulate->object_get_attribute($sample,"ratios"); - my @ratios=@{check_inserted_ratios($r)}; - #$emulate->object_add_attribute ("sample$i","status","run"); - my $bin=get_sim_bin_path($simulate,$sample,$info); - - #load traffic configuration - my $patern=$simulate->object_get_attribute ($sample,'traffic'); - my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); - my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); - my $MIN_PCK_SIZE=$simulate->object_get_attribute ($sample,"MIN_PCK_SIZE"); - my $MAX_PCK_SIZE=$simulate->object_get_attribute ($sample,"MAX_PCK_SIZE"); - - - #hotspot - my $custom=""; - my $custom_sv=""; - if ($patern eq 'custom'){ - $custom=""; - my $num=$simulate->object_get_attribute($sample,"CUSTOM_SRC_NUM"); - $custom_sv.="localparam CUSTOM_NODE_NUM=$num;\n\twire [NEw-1 : 0] custom_traffic_t [NE-1 : 0];\n\twire [NE-1 : 0] custom_traffic_en;\n"; - my @srcs; - for (my $i=0;$i<$num; $i++){ - my $src = $simulate->object_get_attribute($sample,"SRC_$i"); - my $dst = $simulate->object_get_attribute($sample,"DST_$i"); - - $custom.=($i==0)? "-H \"$src,$dst" : ",$src,$dst"; - - } - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($simulate,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - - for (my $i=0;$i<$NE; $i++){ - my ($src,$dst) = custom_traffic_dest ($simulate,$sample,$i); - $custom_sv.="\tassign custom_traffic_t[$src]=$dst;\n"; - $custom_sv.="\tassign custom_traffic_en[$src]="; - $custom_sv.=($dst==-1)? "1'b0;//off \n" : "1'b1;\n" - } - $custom.="\""; - - } - else{ - $custom_sv.="localparam CUSTOM_NODE_NUM=0;\n\twire [NEw-1 : 0] custom_traffic_t [NE-1 : 0];\n\twire [NE-1 : 0] custom_traffic_en; - "; - } - #multicast - my $mcast=""; - my $mcast_sv=""; - my $p= $simulate->object_get_attribute ($sample,"noc_info"); + my ($simulate,$info,$sample,$name)=@_; + + + my %traffic= ( + 'tornado' => 'TORNADO', + 'transposed 1' => "TRANSPOSE1", + 'transposed 2' => "TRANSPOSE2", + 'bit reverse' => "BIT_REVERSE", + 'bit complement' => "BIT_COMPLEMENT", + 'random' => "RANDOM", + 'hot spot' => "HOTSPOT", + 'shuffle' => "SHUFFLE", + 'bit rotation' => "BIT_ROTATE", + 'neighbor' => "NEIGHBOR", + 'custom' => "CUSTOM" + ); + + my $simulator =$simulate->object_get_attribute("Simulator"); + my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; + my $out_path ="$ENV{PRONOC_WORK}/simulate/"; + my $r= $simulate->object_get_attribute($sample,"ratios"); + my @ratios=@{check_inserted_ratios($r)}; + #$emulate->object_add_attribute ("sample$i","status","run"); + my $bin=get_sim_bin_path($simulate,$sample,$info); + + #load traffic configuration + my $patern=$simulate->object_get_attribute ($sample,'traffic'); + my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); + my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); + my $MIN_PCK_SIZE=$simulate->object_get_attribute ($sample,"MIN_PCK_SIZE"); + my $MAX_PCK_SIZE=$simulate->object_get_attribute ($sample,"MAX_PCK_SIZE"); + + + #hotspot + my $custom=""; + my $custom_sv=""; + if ($patern eq 'custom'){ + $custom=""; + my $num=$simulate->object_get_attribute($sample,"CUSTOM_SRC_NUM"); + $custom_sv.="localparam CUSTOM_NODE_NUM=$num;\n\twire [NEw-1 : 0] custom_traffic_t [NE-1 : 0];\n\twire [NE-1 : 0] custom_traffic_en;\n"; + my @srcs; + for (my $i=0;$i<$num; $i++){ + my $src = $simulate->object_get_attribute($sample,"SRC_$i"); + my $dst = $simulate->object_get_attribute($sample,"DST_$i"); + + $custom.=($i==0)? "-H \"$src,$dst" : ",$src,$dst"; + + } + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($simulate,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + + for (my $i=0;$i<$NE; $i++){ + my ($src,$dst) = custom_traffic_dest ($simulate,$sample,$i); + $custom_sv.="\tassign custom_traffic_t[$src]=$dst;\n"; + $custom_sv.="\tassign custom_traffic_en[$src]="; + $custom_sv.=($dst==-1)? "1'b0;//off \n" : "1'b1;\n" + } + $custom.="\""; + + } + else{ + $custom_sv.="localparam CUSTOM_NODE_NUM=0;\n\twire [NEw-1 : 0] custom_traffic_t [NE-1 : 0];\n\twire [NE-1 : 0] custom_traffic_en; + "; + } + #multicast + my $mcast=""; + my $mcast_sv=""; + my $p= $simulate->object_get_attribute ($sample,"noc_info"); my $cast_type=$p->{"CAST_TYPE"}; - if ($cast_type ne '"UNICAST"'){ - #$self->object_get_attribute ($sample, "MCAST_TRAFFIC_TYPE"); - my $mr = $simulate->object_get_attribute ($sample, "MCAST_TRAFFIC_RATIO"); - my $mmax = $simulate->object_get_attribute ($sample, "MCAST_PCK_SIZ_MAX"); - my $mmin = $simulate->object_get_attribute ($sample, "MCAST_PCK_SIZ_MIN"); - - $mcast = "-u \"$mr,$mmin,$mmax\""; - $mcast_sv.= "localparam MCAST_TRAFFIC_RATIO = $mr;\n"; - $mcast_sv.= "localparam MCAST_PCK_SIZ_MAX = $mmax;\n"; - $mcast_sv.= "localparam MCAST_PCK_SIZ_MIN = $mmin;\n"; - }else { - $mcast_sv.= "localparam MCAST_TRAFFIC_RATIO = 0;\n"; - $mcast_sv.= "localparam MCAST_PCK_SIZ_MAX = 0;\n"; - $mcast_sv.= "localparam MCAST_PCK_SIZ_MIN = 0;\n"; - } - - - - - - my $classes; - my $num=$simulate->object_get_attribute($sample,"MESSAGE_CLASS"); - $classes.="-p 100" if($num==0); - for (my $i=0;$i<$num;$i++){ - my $w1 = $simulate->object_get_attribute($sample,"CLASS_$i"); - $classes.= ($i==0)? "-p $w1" : ",$w1" ; - - } - - my $discrete_sv=""; - my $hotspot=""; - my $hotspot_sv=""; - if($patern eq "hot spot"){ - $hotspot="-h \" "; - my $num=$simulate->object_get_attribute($sample,"HOTSPOT_NUM"); - if (defined $num){ - $hotspot.=" $num"; - - $hotspot_sv.="localparam HOTSPOT_NODE_NUM=$num;\n\thotspot_t hotspot_info [HOTSPOT_NODE_NUM-1 : 0];\n"; - my $acum=0; - - for (my $i=0;$i<$num;$i++){ - my $w1 = $simulate->object_get_attribute($sample,"HOTSPOT_CORE_$i"); - my $w2 = $simulate->object_get_attribute($sample,"HOTSPOT_PERCENT_$i"); - $w2=$w2*10; - my $w3 = $simulate->object_get_attribute($sample,"HOTSPOT_SEND_EN_$i"); - $hotspot.=",$w1,$w3,$w2"; - $acum+=$w2; - - $hotspot_sv.=" - assign hotspot_info[$i].ip_num=$w1; - assign hotspot_info[$i].send_enable=$w3; - assign hotspot_info[$i].percentage=$acum; // $w2 -"; } - - } - - $hotspot.=" \""; - - } - else{ $hotspot_sv.="localparam HOTSPOT_NODE_NUM = 0;\n\thotspot_t hotspot_info [0:0];\n" } - - my $pck_size; - my $t=$simulate->object_get_attribute($sample,"PCK_SIZ_SEL"); - if($t eq 'random-range' ){ - - $pck_size = "-m \"R,$MIN_PCK_SIZE,$MAX_PCK_SIZE\""; - $discrete_sv="\t localparam DISCRETE_PCK_SIZ_NUM=1; + if ($cast_type ne '"UNICAST"'){ + #$self->object_get_attribute ($sample, "MCAST_TRAFFIC_TYPE"); + my $mr = $simulate->object_get_attribute ($sample, "MCAST_TRAFFIC_RATIO"); + my $mmax = $simulate->object_get_attribute ($sample, "MCAST_PCK_SIZ_MAX"); + my $mmin = $simulate->object_get_attribute ($sample, "MCAST_PCK_SIZ_MIN"); + + $mcast = "-u \"$mr,$mmin,$mmax\""; + $mcast_sv.= "localparam MCAST_TRAFFIC_RATIO = $mr;\n"; + $mcast_sv.= "localparam MCAST_PCK_SIZ_MAX = $mmax;\n"; + $mcast_sv.= "localparam MCAST_PCK_SIZ_MIN = $mmin;\n"; + }else { + $mcast_sv.= "localparam MCAST_TRAFFIC_RATIO = 0;\n"; + $mcast_sv.= "localparam MCAST_PCK_SIZ_MAX = 0;\n"; + $mcast_sv.= "localparam MCAST_PCK_SIZ_MIN = 0;\n"; + } + + + + + + my $classes; + my $num=$simulate->object_get_attribute($sample,"MESSAGE_CLASS"); + $classes.="-p 100" if($num==0); + for (my $i=0;$i<$num;$i++){ + my $w1 = $simulate->object_get_attribute($sample,"CLASS_$i"); + $classes.= ($i==0)? "-p $w1" : ",$w1" ; + + } + + my $discrete_sv=""; + my $hotspot=""; + my $hotspot_sv=""; + if($patern eq "hot spot"){ + $hotspot="-h \" "; + my $num=$simulate->object_get_attribute($sample,"HOTSPOT_NUM"); + if (defined $num){ + $hotspot.=" $num"; + + $hotspot_sv.="localparam HOTSPOT_NODE_NUM=$num;\n\thotspot_t hotspot_info [HOTSPOT_NODE_NUM-1 : 0];\n"; + my $acum=0; + + for (my $i=0;$i<$num;$i++){ + my $w1 = $simulate->object_get_attribute($sample,"HOTSPOT_CORE_$i"); + my $w2 = $simulate->object_get_attribute($sample,"HOTSPOT_PERCENT_$i"); + $w2=$w2*10; + my $w3 = $simulate->object_get_attribute($sample,"HOTSPOT_SEND_EN_$i"); + $hotspot.=",$w1,$w3,$w2"; + $acum+=$w2; + + $hotspot_sv.=" + assign hotspot_info[$i].ip_num=$w1; + assign hotspot_info[$i].send_enable=$w3; + assign hotspot_info[$i].percentage=$acum; // $w2 +"; } + + } + + $hotspot.=" \""; + + } + else{ $hotspot_sv.="localparam HOTSPOT_NODE_NUM = 0;\n\thotspot_t hotspot_info [0:0];\n" } + + my $pck_size; + my $t=$simulate->object_get_attribute($sample,"PCK_SIZ_SEL"); + if($t eq 'random-range' ){ + + $pck_size = "-m \"R,$MIN_PCK_SIZE,$MAX_PCK_SIZE\""; + $discrete_sv="\t localparam DISCRETE_PCK_SIZ_NUM=1; \t rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1:0];\n"; - - }else{ - my $vt=$simulate->object_get_attribute($sample,"DISCRETE_RANGE"); - my $pt=$simulate->object_get_attribute($sample,"PROBEB_RANGE"); - $pck_size = "-m \"D,$vt,P,$pt\""; - my @injects = split(',',$vt); - my @probs = split(',',$pt); - my $i=0; - my $sum=0; - for my $v (@injects) { - $sum+=$probs[$i]; - $discrete_sv.= "\t assign rnd_discrete[$i].value= $v;\n"; - $discrete_sv.= "\t assign rnd_discrete[$i].percentage= $sum;\n"; - $i++; - } - $discrete_sv="\t localparam DISCRETE_PCK_SIZ_NUM=$i; + + }else{ + my $vt=$simulate->object_get_attribute($sample,"DISCRETE_RANGE"); + my $pt=$simulate->object_get_attribute($sample,"PROBEB_RANGE"); + $pck_size = "-m \"D,$vt,P,$pt\""; + my @injects = split(',',$vt); + my @probs = split(',',$pt); + my $i=0; + my $sum=0; + for my $v (@injects) { + $sum+=$probs[$i]; + $discrete_sv.= "\t assign rnd_discrete[$i].value= $v;\n"; + $discrete_sv.= "\t assign rnd_discrete[$i].percentage= $sum;\n"; + $i++; + } + $discrete_sv="\t localparam DISCRETE_PCK_SIZ_NUM=$i; \t rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1: 0];\n".$discrete_sv; - } - - my $modelsim_bin= $ENV{MODELSIM_BIN}; - my $vsim = (! defined $modelsim_bin)? "vsim" : "$modelsim_bin/vsim"; - - - - - my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); - $cpu_num = 1 if (!defined $cpu_num); - - my $thread_num = $simulate->object_get_attribute('compile', 'thread_num'); - $thread_num = 1 if (!defined $thread_num); - - if ($simulator ne 'Verilator'){ - for (my $i=0; $i<$cpu_num; $i++ ){ - my $out="$out_path/modelsim/work$i"; - rmtree("$out"); - mkpath("$out",1,01777); - my $vsim = ($simulator eq 'Modelsim')? "vsim -c": "vsim"; - gen_noc_localparam_v_file($simulate,"$out",$sample); - my $param=" + } + + my $modelsim_bin= $ENV{MODELSIM_BIN}; + my $vsim = (! defined $modelsim_bin)? "vsim" : "$modelsim_bin/vsim"; + + + + + my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); + $cpu_num = 1 if (!defined $cpu_num); + + my $thread_num = $simulate->object_get_attribute('compile', 'thread_num'); + $thread_num = 1 if (!defined $thread_num); + + if ($simulator ne 'Verilator'){ + for (my $i=0; $i<$cpu_num; $i++ ){ + my $out="$out_path/modelsim/work$i"; + rmtree("$out"); + mkpath("$out",1,01777); + my $vsim = ($simulator eq 'Modelsim')? "vsim -c": "vsim"; + gen_noc_localparam_v_file($simulate,"$out",$sample); + my $param=" // simulation parameter setting `ifdef INCLUDE_SIM_PARAM - localparam - TRAFFIC=\"$traffic{$patern}\", - PCK_SIZ_SEL=\"$t\", - AVG_LATENCY_METRIC= \"HEAD_2_TAIL\", - //simulation min and max packet size. The injected packet take a size randomly selected between min and max value - MIN_PACKET_SIZE=$MIN_PCK_SIZE, - MAX_PACKET_SIZE=$MAX_PCK_SIZE, - STOP_PCK_NUM=$PCK_NUM_LIMIT, - STOP_SIM_CLK=$SIM_CLOCK_LIMIT; - - - $hotspot_sv - - $custom_sv - - $mcast_sv - + localparam + TRAFFIC=\"$traffic{$patern}\", + PCK_SIZ_SEL=\"$t\", + AVG_LATENCY_METRIC= \"HEAD_2_TAIL\", + //simulation min and max packet size. The injected packet take a size randomly selected between min and max value + MIN_PACKET_SIZE=$MIN_PCK_SIZE, + MAX_PACKET_SIZE=$MAX_PCK_SIZE, + STOP_PCK_NUM=$PCK_NUM_LIMIT, + STOP_SIM_CLK=$SIM_CLOCK_LIMIT; + + $hotspot_sv + + $custom_sv + + $mcast_sv + $discrete_sv - - parameter INJRATIO=90; -`endif - "; - save_file("$out/sim_param.sv",$param); - - - #Get the list of all verilog files in src_verilog folder - my @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$out_path/modelsim/src_verilog" ); - - #get list of all verilog files in src_sim folder - my @sim_files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$out_path/modelsim/src_modelsim" ); - push (@files, @sim_files); - my $tt =create_file_list("$out_path/modelsim",\@files,'modelsim'); - $tt="+incdir+./ \n$tt"; - save_file("$out/file_list.f", "$tt"); - my $tcl="#!/usr/bin/tclsh + + parameter INJRATIO=90; +`endif + "; + save_file("$out/sim_param.sv",$param); + + + #Get the list of all verilog files in src_verilog folder + my @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$out_path/modelsim/src_verilog" ); + + #get list of all verilog files in src_sim folder + my @sim_files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$out_path/modelsim/src_modelsim" ); + push (@files, @sim_files); + my $tt =create_file_list("$out_path/modelsim",\@files,'modelsim'); + $tt="+incdir+./ \n$tt"; + save_file("$out/file_list.f", "$tt"); + my $tcl="#!/usr/bin/tclsh transcript on if {[file exists rtl_work]} { - vdel -lib rtl_work -all + vdel -lib rtl_work -all } vlib rtl_work vmap work rtl_work @@ -1240,363 +1170,363 @@ sub run_synthetic_simulation { run -all quit "; - - save_file ("$out/model.tcl",$tcl); - - my $cmd="cd $out; rm -Rf rtl_work; $vsim -do $out/model.tcl "; - save_file ("$out/run.sh",'#!/bin/bash'." - sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=\$1/\" $out/sim_param.sv - ".$cmd); - add_info($info, "model.tcl is created in $out\n"); - }#for - } - - - - my @paralel_ratio; - my $total=scalar @ratios; - my $jobs=0; - my $c=0; - my $cmds=""; - - - foreach my $ratio_in (@ratios){ - #my $r= $ratio_in * MAX_RATIO/100; - my $cmd; - - if ($simulator eq 'Modelsim'){ - add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); - my $out="$out_path/modelsim/work$c"; - $cmd=" xterm -e bash -c ' cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -c -do $out/model.tcl -l $out_path/sim_out$ratio_in;' &\n "; - - }elsif ($simulator eq 'Modelsim gui'){ - add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); - my $out="$out_path/modelsim/work$c"; - $cmd="cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -do $out/model.tcl -l $out_path/sim_out$ratio_in; "; - - }else{ - add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); - $cmd="$bin -t \"$patern\" $pck_size -T $thread_num -n $PCK_NUM_LIMIT -c $SIM_CLOCK_LIMIT -i $ratio_in $classes $hotspot $custom $mcast > $out_path/sim_out$ratio_in & "; - - } - $cmds .=$cmd; - add_info($info, "$cmd \n"); - - my $time_strg = localtime; - #append_text_to_file($log,"started at:$time_strg\n"); #save simulation output - $jobs++; - - push (@paralel_ratio,$ratio_in); - $c++; - if($jobs % $cpu_num ==0 || $jobs == $total){ - - #run paralle simulation - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmds\n wait\n"); - if($exit || (length $stderr >4)){ - add_colored_info($info, "Error in running simulation: $stderr \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - #save results - for (my $i=0; $i<$c; $i++){ - my $r = $paralel_ratio[$i]; - - my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); - if (scalar @errors ){ - add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - - my $stdout = load_file("$out_path/sim_out$r"); - - extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); - - - } - - $cmds=""; - @paralel_ratio=(); - $c=0; - - set_gui_status($simulate,"ref",2); - } - - }#@ratios - - $simulate->object_add_attribute ($sample,"status","done"); - + + save_file ("$out/model.tcl",$tcl); + + my $cmd="cd $out; rm -Rf rtl_work; $vsim -do $out/model.tcl "; + save_file ("$out/run.sh",'#!/bin/bash'." + sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=\$1/\" $out/sim_param.sv + ".$cmd); + add_info($info, "model.tcl is created in $out\n"); + }#for + } + + + + my @paralel_ratio; + my $total=scalar @ratios; + my $jobs=0; + my $c=0; + my $cmds=""; + + + foreach my $ratio_in (@ratios){ + #my $r= $ratio_in * MAX_RATIO/100; + my $cmd; + + if ($simulator eq 'Modelsim'){ + add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); + my $out="$out_path/modelsim/work$c"; + $cmd=" xterm -e bash -c ' cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -c -do $out/model.tcl -l $out_path/sim_out$ratio_in;' &\n "; + + }elsif ($simulator eq 'Modelsim gui'){ + add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); + my $out="$out_path/modelsim/work$c"; + $cmd="cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -do $out/model.tcl -l $out_path/sim_out$ratio_in; "; + + }else{ + add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); + $cmd="$bin -t \"$patern\" $pck_size -T $thread_num -n $PCK_NUM_LIMIT -c $SIM_CLOCK_LIMIT -i $ratio_in $classes $hotspot $custom $mcast > $out_path/sim_out$ratio_in & "; + + } + $cmds .=$cmd; + add_info($info, "$cmd \n"); + + my $time_strg = localtime; + #append_text_to_file($log,"started at:$time_strg\n"); #save simulation output + $jobs++; + + push (@paralel_ratio,$ratio_in); + $c++; + if($jobs % $cpu_num ==0 || $jobs == $total){ + + #run paralle simulation + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmds\n wait\n"); + if($exit || (length $stderr >4)){ + add_colored_info($info, "Error in running simulation: $stderr \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; + } + + #save results + for (my $i=0; $i<$c; $i++){ + my $r = $paralel_ratio[$i]; + + my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); + if (scalar @errors ){ + add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; + } + + + my $stdout = load_file("$out_path/sim_out$r"); + + extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); + + + } + + $cmds=""; + @paralel_ratio=(); + $c=0; + + set_gui_status($simulate,"ref",2); + } + + }#@ratios + + $simulate->object_add_attribute ($sample,"status","done"); + } sub extract_st_by_name{ - my($st_name, $stdout)=@_; - - my @results = split($st_name,$stdout); - my %statistcs; - my @lines = split("\n",$results[1]); - my @names; - my $i=0; - foreach my $line (@lines){ - $line=remove_all_white_spaces($line); - $line =~ s/^#//g; #remove # from beginig of each line in modelsim - if($i==0) { - $i++; - next; - } - elsif($i==1){ - #first line is statsitic names - @names=split(",",$line); - $i++; - next; - }elsif(length($line)>1) { - my @fileds=split(",",$line); - my $j=0; - #print ("ff :@fileds\n"); - foreach my $f (@fileds){ - unless($j==0){ - $statistcs{$fileds[0]}{$names[$j]}=$f; - } - $j++; - } - $i++; - }else{ #empty line end of endp statistic - last; - } - - } - #print Dumper(\%statistcs); - return %statistcs; + my($st_name, $stdout)=@_; + + my @results = split($st_name,$stdout); + my %statistcs; + my @lines = split("\n",$results[1]); + my @names; + my $i=0; + foreach my $line (@lines){ + $line=remove_all_white_spaces($line); + $line =~ s/^#//g; #remove # from beginig of each line in modelsim + if($i==0) { + $i++; + next; + } + elsif($i==1){ + #first line is statsitic names + @names=split(",",$line); + $i++; + next; + }elsif(length($line)>1) { + my @fileds=split(",",$line); + my $j=0; + #print ("ff :@fileds\n"); + foreach my $f (@fileds){ + unless($j==0){ + $statistcs{$fileds[0]}{$names[$j]}=$f; + } + $j++; + } + $i++; + }else{ #empty line end of endp statistic + last; + } + + } + #print Dumper(\%statistcs); + return %statistcs; } sub extract_and_update_noc_sim_statistic { - my ($simulate,$sample,$ratio_in,$stdout)=@_; - - - - my $total_time =capture_number_after("Simulation clock cycles:",$stdout); - - my %statistcs = extract_st_by_name("Endpoints Statistics:",$stdout); - - return if (!defined $statistcs{"total"}{'avg_latency_pck'}); - update_result($simulate,$sample,"latency_result",$ratio_in,$statistcs{"total"}{'avg_latency_pck'}); - update_result($simulate,$sample,"latency_flit_result",$ratio_in,$statistcs{"total"}{'avg_latency_flit'}); - update_result($simulate,$sample,"sd_latency_result",$ratio_in,$statistcs{"total"}{'avg.std_dev'}); - update_result($simulate,$sample,"throughput_result",$ratio_in,$statistcs{"total"}{'avg_throughput(%)'}); - update_result($simulate,$sample,"exe_time_result",$ratio_in,$total_time); - update_result($simulate,$sample,"worst_latency_result",$ratio_in,$statistcs{"total"}{'sent_stat.worst_latency'}); - update_result($simulate,$sample,"latency_perhop_result",$ratio_in,$statistcs{"total"}{'avg_latency_per_hop'}); - update_result($simulate,$sample,"min_latency_result",,$ratio_in,$statistcs{"total"}{'sent_stat.min_latency'}); - update_result($simulate,$sample,"injected_pck_total",,$ratio_in,$statistcs{"total"}{'sent_stat.pck_num'}); - update_result($simulate,$sample,"injected_flit_total",,$ratio_in,$statistcs{"total"}{'sent_stat.flit_num'}); - foreach my $p (sort keys %statistcs){ - next unless (is_integer($p)); - update_result($simulate,$sample,"packet_rsvd_result",$ratio_in,$p,$statistcs{$p}{'rsvd_stat.pck_num'}); - update_result($simulate,$sample,"worst_delay_rsvd_result",$ratio_in,$p,$statistcs{$p}{'rsvd_stat.worst_latency'}); - update_result($simulate,$sample,"packet_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.pck_num'} ); - update_result($simulate,$sample,"worst_delay_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.worst_latency'}); - update_result($simulate,$sample,"flit_rsvd_result",$ratio_in,$p,$statistcs{$p}{'rsvd_stat.flit_num'}); - update_result($simulate,$sample,"flit_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.flit_num'}); - } - - my %st1 = extract_st_by_name("Endp_to_Endp flit_num:",$stdout); - update_result($simulate,$sample,"endp-endp-flit_result",$ratio_in,\%st1); - - my %st2 = extract_st_by_name("Endp_to_Endp pck_num:",$stdout); - update_result($simulate,$sample,"endp-endp-pck_result",$ratio_in,\%st2); - - my %st3 = extract_st_by_name("Routers' statistics:",$stdout); - foreach my $p (sort keys %st3){ - update_result($simulate,$sample,"flit_per_router_result",$ratio_in,$p,$st3{$p}{'flit_in'}); - update_result($simulate,$sample,"packet_per_router_result",$ratio_in,$p,$st3{$p}{'pck_in'}); - my $tmp= ($st3{$p}{'flit_in'}==0)? 0 : ($st3{$p}{'flit_in_buffered'}*100) / $st3{$p}{'flit_in'}; - #print " $tmp= ($st3{$p}{'flit_in_buffered'}*100) / $st3{$p}{'flit_in'};\n"; - update_result($simulate,$sample,"flit_buffered_router_ratio",$ratio_in,$p,$tmp); - $tmp= ($st3{$p}{'flit_in'}==0)? 0 : ($st3{$p}{'flit_in_bypassed'}*100) / $st3{$p}{'flit_in'}; - update_result($simulate,$sample,"flit_bypass_router_ratio",$ratio_in,$p,$tmp); - - } - - #my $p= $simulate->object_get_attribute ($sample,"noc_info"); + my ($simulate,$sample,$ratio_in,$stdout)=@_; + + + + my $total_time =capture_number_after("Simulation clock cycles:",$stdout); + + my %statistcs = extract_st_by_name("Endpoints Statistics:",$stdout); + + return if (!defined $statistcs{"total"}{'avg_latency_pck'}); + update_result($simulate,$sample,"latency_result",$ratio_in,$statistcs{"total"}{'avg_latency_pck'}); + update_result($simulate,$sample,"latency_flit_result",$ratio_in,$statistcs{"total"}{'avg_latency_flit'}); + update_result($simulate,$sample,"sd_latency_result",$ratio_in,$statistcs{"total"}{'avg.std_dev'}); + update_result($simulate,$sample,"throughput_result",$ratio_in,$statistcs{"total"}{'avg_throughput(%)'}); + update_result($simulate,$sample,"exe_time_result",$ratio_in,$total_time); + update_result($simulate,$sample,"worst_latency_result",$ratio_in,$statistcs{"total"}{'sent_stat.worst_latency'}); + update_result($simulate,$sample,"latency_perhop_result",$ratio_in,$statistcs{"total"}{'avg_latency_per_hop'}); + update_result($simulate,$sample,"min_latency_result",,$ratio_in,$statistcs{"total"}{'sent_stat.min_latency'}); + update_result($simulate,$sample,"injected_pck_total",,$ratio_in,$statistcs{"total"}{'sent_stat.pck_num'}); + update_result($simulate,$sample,"injected_flit_total",,$ratio_in,$statistcs{"total"}{'sent_stat.flit_num'}); + foreach my $p (sort keys %statistcs){ + next unless (is_integer($p)); + update_result($simulate,$sample,"packet_rsvd_result",$ratio_in,$p,$statistcs{$p}{'rsvd_stat.pck_num'}); + update_result($simulate,$sample,"worst_delay_rsvd_result",$ratio_in,$p,$statistcs{$p}{'rsvd_stat.worst_latency'}); + update_result($simulate,$sample,"packet_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.pck_num'} ); + update_result($simulate,$sample,"worst_delay_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.worst_latency'}); + update_result($simulate,$sample,"flit_rsvd_result",$ratio_in,$p,$statistcs{$p}{'rsvd_stat.flit_num'}); + update_result($simulate,$sample,"flit_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.flit_num'}); + } + + my %st1 = extract_st_by_name("Endp_to_Endp flit_num:",$stdout); + update_result($simulate,$sample,"endp-endp-flit_result",$ratio_in,\%st1); + + my %st2 = extract_st_by_name("Endp_to_Endp pck_num:",$stdout); + update_result($simulate,$sample,"endp-endp-pck_result",$ratio_in,\%st2); + + my %st3 = extract_st_by_name("Routers' statistics:",$stdout); + foreach my $p (sort keys %st3){ + update_result($simulate,$sample,"flit_per_router_result",$ratio_in,$p,$st3{$p}{'flit_in'}); + update_result($simulate,$sample,"packet_per_router_result",$ratio_in,$p,$st3{$p}{'pck_in'}); + my $tmp= ($st3{$p}{'flit_in'}==0)? 0 : ($st3{$p}{'flit_in_buffered'}*100) / $st3{$p}{'flit_in'}; + #print " $tmp= ($st3{$p}{'flit_in_buffered'}*100) / $st3{$p}{'flit_in'};\n"; + update_result($simulate,$sample,"flit_buffered_router_ratio",$ratio_in,$p,$tmp); + $tmp= ($st3{$p}{'flit_in'}==0)? 0 : ($st3{$p}{'flit_in_bypassed'}*100) / $st3{$p}{'flit_in'}; + update_result($simulate,$sample,"flit_bypass_router_ratio",$ratio_in,$p,$tmp); + + } + + #my $p= $simulate->object_get_attribute ($sample,"noc_info"); # my $TOPOLOGY=$p->{"TOPOLOGY"}; - #print "$TOPOLOGY\n"; - - + #print "$TOPOLOGY\n"; + + } sub run_task_simulation{ - my ($simulate,$info,$sample,$name)=@_; - my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; - my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); - - my $bin=get_sim_bin_path($simulate,$sample,$info); - - my $dir = Cwd::getcwd(); - my $project_dir = abs_path("$dir/../.."); #mpsoc directory address - $bin= "$project_dir/$bin" if(!(-f $bin)); - my $num=$simulate->object_get_attribute($sample,"TRAFFIC_FILE_NUM"); - - my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); - $cpu_num = 1 if (!defined $cpu_num); - - my @paralel_ratio; - my $total=$num; - my $jobs=0; - my $c=0; - my $cmds=""; - my $out_path ="$ENV{PRONOC_WORK}/simulate/"; - - for (my $i=0; $i<$num; $i++){ - my $f=$simulate->object_get_attribute($sample,"traffic_file$i"); - add_info($info, "Run $bin for $f file \n"); - my $cmd="$bin -c $SIM_CLOCK_LIMIT -f \"$f\" > $out_path/sim_out$i & "; - $cmds .=$cmd; - add_info($info, "$cmd \n"); - $jobs++; - push (@paralel_ratio,$i); - $c++; - if($jobs % $cpu_num ==0 || $jobs == $total){ - #run paralle simulation - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmds\n wait\n"); - #print "($stdout,$exit,$stderr)\n"; - if($exit || (length $stderr >4)){ - add_colored_info($info, "Error in running simulation: $stderr \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - - - - #save results - for (my $j=0; $j<$c; $j++){ - my $r = $paralel_ratio[$j]; - my $stdout = load_file("$out_path/sim_out$r"); - my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); - if (scalar @errors ){ - add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); - } - - $cmds=""; - @paralel_ratio=(); - $c=0; - set_gui_status($simulate,"ref",2); - } - - }#for i - - $simulate->object_add_attribute ($sample,"status","done"); -} + my ($simulate,$info,$sample,$name)=@_; + my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; + my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); + + my $bin=get_sim_bin_path($simulate,$sample,$info); + + my $dir = Cwd::getcwd(); + my $project_dir = abs_path("$dir/../.."); #mpsoc directory address + $bin= "$project_dir/$bin" if(!(-f $bin)); + my $num=$simulate->object_get_attribute($sample,"TRAFFIC_FILE_NUM"); + + my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); + $cpu_num = 1 if (!defined $cpu_num); + + my @paralel_ratio; + my $total=$num; + my $jobs=0; + my $c=0; + my $cmds=""; + my $out_path ="$ENV{PRONOC_WORK}/simulate/"; + + for (my $i=0; $i<$num; $i++){ + my $f=$simulate->object_get_attribute($sample,"traffic_file$i"); + add_info($info, "Run $bin for $f file \n"); + my $cmd="$bin -c $SIM_CLOCK_LIMIT -f \"$f\" > $out_path/sim_out$i & "; + $cmds .=$cmd; + add_info($info, "$cmd \n"); + $jobs++; + push (@paralel_ratio,$i); + $c++; + if($jobs % $cpu_num ==0 || $jobs == $total){ + #run paralle simulation + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmds\n wait\n"); + #print "($stdout,$exit,$stderr)\n"; + if($exit || (length $stderr >4)){ + add_colored_info($info, "Error in running simulation: $stderr \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; + } + + + + + #save results + for (my $j=0; $j<$c; $j++){ + my $r = $paralel_ratio[$j]; + my $stdout = load_file("$out_path/sim_out$r"); + my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); + if (scalar @errors ){ + add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; + } + + extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); + } + + $cmds=""; + @paralel_ratio=(); + $c=0; + set_gui_status($simulate,"ref",2); + } + + }#for i + + $simulate->object_add_attribute ($sample,"status","done"); +} sub run_trace_simulation{ - my ($simulate,$info,$sample,$name)=@_; - my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; - - - my $bin=get_sim_bin_path($simulate,$sample,$info); - - - my $project_dir = get_project_dir(); - $bin= "$project_dir/$bin" if(!(-f $bin)); - - - my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); - $cpu_num = 1 if (!defined $cpu_num); - - my @paralel_ratio; - - my $jobs=0; - my $c=0; - my $cmds=""; - my $out_path ="$ENV{PRONOC_WORK}/simulate/"; - my $thread_num = $simulate->object_get_attribute('compile', 'thread_num'); - $thread_num = 1 if (!defined $thread_num); - - my $model= $simulate->object_get_attribute($sample,'MODEL_NAME'); - - add_info($info, "Run $bin for $model model \n"); - - my $cmd="$bin -T $thread_num "; - my $traffictype=$simulate->object_get_attribute($sample,"TRAFFIC_TYPE"); - if($traffictype eq "Netrace"){ - my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); - my $IGNORE_DPNDCY=$simulate->object_get_attribute ($sample,"IGNORE_DPNDCY"); - my $READER_THRL=$simulate->object_get_attribute ($sample,"READER_THRL"); - my $START_RGN=$simulate->object_get_attribute ($sample,"START_RGN"); - my $SPEED_UP=$simulate->object_get_attribute ($sample,"SPEED_UP"); - - my $models_dir = "$ENV{PRONOC_WORK}/simulate/netrace"; - - $cmd .="-F $models_dir/$model.bz2 -n $PCK_NUM_LIMIT -r $START_RGN -v 0 -s $SPEED_UP"; - $cmd .=" -l " if ($READER_THRL eq "1\'b1" ); - $cmd .=" -d " if ($IGNORE_DPNDCY eq "1\'b1"); - - - - - - }else{#synful - my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); - my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); - my $RND_SEED=$simulate->object_get_attribute ($sample,"RND_SEED"); - my $EXIT_STEADY=$simulate->object_get_attribute ($sample,"EXIT_STEADY"); - my $FLITw=$simulate->object_get_attribute ($sample,"SYNFUL_FLITw"); - - - my $models_dir = get_project_dir()."/mpsoc/src_c/synfull/generated-models/"; - $cmd .=" -S $models_dir/$model.model -n $PCK_NUM_LIMIT -r $RND_SEED -c $SIM_CLOCK_LIMIT -v 0 -w $FLITw"; - $cmd .=" -s " if ($EXIT_STEADY eq "1\'b1"); - - - - } - $cmd .=" > $out_path/sim_out"; - add_info($info, "$cmd \n"); - - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmd\n wait\n"); - if($exit || (length $stderr >4)){ - add_colored_info($info, "Error in running simulation: $stderr \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - - - $stdout = load_file("$out_path/sim_out"); - my @errors = unix_grep("$out_path/sim_out","ERROR:"); - if (scalar @errors ){ - add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - extract_and_update_noc_sim_statistic ($simulate,$sample,0,$stdout); - - - set_gui_status($simulate,"ref",2); - - - $simulate->object_add_attribute ($sample,"status","done"); -} + my ($simulate,$info,$sample,$name)=@_; + my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; + + + my $bin=get_sim_bin_path($simulate,$sample,$info); + + + my $project_dir = get_project_dir(); + $bin= "$project_dir/$bin" if(!(-f $bin)); + + + my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); + $cpu_num = 1 if (!defined $cpu_num); + + my @paralel_ratio; + + my $jobs=0; + my $c=0; + my $cmds=""; + my $out_path ="$ENV{PRONOC_WORK}/simulate/"; + my $thread_num = $simulate->object_get_attribute('compile', 'thread_num'); + $thread_num = 1 if (!defined $thread_num); + + my $model= $simulate->object_get_attribute($sample,'MODEL_NAME'); + + add_info($info, "Run $bin for $model model \n"); + + my $cmd="$bin -T $thread_num "; + my $traffictype=$simulate->object_get_attribute($sample,"TRAFFIC_TYPE"); + if($traffictype eq "Netrace"){ + my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); + my $IGNORE_DPNDCY=$simulate->object_get_attribute ($sample,"IGNORE_DPNDCY"); + my $READER_THRL=$simulate->object_get_attribute ($sample,"READER_THRL"); + my $START_RGN=$simulate->object_get_attribute ($sample,"START_RGN"); + my $SPEED_UP=$simulate->object_get_attribute ($sample,"SPEED_UP"); + + my $models_dir = "$ENV{PRONOC_WORK}/simulate/netrace"; + + $cmd .="-F $models_dir/$model.bz2 -n $PCK_NUM_LIMIT -r $START_RGN -v 0 -s $SPEED_UP"; + $cmd .=" -l " if ($READER_THRL eq "1\'b1" ); + $cmd .=" -d " if ($IGNORE_DPNDCY eq "1\'b1"); + + + + + + }else{#synful + my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); + my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); + my $RND_SEED=$simulate->object_get_attribute ($sample,"RND_SEED"); + my $EXIT_STEADY=$simulate->object_get_attribute ($sample,"EXIT_STEADY"); + my $FLITw=$simulate->object_get_attribute ($sample,"SYNFUL_FLITw"); + + + my $models_dir = get_project_dir()."/mpsoc/src_c/synfull/generated-models/"; + $cmd .=" -S $models_dir/$model.model -n $PCK_NUM_LIMIT -r $RND_SEED -c $SIM_CLOCK_LIMIT -v 0 -w $FLITw"; + $cmd .=" -s " if ($EXIT_STEADY eq "1\'b1"); + + + + } + $cmd .=" > $out_path/sim_out"; + add_info($info, "$cmd \n"); + + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmd\n wait\n"); + if($exit || (length $stderr >4)){ + add_colored_info($info, "Error in running simulation: $stderr \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; + } + + + + $stdout = load_file("$out_path/sim_out"); + my @errors = unix_grep("$out_path/sim_out","ERROR:"); + if (scalar @errors ){ + add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; + } + + extract_and_update_noc_sim_statistic ($simulate,$sample,0,$stdout); + + + set_gui_status($simulate,"ref",2); + + + $simulate->object_add_attribute ($sample,"status","done"); +} @@ -1606,158 +1536,158 @@ sub run_trace_simulation{ ########## sub get_sim_bin_path { - my ($self,$sample,$info)=@_; - my $bin_path=$self->object_get_attribute ($sample,"sof_path"); - unless (-d $bin_path){ - my $path= $self->object_get_attribute ("sim_param","BIN_DIR"); - if(-d $path){ - add_colored_info($info, "Warning: The given path ($bin_path) for searching $sample bin file does not exist. The system search in default $path instead.\n",'green'); - $bin_path=$path; - } - } - my $bin_file=$self->object_get_attribute ($sample,"sof_file"); - $bin_file = "-" if(!defined $bin_file); - my $sof="$bin_path/$bin_file"; - return $sof; + my ($self,$sample,$info)=@_; + my $bin_path=$self->object_get_attribute ($sample,"sof_path"); + unless (-d $bin_path){ + my $path= $self->object_get_attribute ("sim_param","BIN_DIR"); + if(-d $path){ + add_colored_info($info, "Warning: The given path ($bin_path) for searching $sample bin file does not exist. The system search in default $path instead.\n",'green'); + $bin_path=$path; + } + } + my $bin_file=$self->object_get_attribute ($sample,"sof_file"); + $bin_file = "-" if(!defined $bin_file); + my $sof="$bin_path/$bin_file"; + return $sof; } sub check_sim_sample{ - my ($self,$sample,$info)=@_; - my $status=1; - my $sof=get_sim_bin_path($self,$sample,$info); - - # ckeck if sample have sof file - if(!defined $sof){ - add_colored_info($info, "Error: bin file has not set for $sample!\n",'red'); - $self->object_add_attribute ($sample,"status","failed"); - $status=0; - } else { - # ckeck if bin file has info file - my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); - my $sof_info= "$path$name.inf"; - if(!(-f $sof_info)){ - add_colored_info($info, "Could not find $name.inf file in $path. An information file is required for each sof file containing the device name and NoC configuration. Press F3 for more help.\n",'red'); - $self->object_add_attribute ($sample,"status","failed"); - $status=0; - }else { #add info - my $pp= do $sof_info ; - - my $p=$pp->{'noc_param'}; - - $status=0 if $@; - message_dialog("Error reading: $@") if $@; - if ($status==1){ - $self->object_add_attribute ($sample,"noc_info",$p) ; - - - } - } - } - #check if sample min packet size matches in simulation - - my $p= $self->object_get_attribute ($sample,"noc_info"); + my ($self,$sample,$info)=@_; + my $status=1; + my $sof=get_sim_bin_path($self,$sample,$info); + + # ckeck if sample have sof file + if(!defined $sof){ + add_colored_info($info, "Error: bin file has not set for $sample!\n",'red'); + $self->object_add_attribute ($sample,"status","failed"); + $status=0; + } else { + # ckeck if bin file has info file + my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); + my $sof_info= "$path$name.inf"; + if(!(-f $sof_info)){ + add_colored_info($info, "Could not find $name.inf file in $path. An information file is required for each sof file containing the device name and NoC configuration. Press F3 for more help.\n",'red'); + $self->object_add_attribute ($sample,"status","failed"); + $status=0; + }else { #add info + my $pp= do $sof_info ; + + my $p=$pp->{'noc_param'}; + + $status=0 if $@; + message_dialog("Error reading: $@") if $@; + if ($status==1){ + $self->object_add_attribute ($sample,"noc_info",$p) ; + + + } + } + } + #check if sample min packet size matches in simulation + + my $p= $self->object_get_attribute ($sample,"noc_info"); my $HW_MIN_PCK_SIZE=$p->{"MIN_PCK_SIZE"}; my $HW_PCK_TYPE=$p->{"PCK_TYPE"}; my $SIM_MIN_PCK_SIZE=$self->object_get_attribute ($sample,"MIN_PCK_SIZE"); my $SIM_MAX_PCK_SIZE=$self->object_get_attribute ($sample,"MAX_PCK_SIZE"); if(!defined $HW_MIN_PCK_SIZE){ - $HW_MIN_PCK_SIZE= 2; - #print "undef\n"; + $HW_MIN_PCK_SIZE= 2; + #print "undef\n"; } $HW_PCK_TYPE = "MULTI_FLIT" if(~defined $HW_PCK_TYPE); - if($HW_MIN_PCK_SIZE>$SIM_MIN_PCK_SIZE){ - add_colored_info($info, "Error: The minimum simulation packet size of $SIM_MIN_PCK_SIZE flit(s) is smaller than $HW_MIN_PCK_SIZE which is defined in generating verilog model of NoC!\n",'red'); - $self->object_add_attribute ($sample,"status","failed"); - $status=0; - } - if( $HW_PCK_TYPE eq '"SINGLE_FLIT"' && $SIM_MAX_PCK_SIZE !=1){ - #print "$HW_PCK_TYPE \n"; - add_colored_info($info, "Error: The maximum packet size is set as $SIM_MAX_PCK_SIZE however, the selected NoC model only support single-flit packet injection! Please redefine it to one\n",'red'); - - $self->object_add_attribute ($sample,"status","failed"); - $status=0; - } - - return $status; + if($HW_MIN_PCK_SIZE>$SIM_MIN_PCK_SIZE){ + add_colored_info($info, "Error: The minimum simulation packet size of $SIM_MIN_PCK_SIZE flit(s) is smaller than $HW_MIN_PCK_SIZE which is defined in generating verilog model of NoC!\n",'red'); + $self->object_add_attribute ($sample,"status","failed"); + $status=0; + } + if( $HW_PCK_TYPE eq '"SINGLE_FLIT"' && $SIM_MAX_PCK_SIZE !=1){ + #print "$HW_PCK_TYPE \n"; + add_colored_info($info, "Error: The maximum packet size is set as $SIM_MAX_PCK_SIZE however, the selected NoC model only support single-flit packet injection! Please redefine it to one\n",'red'); + + $self->object_add_attribute ($sample,"status","failed"); + $status=0; + } + + return $status; } sub noc_sim_ctrl{ - my ($simulate,$info)=@_; - - my $generate = def_image_button('icons/forward.png','R_un all',FALSE,1); - my $open = def_image_button('icons/browse.png',"_Load",FALSE,1); - my $save = def_image_button('icons/save.png','Sav_e',FALSE,1); - my $save_all_results = def_image_button('icons/copy.png',"E_xtract all results",FALSE,1); - my $cpus=select_parallel_process_num($simulate); - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - - my $compiler =def_pack_hbox('FALSE',0, gen_label_in_center('Simulator:'), gen_combobox_object($simulate,'Simulator',undef,"Modelsim gui,Modelsim,Verilator","Verilator",'ref',1)); - - - my $entry = gen_entry_object($simulate,'simulate_name',undef,undef,undef,undef); - my $entrybox=gen_label_info(" Save as:",$entry); - $entrybox->pack_start( $save, FALSE, FALSE, 0); - - my $simulator =$simulate->object_get_attribute("Simulator"); - - - my $thread=select_parallel_thread_num($simulate); - - - my $table = def_table (1, 12, FALSE); - $table->attach ($open, 0, 1, 0,1,'expand','shrink',2,2); - $table->attach ($compiler, 1, 2, 0,1,'expand','shrink',2,2); - - $table->attach ($cpus, 2, 4, 0,1,'expand','shrink',2,2); - if($simulator eq "Verilator"){ - $table->attach ($thread, 4, 5, 0,1,'expand','shrink',2,2); - } - - $table->attach ($entrybox, 5, 7, 0,1,'expand','shrink',2,2); - $table->attach ($save_all_results, 7, 8, 0,1,'shrink','shrink',2,2); - $table->attach ($generate, 8, 9, 0,1,'expand','shrink',2,2); - - $generate-> signal_connect("clicked" => sub{ - my @samples =$simulate->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - $simulate->object_add_attribute ("$sample","status","run"); - } - run_simulator($simulate,$info); - #set_gui_status($emulate,"ideal",2); - - }); - -# $wb-> signal_connect("clicked" => sub{ -# wb_address_setting($mpsoc); -# -# }); - - $open-> signal_connect("clicked" => sub{ - - load_simulation($simulate,$info); - #print Dumper($simulate); - set_gui_status($simulate,"ref",5); - - }); - - $save-> signal_connect("clicked" => sub{ - save_simulation($simulate); - set_gui_status($simulate,"ref",5); - - - }); - - $save_all_results-> signal_connect("clicked" => sub{ - #Get the path where to save all the simulation results - my $open_in = $simulate->object_get_attribute ('sim_param','BIN_DIR'); - get_dir_name($simulate,"Select the target directory","sim_param","ALL_RESULT_DIR",$open_in,'ref',1); - $simulate->object_add_attribute ("graph_save","save_all_result",1); - - }); - - - return add_widget_to_scrolled_win($table,gen_scr_win_with_adjst($simulate,"ctrl_sc_win")); - + my ($simulate,$info)=@_; + + my $generate = def_image_button('icons/forward.png','R_un all',FALSE,1); + my $open = def_image_button('icons/browse.png',"_Load",FALSE,1); + my $save = def_image_button('icons/save.png','Sav_e',FALSE,1); + my $save_all_results = def_image_button('icons/copy.png',"E_xtract all results",FALSE,1); + my $cpus=select_parallel_process_num($simulate); + my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; + + my $compiler =def_pack_hbox('FALSE',0, gen_label_in_center('Simulator:'), gen_combobox_object($simulate,'Simulator',undef,"Modelsim gui,Modelsim,Verilator","Verilator",'ref',1)); + + + my $entry = gen_entry_object($simulate,'simulate_name',undef,undef,undef,undef); + my $entrybox=gen_label_info(" Save as:",$entry); + $entrybox->pack_start( $save, FALSE, FALSE, 0); + + my $simulator =$simulate->object_get_attribute("Simulator"); + + + my $thread=select_parallel_thread_num($simulate); + + + my $table = def_table (1, 12, FALSE); + $table->attach ($open, 0, 1, 0,1,'expand','shrink',2,2); + $table->attach ($compiler, 1, 2, 0,1,'expand','shrink',2,2); + + $table->attach ($cpus, 2, 4, 0,1,'expand','shrink',2,2); + if($simulator eq "Verilator"){ + $table->attach ($thread, 4, 5, 0,1,'expand','shrink',2,2); + } + + $table->attach ($entrybox, 5, 7, 0,1,'expand','shrink',2,2); + $table->attach ($save_all_results, 7, 8, 0,1,'shrink','shrink',2,2); + $table->attach ($generate, 8, 9, 0,1,'expand','shrink',2,2); + + $generate-> signal_connect("clicked" => sub{ + my @samples =$simulate->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + $simulate->object_add_attribute ("$sample","status","run"); + } + run_simulator($simulate,$info); + #set_gui_status($emulate,"ideal",2); + + }); + +# $wb-> signal_connect("clicked" => sub{ +# wb_address_setting($mpsoc); +# +# }); + + $open-> signal_connect("clicked" => sub{ + + load_simulation($simulate,$info); + #print Dumper($simulate); + set_gui_status($simulate,"ref",5); + + }); + + $save-> signal_connect("clicked" => sub{ + save_simulation($simulate); + set_gui_status($simulate,"ref",5); + + + }); + + $save_all_results-> signal_connect("clicked" => sub{ + #Get the path where to save all the simulation results + my $open_in = $simulate->object_get_attribute ('sim_param','BIN_DIR'); + get_dir_name($simulate,"Select the target directory","sim_param","ALL_RESULT_DIR",$open_in,'ref',1); + $simulate->object_add_attribute ("graph_save","save_all_result",1); + + }); + + + return add_widget_to_scrolled_win($table,gen_scr_win_with_adjst($simulate,"ctrl_sc_win")); + } @@ -1765,182 +1695,182 @@ sub noc_sim_ctrl{ # main ############ sub simulator_main{ - - add_color_to_gd(); - my $simulate= emulator->emulator_new(); - set_gui_status($simulate,"ideal",0); - - - my $main_table = def_table (25, 12, FALSE); - $main_table->show_all; - my ($infobox,$info)= create_txview(); - - + + add_color_to_gd(); + my $simulate= emulator->emulator_new(); + set_gui_status($simulate,"ideal",0); + + + my $main_table = def_table (25, 12, FALSE); + $main_table->show_all; + my ($infobox,$info)= create_txview(); + + my @pages =( - {page_name=>" Average/Total ", page_num=>0}, - {page_name=>" Per node ", page_num=>1}, - #{page_name=>" Worst-Case Delay ",page_num=>2}, - #{page_name=>" Execution Time ",page_num=>3}, - {page_name=>" Heat-Map. ",page_num=>4}, + {page_name=>" Average/Total ", page_num=>0}, + {page_name=>" Per node ", page_num=>1}, + #{page_name=>" Worst-Case Delay ",page_num=>2}, + #{page_name=>" Execution Time ",page_num=>3}, + {page_name=>" Heat-Map. ",page_num=>4}, ); my @charts = ( - { type=>"2D_line", page_num=>0, graph_name=> "Avg. packet Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Packet Latency (clock)', Z_Title=>undef, Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency", result_name => "latency_flit_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency (clock)', Z_Title=>undef, Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency per hop", result_name => "latency_perhop_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency per hop (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Avg. packet Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Packet Latency (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency", result_name => "latency_flit_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency per hop", result_name => "latency_perhop_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency per hop (clock)', Z_Title=>undef, Y_Max=>100}, { type=>"2D_line", page_num=>0, graph_name=> "Avg. throughput", result_name => "throughput_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Throughput (flits/clock (%))', Z_Title=>undef,Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Avg. SD latency", result_name => "sd_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Latency Standard Deviation (clock)', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Worst pck latency (clk)", result_name => "worst_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Worst Packet Latency (clock)', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Min pck latency (clk)", result_name => "min_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Minimum Packet Latency (clock)', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Total injected pck", result_name =>"injected_pck_total" , X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected packets', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Total injected flit",result_name =>"injected_flit_total", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected Fslits', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Execuation Cycles", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Simulation Time (clk)', Z_Title=>undef}, - - - - { type=>"3D_bar", page_num=>1, graph_name=> "Received packets per Endp", result_name => "packet_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Packets Per Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Sent packets per Endp", result_name => "packet_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Per Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Received flits per Endp", result_name => "flit_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Flits Per Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Sent flits per Endp", result_name => "flit_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Flits Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Flits per Router", result_name => "flit_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Flits Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Packets per Router", result_name => "packet_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Worst Received pck latency per Endp", result_name => "worst_delay_rsvd_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Worst Sent pck latency per Endp", result_name => "worst_delay_sent_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, - - { type=>"3D_bar", page_num=>1, graph_name=> "Buffered Flit in Ratio Per Router", result_name => "flit_buffered_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in buffered in router/Flit in (%)', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Bypassed Flit in Ratio Per Router", result_name => "flit_bypass_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in bypassed in router/Flit in (%)', Z_Title=>undef}, - - - - - - - - - - - - - { type=>"Heat-map", page_num=>4, graph_name=> "Select", result_name => "undef",X_Title=>'-' , Y_Title=> undef, Z_Title=>undef}, - { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Flit-num", result_name => "endp-endp-flit_result",X_Title=>'total flit number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, - { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Packet-num", result_name => "endp-endp-pck_result",X_Title=>'total packet number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, - - - ); - - - my ($conf_box,$set_win)=process_notebook_gen($simulate,$info,"simulate",undef,@charts); - my $chart =gen_multiple_charts ($simulate,\@pages,\@charts,0.4); - - - - $main_table->set_row_spacings (4); - $main_table->set_col_spacings (1); - - - #my $device_win=show_active_dev($soc,$soc,$infc,$soc_state,\$refresh,$info); - - - - - my $image = get_status_gif($simulate); - my $ctrl = noc_sim_ctrl ($simulate,$info); - - my $v1=gen_vpaned($conf_box,.45,$image); - my $v2=gen_vpaned($infobox,.2,$chart); - my $h1=gen_hpaned($v1,.4,$v2); - - - - $main_table->attach_defaults ($h1 , 0, 12, 0,24); - $main_table->attach ($ctrl, 0,12, 24,25,'fill','fill',2,2); - - my $sc_win=add_widget_to_scrolled_win($main_table); - - - #check soc status every 0.5 second. refresh device table if there is any changes - Glib::Timeout->add (100, sub{ - - my ($state,$timeout)= get_gui_status($simulate); - - if ($timeout>0){ - $timeout--; - set_gui_status($simulate,$state,$timeout); - return TRUE; - - } - if($state eq "ideal"){ - return TRUE; - - } - - - - #refresh GUI - - - $ctrl->destroy(); - $conf_box->destroy(); - $chart->destroy(); - $image->destroy(); - $image = get_status_gif($simulate); - ($conf_box,$set_win)=process_notebook_gen($simulate,$info,"simulate",$set_win,@charts); - $chart = gen_multiple_charts ($simulate,\@pages,\@charts,0.4); - $ctrl = noc_sim_ctrl ($simulate,$info); - $main_table->attach ($ctrl,0, 12, 24,25,'fill','fill',2,2); - $v1 -> pack1($conf_box, TRUE, TRUE); - $v1 -> pack2($image, TRUE, TRUE); - $v2 -> pack2($chart, TRUE, TRUE); - - - - - $conf_box->show_all(); - $main_table->show_all(); - set_gui_status($simulate,"ideal",0); - - - return TRUE; - - } ); - - - - - - - return $sc_win; - - + { type=>"2D_line", page_num=>0, graph_name=> "Avg. SD latency", result_name => "sd_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Latency Standard Deviation (clock)', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Worst pck latency (clk)", result_name => "worst_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Worst Packet Latency (clock)', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Min pck latency (clk)", result_name => "min_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Minimum Packet Latency (clock)', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Total injected pck", result_name =>"injected_pck_total" , X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected packets', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Total injected flit",result_name =>"injected_flit_total", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected Fslits', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Execuation Cycles", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Simulation Time (clk)', Z_Title=>undef}, + + + + { type=>"3D_bar", page_num=>1, graph_name=> "Received packets per Endp", result_name => "packet_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Packets Per Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Sent packets per Endp", result_name => "packet_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Per Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Received flits per Endp", result_name => "flit_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Flits Per Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Sent flits per Endp", result_name => "flit_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Flits Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Flits per Router", result_name => "flit_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Flits Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Packets per Router", result_name => "packet_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Worst Received pck latency per Endp", result_name => "worst_delay_rsvd_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Worst Sent pck latency per Endp", result_name => "worst_delay_sent_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, + + { type=>"3D_bar", page_num=>1, graph_name=> "Buffered Flit in Ratio Per Router", result_name => "flit_buffered_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in buffered in router/Flit in (%)', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Bypassed Flit in Ratio Per Router", result_name => "flit_bypass_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in bypassed in router/Flit in (%)', Z_Title=>undef}, + + + + + + + + + + + + + { type=>"Heat-map", page_num=>4, graph_name=> "Select", result_name => "undef",X_Title=>'-' , Y_Title=> undef, Z_Title=>undef}, + { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Flit-num", result_name => "endp-endp-flit_result",X_Title=>'total flit number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, + { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Packet-num", result_name => "endp-endp-pck_result",X_Title=>'total packet number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, + + + ); + + + my ($conf_box,$set_win)=process_notebook_gen($simulate,$info,"simulate",undef,@charts); + my $chart =gen_multiple_charts ($simulate,\@pages,\@charts,0.4); + + + + $main_table->set_row_spacings (4); + $main_table->set_col_spacings (1); + + + #my $device_win=show_active_dev($soc,$soc,$infc,$soc_state,\$refresh,$info); + + + + + my $image = get_status_gif($simulate); + my $ctrl = noc_sim_ctrl ($simulate,$info); + + my $v1=gen_vpaned($conf_box,.45,$image); + my $v2=gen_vpaned($infobox,.2,$chart); + my $h1=gen_hpaned($v1,.4,$v2); + + + + $main_table->attach_defaults ($h1 , 0, 12, 0,24); + $main_table->attach ($ctrl, 0,12, 24,25,'fill','fill',2,2); + + my $sc_win=add_widget_to_scrolled_win($main_table); + + + #check soc status every 0.5 second. refresh device table if there is any changes + Glib::Timeout->add (100, sub{ + + my ($state,$timeout)= get_gui_status($simulate); + + if ($timeout>0){ + $timeout--; + set_gui_status($simulate,$state,$timeout); + return TRUE; + + } + if($state eq "ideal"){ + return TRUE; + + } + + + + #refresh GUI + + + $ctrl->destroy(); + $conf_box->destroy(); + $chart->destroy(); + $image->destroy(); + $image = get_status_gif($simulate); + ($conf_box,$set_win)=process_notebook_gen($simulate,$info,"simulate",$set_win,@charts); + $chart = gen_multiple_charts ($simulate,\@pages,\@charts,0.4); + $ctrl = noc_sim_ctrl ($simulate,$info); + $main_table->attach ($ctrl,0, 12, 24,25,'fill','fill',2,2); + $v1 -> pack1($conf_box, TRUE, TRUE); + $v1 -> pack2($image, TRUE, TRUE); + $v2 -> pack2($chart, TRUE, TRUE); + + + + + $conf_box->show_all(); + $main_table->show_all(); + set_gui_status($simulate,"ideal",0); + + + return TRUE; + + } ); + + + + + + + return $sc_win; + + } sub custom_traffic_dest{ - my ($self,$sample,$core_num) =@_; - - my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); + my ($self,$sample,$core_num) =@_; + + my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); for (my $i=0;$i<$num;$i++){ - my $src = $self->object_get_attribute($sample,"SRC_$i"); - my $dst = $self->object_get_attribute($sample,"DST_$i"); - return ($core_num,$dst) if($src == $core_num); + my $src = $self->object_get_attribute($sample,"SRC_$i"); + my $dst = $self->object_get_attribute($sample,"DST_$i"); + return ($core_num,$dst) if($src == $core_num); } - return ($core_num, -1);#off + return ($core_num, -1);#off } sub download_netrace{ - my ($path) =@_; - #create path if it is not exist - unless (-d $path){ - mkpath("$path",1,01777); - } - my $window = def_popwin_size(30,85,"Netrace download",'percent'); - my $table = def_table(1, 1, FALSE); - my $scrolled_win = add_widget_to_scrolled_win($table); - - + my ($path) =@_; + #create path if it is not exist + unless (-d $path){ + mkpath("$path",1,01777); + } + my $window = def_popwin_size(30,85,"Netrace download",'percent'); + my $table = def_table(1, 1, FALSE); + my $scrolled_win = add_widget_to_scrolled_win($table); + + my @links =( { label=>"blackscholes simlarge (907M) ",name=>"blackscholes_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simlarge.tra.bz2"}, { label=>"blackscholes simmedium (182M)",name=>"blackscholes_64c_simmedium.tra.bz2",url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simmedium.tra.bz2"}, @@ -1958,31 +1888,31 @@ sub download_netrace{ { label=>"x264 simsmall (1.2G) ",name=>"x264_64c_simsmall.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/x264_64c_simsmall.tra.bz2"}, ); - my $row=0; - - - foreach my $d (@links){ - my $srow=$row; - $table-> attach (gen_label_in_left($d->{label}) , 0, 1, $row,$row+1,'expand','shrink',2,2); - my $file="$path/$d->{name}"; - if (-f $file){ - - }else{ - my $download=def_image_button("icons/download.png",'Download'); - $table-> attach ($download , 2, 3, $row,$row+1,'expand','shrink',2,2); - $download->signal_connect("clicked"=> sub{ - $download ->set_sensitive (FALSE); - my $load= show_gif("icons/load.gif"); - $table->attach ($load, 1, 2, $srow,$srow+ 1,'shrink','shrink',0,0); - $load->show_all; - my $o=$d->{name}; - download_from_google_drive("$d->{url}" ,"$path/$o" ); - $load->destroy; - $download->destroy if (-f $file); - }); - } - $row++; - } + my $row=0; + + + foreach my $d (@links){ + my $srow=$row; + $table-> attach (gen_label_in_left($d->{label}) , 0, 1, $row,$row+1,'expand','shrink',2,2); + my $file="$path/$d->{name}"; + if (-f $file){ + + }else{ + my $download=def_image_button("icons/download.png",'Download'); + $table-> attach ($download , 2, 3, $row,$row+1,'expand','shrink',2,2); + $download->signal_connect("clicked"=> sub{ + $download ->set_sensitive (FALSE); + my $load= show_gif("icons/load.gif"); + $table->attach ($load, 1, 2, $srow,$srow+ 1,'shrink','shrink',0,0); + $load->show_all; + my $o=$d->{name}; + download_from_google_drive("$d->{url}" ,"$path/$o" ); + $load->destroy; + $download->destroy if (-f $file); + }); + } + $row++; + } diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index a47c226..734639a 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -8,22 +8,22 @@ sub generate_topology_top_v { - my ($self,$info,$dir)=@_; - - - #create topology top file - my $name=$self->object_get_attribute('save_as'); - - my $r; - my $top="$dir/${name}_noc.sv"; + my ($self,$info,$dir)=@_; + + + #create topology top file + my $name=$self->object_get_attribute('save_as'); + + my $r; + my $top="$dir/${name}_noc.sv"; open my $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } print $fd autogen_warning(); print $fd get_license_header($top); - print $fd ' + print $fd ' `include "pronoc_def.v" '; @@ -33,116 +33,116 @@ sub generate_topology_top_v { my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; -# foreach my $d (@parameters){ -# $param_str = $param_str.",\n\tparameter $d->{param_name} = $d->{value}"; -# } +# foreach my $d (@parameters){ +# $param_str = $param_str.",\n\tparameter $d->{param_name} = $d->{value}"; +# } my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); my $MAX_P=0; foreach my $p (@routers){ - my $Pnum=$self->object_get_attribute("$p",'PNUM'); - $MAX_P =$Pnum if($Pnum>$MAX_P ); - } + my $Pnum=$self->object_get_attribute("$p",'PNUM'); + $MAX_P =$Pnum if($Pnum>$MAX_P ); + } my $NE= scalar @ends; my $NR= scalar @routers; - - - #step 2 add routers - my @nodes=get_list_of_all_routers($self); - my $i=0; - - my $ports="\treset, + + + #step 2 add routers + my @nodes=get_list_of_all_routers($self); + my $i=0; + + my $ports="\treset, \tclk"; - my $wires='', - my $routers=''; - - foreach my $p (@ends){ - my $instance= $self->object_get_attribute("$p","NAME"); - $ports=$ports.",\n\t//$instance"; - $wires=$wires." - /******************* - * $instance - *******************/ + my $wires='', + my $routers=''; + + foreach my $p (@ends){ + my $instance= $self->object_get_attribute("$p","NAME"); + $ports=$ports.",\n\t//$instance"; + $wires=$wires." + /******************* + * $instance + *******************/ "; - - $wires=$wires."\tinput smartflit_chanel_t ${instance}_chan_in;\n"; - $wires=$wires."\toutput smartflit_chanel_t ${instance}_chan_out;\n"; - $wires=$wires."\toutput router_event_t ${instance}_router_event;\n"; - $ports=$ports.",\n\t${instance}_chan_in,\n\t${instance}_chan_out,\n\t${instance}_router_event"; - - foreach my $d (@ports){ - my $range = ($d->{pwidth} eq 1)? " " : " [$d->{pwidth}-1 : 0]"; - my $type=$d->{type}; - my $ctype= ($type eq 'input')? 'output' : 'input'; - if( $d->{endp} eq "yes"){ - #$wires=$wires."\t$type $range ${instance}_$d->{pname};\n"; - #$wires=$wires."\t$ctype $range ${instance}_$d->{pconnect};\n"; - #$ports=$ports.",\n\t${instance}_$d->{pname},\n\t${instance}_$d->{pconnect}"; - } - } - } - - - foreach my $p (@nodes){ - - my ($wire,$router) = get_router_instance_v($self,$p,$i,$NE,$NR,$MAX_P); - $wires=$wires.$wire, - $routers=$routers.$router; - - - $i++; - } - - my $assign=""; - foreach my $p (@ends){ - my $instance= $self->object_get_attribute("$p","NAME"); - my $pname= "Port[0]"; - my $connect = $self->{$p}{'PCONNECT'}{$pname}; - if(defined $connect){ - my ($cname,$pnode)=split(/\s*,\s*/,$connect); - my $cinstance= $self->object_get_attribute("$cname","NAME"); - my ($cp)= sscanf("Port[%u]","$pnode"); - #$assign = $assign."//Connect $instance output ports 0 to $cinstance input ports $cp\n"; - my $cpplus=$cp+1; - - - foreach my $p (@ports){ - my $w=$p->{pwidth}; - my $range = ($w eq 1)? " " : "[$w-1 : 0 ]"; - my $crange = ($w eq 1)? "[$cp]" : "[($cpplus*$w)-1 : $cp*$w ]"; - my $cport = "${cinstance}_$p->{connect}"; - my $port ="${instance}_$p->{pconnect}"; - if($p->{type} eq 'input' ){ - # $assign= $assign."\t\tassign $port $range = $cport $crange;\n" if($p->{endp} eq "yes"); - }else{ - # $assign= $assign."\t\tassign $cport $crange= $port $range;\n" if($p->{endp} eq "yes"); - } - - } #@port - } - - } - - - - - print $fd " + + $wires=$wires."\tinput smartflit_chanel_t ${instance}_chan_in;\n"; + $wires=$wires."\toutput smartflit_chanel_t ${instance}_chan_out;\n"; + $wires=$wires."\toutput router_event_t ${instance}_router_event;\n"; + $ports=$ports.",\n\t${instance}_chan_in,\n\t${instance}_chan_out,\n\t${instance}_router_event"; + + foreach my $d (@ports){ + my $range = ($d->{pwidth} eq 1)? " " : " [$d->{pwidth}-1 : 0]"; + my $type=$d->{type}; + my $ctype= ($type eq 'input')? 'output' : 'input'; + if( $d->{endp} eq "yes"){ + #$wires=$wires."\t$type $range ${instance}_$d->{pname};\n"; + #$wires=$wires."\t$ctype $range ${instance}_$d->{pconnect};\n"; + #$ports=$ports.",\n\t${instance}_$d->{pname},\n\t${instance}_$d->{pconnect}"; + } + } + } + + + foreach my $p (@nodes){ + + my ($wire,$router) = get_router_instance_v($self,$p,$i,$NE,$NR,$MAX_P); + $wires=$wires.$wire, + $routers=$routers.$router; + + + $i++; + } + + my $assign=""; + foreach my $p (@ends){ + my $instance= $self->object_get_attribute("$p","NAME"); + my $pname= "Port[0]"; + my $connect = $self->{$p}{'PCONNECT'}{$pname}; + if(defined $connect){ + my ($cname,$pnode)=split(/\s*,\s*/,$connect); + my $cinstance= $self->object_get_attribute("$cname","NAME"); + my ($cp)= sscanf("Port[%u]","$pnode"); + #$assign = $assign."//Connect $instance output ports 0 to $cinstance input ports $cp\n"; + my $cpplus=$cp+1; + + + foreach my $p (@ports){ + my $w=$p->{pwidth}; + my $range = ($w eq 1)? " " : "[$w-1 : 0 ]"; + my $crange = ($w eq 1)? "[$cp]" : "[($cpplus*$w)-1 : $cp*$w ]"; + my $cport = "${cinstance}_$p->{connect}"; + my $port ="${instance}_$p->{pconnect}"; + if($p->{type} eq 'input' ){ + # $assign= $assign."\t\tassign $port $range = $cport $crange;\n" if($p->{endp} eq "yes"); + }else{ + # $assign= $assign."\t\tassign $cport $crange= $port $range;\n" if($p->{endp} eq "yes"); + } + + } #@port + } + + } + + + + + print $fd " module ${name}_noc #( - parameter NOC_ID=0 + parameter NOC_ID=0 ) ( - $ports + $ports ); - - `NOC_CONF - + + `NOC_CONF + input reset,clk; $wires @@ -153,30 +153,30 @@ sub generate_topology_top_v { endmodule "; - add_info($info,"$top file is created\n "); - close $fd; - - + add_info($info,"$top file is created\n "); + close $fd; + + } sub get_router_instance_v { - my ($self,$rname,$current_r,$NE,$NR,$MAX_P)=@_; - - - my $instance= $self->object_get_attribute("$rname","NAME"); - my $Pnum=$self->object_get_attribute("$rname",'PNUM'); - - #read ruter parameters and ports - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + my ($self,$rname,$current_r,$NE,$NR,$MAX_P)=@_; + + + my $instance= $self->object_get_attribute("$rname","NAME"); + my $Pnum=$self->object_get_attribute("$rname",'PNUM'); + + #read ruter parameters and ports + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - - my $wires_v=" - /******************* - * $instance - *******************/ + + my $wires_v=" + /******************* + * $instance + *******************/ \twire ${instance}_clk; \twire ${instance}_reset; @@ -188,30 +188,27 @@ sub get_router_instance_v { "; - - - - my $router_v=" - /******************* - * $instance - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P($Pnum) - ) - $instance - ( - .clk(${instance}_clk), - .reset(${instance}_reset), - .current_r_id($current_r), - .current_r_addr (${instance}_current_r_addr), - .chan_in (${instance}_chan_in), - .chan_out (${instance}_chan_out), - .router_event (${instance}_router_event) - ); + + my $router_v=" + /******************* + * $instance + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID($current_r), + .P($Pnum) + ) $instance ( + .clk(${instance}_clk), + .reset(${instance}_reset), + .current_r_id($current_r), + .current_r_addr (${instance}_current_r_addr), + .chan_in (${instance}_chan_in), + .chan_out (${instance}_chan_out), + .router_event (${instance}_router_event) + ); "; - + $router_v= $router_v." \t\tassign ${instance}_clk = clk; \t\tassign ${instance}_reset = reset; @@ -219,93 +216,91 @@ sub get_router_instance_v { "; - - for (my $i=0;$i<$Pnum; $i++){ - my $pname= "Port[${i}]"; - my $connect = $self->{$rname}{'PCONNECT'}{$pname}; - my $iplus=$i+1; - if(defined $connect){ - my ($cname,$pnode)=split(/\s*,\s*/,$connect); - my $cinstance= $self->object_get_attribute("$cname","NAME"); - my $ctype = $self->object_get_attribute("$cname",'TYPE'); - my ($cp)= sscanf("Port[%u]","$pnode"); - $router_v = $router_v."//Connect $instance port $i to $cinstance port $cp\n"; - if($ctype ne 'ENDP'){ - $router_v.=" \t\tassign ${instance}_chan_in [$i] = ${cinstance}_chan_out [$cp];\n"; - }else{ - $router_v.=" \t\tassign ${instance}_chan_in [$i] = ${cinstance}_chan_in;\n"; - $router_v.=" \t\tassign ${cinstance}_chan_out = ${instance}_chan_out [$i];\n"; - $router_v.=" \t\tassign ${cinstance}_router_event = ${instance}_router_event [$i];\n"; - - } - my $cpplus=$cp+1; - - #{name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw" }, - - - - foreach my $p (@ports){ - my $w=$p->{pwidth}; - my $range = ($w eq 1)? "[$i]" : "[($iplus*$w)-1 : $i*$w ]"; - my $crange = ($ctype eq 'ENDP') ? '' : - ($w eq 1)? "[$cp]" : "[($cpplus*$w)-1 : $cp*$w ]"; - my $cport = ($ctype eq 'ENDP') ? "${cinstance}_$p->{pname}" : "${cinstance}_$p->{connect}"; - my $port ="${instance}_$p->{name}"; - if($ctype eq 'ENDP' && $p->{endp} eq "no" && $p->{type} eq 'input' ){ - # $router_v= $router_v."\t\tassign $port $range = 0;\n"; - - }else{ - if($p->{type} eq 'input' ){ - # $router_v= $router_v."\t\tassign $port $range = $cport $crange;\n"; - }else{ - # $router_v= $router_v."\t\tassign $cport $crange= $port $range;\n"; - } - } - } #@port - - }else { - $router_v = $router_v."//Connect $instance port $i to ground -\t assign ${instance}_chan_in [$i]= {SMARTFLIT_CHANEL_w{1'b0}};\n"; - - foreach my $p (@ports){ - my $w=$p->{pwidth}; - my $range = ($w eq 1)? "[$i]" : "[($iplus*$w)-1 : $i*$w ]"; - if($p->{type} eq 'input' ){ - # $router_v= $router_v."\t\tassign ${instance}_$p->{name} $range = \{$w\{1'b0\}\};\n"; - } - } - } - -} - - - return ($wires_v,$router_v); + my $pname= "Port[${i}]"; + my $connect = $self->{$rname}{'PCONNECT'}{$pname}; + my $iplus=$i+1; + if(defined $connect){ + my ($cname,$pnode)=split(/\s*,\s*/,$connect); + my $cinstance= $self->object_get_attribute("$cname","NAME"); + my $ctype = $self->object_get_attribute("$cname",'TYPE'); + my ($cp)= sscanf("Port[%u]","$pnode"); + $router_v = $router_v."//Connect $instance port $i to $cinstance port $cp\n"; + if($ctype ne 'ENDP'){ + $router_v.=" \t\tassign ${instance}_chan_in [$i] = ${cinstance}_chan_out [$cp];\n"; + }else{ + $router_v.=" \t\tassign ${instance}_chan_in [$i] = ${cinstance}_chan_in;\n"; + $router_v.=" \t\tassign ${cinstance}_chan_out = ${instance}_chan_out [$i];\n"; + $router_v.=" \t\tassign ${cinstance}_router_event = ${instance}_router_event [$i];\n"; + + } + my $cpplus=$cp+1; + + #{name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw" }, + + + + foreach my $p (@ports){ + my $w=$p->{pwidth}; + my $range = ($w eq 1)? "[$i]" : "[($iplus*$w)-1 : $i*$w ]"; + my $crange = ($ctype eq 'ENDP') ? '' : + ($w eq 1)? "[$cp]" : "[($cpplus*$w)-1 : $cp*$w ]"; + my $cport = ($ctype eq 'ENDP') ? "${cinstance}_$p->{pname}" : "${cinstance}_$p->{connect}"; + my $port ="${instance}_$p->{name}"; + if($ctype eq 'ENDP' && $p->{endp} eq "no" && $p->{type} eq 'input' ){ + # $router_v= $router_v."\t\tassign $port $range = 0;\n"; + + }else{ + if($p->{type} eq 'input' ){ + # $router_v= $router_v."\t\tassign $port $range = $cport $crange;\n"; + }else{ + # $router_v= $router_v."\t\tassign $cport $crange= $port $range;\n"; + } + } + } #@port + + }else { + $router_v = $router_v."//Connect $instance port $i to ground +\t assign ${instance}_chan_in [$i]= {SMARTFLIT_CHANEL_w{1'b0}};\n"; + + foreach my $p (@ports){ + my $w=$p->{pwidth}; + my $range = ($w eq 1)? "[$i]" : "[($iplus*$w)-1 : $i*$w ]"; + if($p->{type} eq 'input' ){ + # $router_v= $router_v."\t\tassign ${instance}_$p->{name} $range = \{$w\{1'b0\}\};\n"; + } + } + } + +} + + + return ($wires_v,$router_v); } #******************* -# generate_topology_top_genvar_v +# generate_topology_top_genvar_v #******************** sub generate_topology_top_genvar_v{ - my ($self,$info,$dir)=@_; - - - #create topology top file - my $name=$self->object_get_attribute('save_as'); - my $r; - my $top="$dir/${name}_noc_genvar.sv"; + my ($self,$info,$dir)=@_; + + + #create topology top file + my $name=$self->object_get_attribute('save_as'); + my $r; + my $top="$dir/${name}_noc_genvar.sv"; open my $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } print $fd autogen_warning(); print $fd get_license_header($top); - print $fd ' + print $fd ' `include "pronoc_def.v" '; @@ -315,28 +310,28 @@ sub generate_topology_top_genvar_v{ my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - foreach my $d (@parameters){ - $param_str = $param_str.",\n\tparameter $d->{param_name} = $d->{value}"; - } + foreach my $d (@parameters){ + $param_str = $param_str.",\n\tparameter $d->{param_name} = $d->{value}"; + } my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); my $MAX_P=0; foreach my $p (@routers){ - my $Pnum=$self->object_get_attribute("$p",'PNUM'); - $MAX_P =$Pnum if($Pnum>$MAX_P ); - } + my $Pnum=$self->object_get_attribute("$p",'PNUM'); + $MAX_P =$Pnum if($Pnum>$MAX_P ); + } my $NE= scalar @ends; my $NR= scalar @routers; - - - my @nodes=get_list_of_all_routers($self); - my $i=0; - - my $ports="\treset, + + + my @nodes=get_list_of_all_routers($self); + my $i=0; + + my $ports="\treset, \tclk, \tchan_in_all, \tchan_out_all, @@ -361,148 +356,147 @@ sub generate_topology_top_genvar_v{ "; - my $router_wires=""; - my $endps_wires=""; - - - - - foreach my $d (@ports){ - my $range = ($d->{width} eq 1)? " " : " [$d->{width}-1 : 0]"; - my $pdef_range = ($d->{pwidth} eq 1)? "[NE-1 : 0]" : "[(NE*$d->{pwidth})-1 : 0]"; - my $endp_range = "[$d->{pwidth}-1 : 0]"; - my $type=$d->{type}; - my $ctype= ($type eq 'input')? 'output' : 'input'; - if( $d->{endp} eq "yes"){ - #$ports_def=$ports_def."\t$type $pdef_range $d->{name};\n"; - #$ports_def=$ports_def."\t$ctype $pdef_range $d->{connect};\n"; - #$ports=$ports.",\n\t$d->{name},\n\t$d->{connect}"; - } - if($d->{width} eq 1){ - #$router_wires=$router_wires. "\twire [NR-1 :0] router_$d->{name};\n"; - #$router_wires=$router_wires. "\twire [NR-1 :0] router_$d->{connect};\n"; - }else{ - #$router_wires=$router_wires. "\twire $range router_$d->{name} [NR-1 :0];\n"; - #$router_wires=$router_wires. "\twire $range router_$d->{connect} [NR-1 :0];\n"; - } - if( $d->{endp} eq "yes"){ - if($d->{pwidth} eq 1){ - #$endps_wires=$endps_wires. "\twire [NE-1 :0] ni_$d->{pname};\n"; - #$endps_wires=$endps_wires. "\twire [NE-1 :0] ni_$d->{pconnect};\n"; - }else{ - #$endps_wires=$endps_wires. "\twire $endp_range ni_$d->{pname} [NE-1 :0];\n"; - #$endps_wires=$endps_wires. "\twire $endp_range ni_$d->{pconnect} [NE-1 :0];\n"; - } - - } - } - - - - - #step 2 add routers - my $Tnum=1; - - my $routers=' - genvar i; - generate - '; - my $offset=0; - my $assign=""; - my $assign_r2r=""; - my $assign_r2e=""; - my $init_h=""; - my $init_gnd_h=""; - my %new_h; - my $addr=0; - for ( my $i=2;$i<=12; $i++){ - my $n= $self->object_get_attribute("ROUTER${i}","NUM"); - $n=0 if(!defined $n); - if($n>0){ - - for(my $rr=0; $rr<$n; $rr=$rr+1) { - my $pos= ($offset==0)? $rr : $rr+$offset; - $new_h{"TNUM_${pos}"}="$Tnum"; - $new_h{"RNUM_${pos}"}="$rr"; - - $init_h.="router${Tnum}[$rr]->current_r_addr=$addr;\n"; - $init_h.="router${Tnum}[$rr]->current_r_id=$addr;\n"; - $addr++; - } - $offset+= $n; - $Tnum++; - } - } - - - - - - - - $offset=0; - my $R_num=0; - for ( my $i=2;$i<=12; $i++){ - my $n= $self->object_get_attribute("ROUTER${i}","NUM"); - $n=0 if(!defined $n); - if($n>0){ - my $router_pos= ($offset==0)? 'i' : "i+$offset"; - #my $instant=get_router_genvar_instance_v($self,$i,$router_pos,$NE,$NR,$MAX_P); - my $p = $i-1; - $routers=$routers." + my $router_wires=""; + my $endps_wires=""; + + + + + foreach my $d (@ports){ + my $range = ($d->{width} eq 1)? " " : " [$d->{width}-1 : 0]"; + my $pdef_range = ($d->{pwidth} eq 1)? "[NE-1 : 0]" : "[(NE*$d->{pwidth})-1 : 0]"; + my $endp_range = "[$d->{pwidth}-1 : 0]"; + my $type=$d->{type}; + my $ctype= ($type eq 'input')? 'output' : 'input'; + if( $d->{endp} eq "yes"){ + #$ports_def=$ports_def."\t$type $pdef_range $d->{name};\n"; + #$ports_def=$ports_def."\t$ctype $pdef_range $d->{connect};\n"; + #$ports=$ports.",\n\t$d->{name},\n\t$d->{connect}"; + } + if($d->{width} eq 1){ + #$router_wires=$router_wires. "\twire [NR-1 :0] router_$d->{name};\n"; + #$router_wires=$router_wires. "\twire [NR-1 :0] router_$d->{connect};\n"; + }else{ + #$router_wires=$router_wires. "\twire $range router_$d->{name} [NR-1 :0];\n"; + #$router_wires=$router_wires. "\twire $range router_$d->{connect} [NR-1 :0];\n"; + } + if( $d->{endp} eq "yes"){ + if($d->{pwidth} eq 1){ + #$endps_wires=$endps_wires. "\twire [NE-1 :0] ni_$d->{pname};\n"; + #$endps_wires=$endps_wires. "\twire [NE-1 :0] ni_$d->{pconnect};\n"; + }else{ + #$endps_wires=$endps_wires. "\twire $endp_range ni_$d->{pname} [NE-1 :0];\n"; + #$endps_wires=$endps_wires. "\twire $endp_range ni_$d->{pconnect} [NE-1 :0];\n"; + } + + } + } + + + + + #step 2 add routers + my $Tnum=1; + + my $routers=' + genvar i; + generate + '; + my $offset=0; + my $assign=""; + my $assign_r2r=""; + my $assign_r2e=""; + my $init_h=""; + my $init_gnd_h=""; + my %new_h; + my $addr=0; + for ( my $i=2;$i<=12; $i++){ + my $n= $self->object_get_attribute("ROUTER${i}","NUM"); + $n=0 if(!defined $n); + if($n>0){ + + for(my $rr=0; $rr<$n; $rr=$rr+1) { + my $pos= ($offset==0)? $rr : $rr+$offset; + $new_h{"TNUM_${pos}"}="$Tnum"; + $new_h{"RNUM_${pos}"}="$rr"; + + $init_h.="router${Tnum}[$rr]->current_r_addr=$addr;\n"; + $init_h.="router${Tnum}[$rr]->current_r_id=$addr;\n"; + $addr++; + } + $offset+= $n; + $Tnum++; + } + } + + + + + + + + $offset=0; + my $R_num=0; + for ( my $i=2;$i<=12; $i++){ + my $n= $self->object_get_attribute("ROUTER${i}","NUM"); + $n=0 if(!defined $n); + if($n>0){ + my $router_pos= ($offset==0)? 'i' : "i+$offset"; + #my $instant=get_router_genvar_instance_v($self,$i,$router_pos,$NE,$NR,$MAX_P); + my $p = $i-1; + $routers=$routers." \tfor( i=0; i<$n; i=i+1) begin : router_${i}_port_lp - localparam RID = $router_pos; - assign current_r_addr [RID] = RID[RAw-1: 0]; - - router_top #( - .NOC_ID(NOC_ID), - .P($i) - ) - router_${i}_port - ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr\[RID\]), - .chan_in (router_chan_in \[RID\] \[$p : 0\]), - .chan_out (router_chan_out\[RID\] \[$p : 0\]), - .router_event(router_event\[RID\] \[$p : 0\]) - ); + localparam RID = $router_pos; + assign current_r_addr [RID] = RID[RAw-1: 0]; + + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P($i) + ) router_${i}_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr\[RID\]), + .chan_in (router_chan_in \[RID\] \[$p : 0\]), + .chan_out (router_chan_out\[RID\] \[$p : 0\]), + .router_event(router_event\[RID\] \[$p : 0\]) + ); -\tend - "; - - for ( my $j=0;$j<$n; $j++){ - my $rname ="ROUTER${i}_$j"; - my ($ass_v,$r2r_h,$r2e_h, $int_h,$gnd_h); - ($ass_v,$r2r_h,$r2e_h, $int_h,$gnd_h,$R_num) = get_wires_assignment_genvar_v($self,$rname,0,\%new_h,$R_num); - - $assign=$assign.$ass_v; - $assign_r2r.=$r2r_h; - $assign_r2e.=$r2e_h; - $init_h.=$int_h; - $init_gnd_h.=$gnd_h; - } - - $offset+= $n; - - } - } - - -$routers.="endgenerate\n"; - - - - - - - print $fd " +\tend + "; + + for ( my $j=0;$j<$n; $j++){ + my $rname ="ROUTER${i}_$j"; + my ($ass_v,$r2r_h,$r2e_h, $int_h,$gnd_h); + ($ass_v,$r2r_h,$r2e_h, $int_h,$gnd_h,$R_num) = get_wires_assignment_genvar_v($self,$rname,0,\%new_h,$R_num); + + $assign=$assign.$ass_v; + $assign_r2r.=$r2r_h; + $assign_r2e.=$r2e_h; + $init_h.=$int_h; + $init_gnd_h.=$gnd_h; + } + + $offset+= $n; + + } + } + + +$routers.="endgenerate\n"; + + + + + + + print $fd " module ${name}_noc_genvar #( - parameter NOC_ID=0 + parameter NOC_ID=0 )( reset, @@ -528,32 +522,32 @@ sub generate_topology_top_genvar_v{ endmodule "; - - close $fd; - add_info($info,"$top file is created\n "); - - my $project_dir = get_project_dir(); - $project_dir= "$project_dir/mpsoc"; - my $src_verilator_dir="$project_dir/src_verilator/topology/custom"; - mkpath("$src_verilator_dir",1,01777) unless -f $src_verilator_dir; + + close $fd; + add_info($info,"$top file is created\n "); + + my $project_dir = get_project_dir(); + $project_dir= "$project_dir/mpsoc"; + my $src_verilator_dir="$project_dir/src_verilator/topology/custom"; + mkpath("$src_verilator_dir",1,01777) unless -f $src_verilator_dir; $top="$src_verilator_dir/${name}_noc.h"; open $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } my $fr2r=""; for (my $i=0;$i<$R_num ; $i++){ - $fr2r.="\n" if($i%10==0); - $fr2r.=($i==0) ? "single_r2r$i" : ",single_r2r$i"; - + $fr2r.="\n" if($i%10==0); + $fr2r.=($i==0) ? "single_r2r$i" : ",single_r2r$i"; + } my $fr2e=""; for (my $i=0;$i<$NE ; $i++){ - $fr2e.="\n" if($i%10==0); - $fr2e.=($i==0) ? "single_r2e$i" : ",single_r2e$i"; + $fr2e.="\n" if($i%10==0); + $fr2e.=($i==0) ? "single_r2e$i" : ",single_r2e$i"; } @@ -569,57 +563,54 @@ sub generate_topology_top_genvar_v{ void (*r2e_func_ptr[$NE])() = {$fr2e}; void topology_connect_r2r (int n){ - (*r2r_func_ptr[n])(); + (*r2r_func_ptr[n])(); } void topology_connect_r2e (int n){ - (*r2e_func_ptr[n])(); + (*r2e_func_ptr[n])(); } void topology_init(void){ - $init_h - R2R_TABLE_SIZ=$R_num; - $init_gnd_h + $init_h + R2R_TABLE_SIZ=$R_num; + $init_gnd_h } "; close $fd; - add_info($info,"$top file is created\n "); - + add_info($info,"$top file is created\n "); + } sub get_router_genvar_instance_v{ - my ($self,$Pnum,$router_pos,$NE,$NR,$MAX_P)=@_; + my ($self,$Pnum,$router_pos,$NE,$NR,$MAX_P)=@_; - #read ruter parameters and ports - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + #read ruter parameters and ports + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - - - - my $router_v=" - - router_top #( - .NOC_ID(NOC_ID), - .P($Pnum) - ) - router_${Pnum}_port - ( - .clk(clk), - .reset(reset), - .current_r_addr($router_pos), - .current_r_id($router_pos), - .chan_in (router_chan_in\[$router_pos\]), - .chan_out(router_chan_out\[$router_pos\]), - .router_event(router_event\[$router_pos\]) - ); - - - + + + + my $router_v=" + + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID($router_pos), + .P($Pnum) + ) router_${Pnum}_port ( + .clk(clk), + .reset(reset), + .current_r_addr($router_pos), + .current_r_id($router_pos), + .chan_in (router_chan_in\[$router_pos\]), + .chan_out(router_chan_out\[$router_pos\]), + .router_event(router_event\[$router_pos\]) + ); + "; return $router_v; @@ -629,102 +620,102 @@ sub get_router_genvar_instance_v{ sub get_wires_assignment_genvar_v{ - my ($self,$rname,$reverse,$cref,$R_num)=@_; + my ($self,$rname,$reverse,$cref,$R_num)=@_; $reverse = 0 if(!defined $reverse); - my $instance= $self->object_get_attribute("$rname","NAME"); - my $Pnum=$self->object_get_attribute("$rname",'PNUM'); - - #read ruter parameters and ports - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + my $instance= $self->object_get_attribute("$rname","NAME"); + my $Pnum=$self->object_get_attribute("$rname",'PNUM'); + + #read ruter parameters and ports + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - my $assign=""; - my $r2e_h=""; - my $r2r_h=""; - my $init_h=""; - my $gnd_h=""; - - + my $assign=""; + my $r2e_h=""; + my $r2r_h=""; + my $init_h=""; + my $gnd_h=""; + + - my @ends=get_list_of_all_endpoints($self); + my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - my $pos = get_scolar_pos($rname,@routers); - my $type = "ROUTER"; - if(!defined $pos){ - $pos = get_scolar_pos($rname,@ends); - $type = "ENDP"; - } - - my %rinfo = %{$cref} if (defined $cref); - + my $pos = get_scolar_pos($rname,@routers); + my $type = "ROUTER"; + if(!defined $pos){ + $pos = get_scolar_pos($rname,@ends); + $type = "ENDP"; + } + + my %rinfo = %{$cref} if (defined $cref); + for (my $i=0;$i<$Pnum; $i++){ - my $pname= "Port[${i}]"; - my $connect = $self->{$rname}{'PCONNECT'}{$pname}; - my $iplus=$i+1; - if(defined $connect){ - my ($cname,$pnode)=split(/\s*,\s*/,$connect); - my $cinstance= $self->object_get_attribute("$cname","NAME"); - my $ctype = $self->object_get_attribute("$cname",'TYPE'); - my ($cp)= sscanf("Port[%u]","$pnode"); - $assign.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; - - - my $cpos =($ctype eq 'ENDP')? get_scolar_pos($cname,@ends) : get_scolar_pos($cname,@routers); - - my $cpplus=$cp+1; - my $cposplus = $cpos+1; - my $posplus=$pos+1; - #{name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw" }, - - my $TNUM_pos = $rinfo{"TNUM_${pos}"}; - my $RNUM_pos = $rinfo{"RNUM_${pos}"}; - my $TNUM_cpos = $rinfo{"TNUM_${cpos}"}; - my $RNUM_cpos = $rinfo{"RNUM_${cpos}"}; - - #$assign = $assign."//connet $instance input port $i to $cinstance output port $cp\n"; - if($type ne 'ENDP' && $ctype eq 'ENDP'){ - - $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] = chan_in_all \[$cpos\];\n" if($reverse==0); - $assign= $assign."\t\tassign chan_in_all \[$cpos\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); - - $assign= $assign."\t\tassign chan_out_all \[$cpos\] = router_chan_out \[$pos\]\[$i\];\n" if($reverse==0); - $assign= $assign."\t\tassign router_chan_out \[$pos\]\[$i\] = chan_out_all \[$cpos\];\n" if($reverse==1); - - $r2e_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; - $r2e_h.= "void single_r2e$cpos(void) {connect_r2e($TNUM_pos,$RNUM_pos,$i,$cpos);}\n" if (defined $TNUM_pos); - - - }elsif ($type ne 'ENDP' && $ctype ne 'ENDP'){ - $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] = router_chan_out \[$cpos\]\[$cp\];\n" if($reverse==0); - $assign= $assign."\t\tassign router_chan_out \[$cpos\]\[$cp\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); - $r2r_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; - $r2r_h.= "void single_r2r$R_num(void){conect_r2r($TNUM_pos,$RNUM_pos,$i,$TNUM_cpos,$RNUM_cpos,$cp);}\n" if (defined $TNUM_pos); - $init_h.="\tr2r_cnt_all[$R_num] =(r2r_cnt_table_t){.id1=$pos, .t1=$TNUM_pos, .r1=$RNUM_pos, .p1=$i,.id2=$cpos, .t2=$TNUM_cpos, .r2=$RNUM_cpos, .p2=$cp };\n"; - $R_num++; - } - - - - - - }else { - my $TNUM_pos = $rinfo{"TNUM_${pos}" }; - my $RNUM_pos = $rinfo{"RNUM_${pos}" }; - - $assign = $assign."//Connect $instance port $i to ground\n"; - $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==0); - $assign= $assign."\t\tassign router_chan_out \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==1); - - $gnd_h.="//Connect $instance port $i to ground\n"; - $gnd_h.= "\tconnect_r2gnd($TNUM_pos,$RNUM_pos,$i);\n" if (defined $TNUM_pos); - } - -} - - - - return ($assign,$r2r_h,$r2e_h,$init_h,$gnd_h,$R_num); + my $pname= "Port[${i}]"; + my $connect = $self->{$rname}{'PCONNECT'}{$pname}; + my $iplus=$i+1; + if(defined $connect){ + my ($cname,$pnode)=split(/\s*,\s*/,$connect); + my $cinstance= $self->object_get_attribute("$cname","NAME"); + my $ctype = $self->object_get_attribute("$cname",'TYPE'); + my ($cp)= sscanf("Port[%u]","$pnode"); + $assign.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + + + my $cpos =($ctype eq 'ENDP')? get_scolar_pos($cname,@ends) : get_scolar_pos($cname,@routers); + + my $cpplus=$cp+1; + my $cposplus = $cpos+1; + my $posplus=$pos+1; + #{name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw" }, + + my $TNUM_pos = $rinfo{"TNUM_${pos}"}; + my $RNUM_pos = $rinfo{"RNUM_${pos}"}; + my $TNUM_cpos = $rinfo{"TNUM_${cpos}"}; + my $RNUM_cpos = $rinfo{"RNUM_${cpos}"}; + + #$assign = $assign."//connet $instance input port $i to $cinstance output port $cp\n"; + if($type ne 'ENDP' && $ctype eq 'ENDP'){ + + $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] = chan_in_all \[$cpos\];\n" if($reverse==0); + $assign= $assign."\t\tassign chan_in_all \[$cpos\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); + + $assign= $assign."\t\tassign chan_out_all \[$cpos\] = router_chan_out \[$pos\]\[$i\];\n" if($reverse==0); + $assign= $assign."\t\tassign router_chan_out \[$pos\]\[$i\] = chan_out_all \[$cpos\];\n" if($reverse==1); + + $r2e_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + $r2e_h.= "void single_r2e$cpos(void) {connect_r2e($TNUM_pos,$RNUM_pos,$i,$cpos);}\n" if (defined $TNUM_pos); + + + }elsif ($type ne 'ENDP' && $ctype ne 'ENDP'){ + $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] = router_chan_out \[$cpos\]\[$cp\];\n" if($reverse==0); + $assign= $assign."\t\tassign router_chan_out \[$cpos\]\[$cp\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); + $r2r_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + $r2r_h.= "void single_r2r$R_num(void){conect_r2r($TNUM_pos,$RNUM_pos,$i,$TNUM_cpos,$RNUM_cpos,$cp);}\n" if (defined $TNUM_pos); + $init_h.="\tr2r_cnt_all[$R_num] =(r2r_cnt_table_t){.id1=$pos, .t1=$TNUM_pos, .r1=$RNUM_pos, .p1=$i,.id2=$cpos, .t2=$TNUM_cpos, .r2=$RNUM_cpos, .p2=$cp };\n"; + $R_num++; + } + + + + + + }else { + my $TNUM_pos = $rinfo{"TNUM_${pos}" }; + my $RNUM_pos = $rinfo{"RNUM_${pos}" }; + + $assign = $assign."//Connect $instance port $i to ground\n"; + $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==0); + $assign= $assign."\t\tassign router_chan_out \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==1); + + $gnd_h.="//Connect $instance port $i to ground\n"; + $gnd_h.= "\tconnect_r2gnd($TNUM_pos,$RNUM_pos,$i);\n" if (defined $TNUM_pos); + } + +} + + + + return ($assign,$r2r_h,$r2e_h,$init_h,$gnd_h,$R_num); } @@ -732,78 +723,78 @@ sub get_wires_assignment_genvar_v{ sub generate_routing_v { - my ($self,$info,$dir)=@_; - - my @ends=get_list_of_all_endpoints($self); - my @routers=get_list_of_all_routers($self); - -######################### + my ($self,$info,$dir)=@_; + + my @ends=get_list_of_all_endpoints($self); + my @routers=get_list_of_all_routers($self); + +######################### # conventional_routing ######################### - #create routing file - my $name=$self->object_get_attribute('save_as'); - my $rname=$self->object_get_attribute('routing_name'); - my $Vname="T${name}R${rname}"; - - my $r; - my $top="$dir/${Vname}_conventional_routing.v"; + #create routing file + my $name=$self->object_get_attribute('save_as'); + my $rname=$self->object_get_attribute('routing_name'); + my $Vname="T${name}R${rname}"; + + my $r; + my $top="$dir/${Vname}_conventional_routing.v"; open my $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } print $fd autogen_warning(); print $fd get_license_header($top); - - - - - - my $route_str="\talways@(*)begin + + + + + + my $route_str="\talways@(*)begin \t\tdestport=0; \t\tcase(src_e_addr) //source address of each individual NI is fixed. So this CASE will be optimized by the synthesizer for each endpoint. "; - - foreach my $src (@ends){ - my $PNUM=$self->object_get_attribute($src,"PNUM"); - my $src_num=get_scolar_pos($src,@ends); - my %route; - $route_str=$route_str."\t\t$src_num: begin + + foreach my $src (@ends){ + my $PNUM=$self->object_get_attribute($src,"PNUM"); + my $src_num=get_scolar_pos($src,@ends); + my %route; + $route_str=$route_str."\t\t$src_num: begin \t\t\tcase(dest_e_addr) "; - - foreach my $dst (@ends){ - my $dest_num = get_scolar_pos($dst,@ends); - my $ref = $self->object_get_attribute('Route',"${src}::$dst"); - next if(!defined $ref); - my @path = @{$ref}; - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); - #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; - $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; - } - foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin + + foreach my $dst (@ends){ + my $dest_num = get_scolar_pos($dst,@ends); + my $ref = $self->object_get_attribute('Route',"${src}::$dst"); + next if(!defined $ref); + my @path = @{$ref}; + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); + #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; + $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; + } + foreach my $q (sort {$a <=> $b} keys %route){ + $route_str=$route_str."\t\t\t$route{$q}: begin \t\t\t\tdestport= $q; \t\t\tend "; - } - $route_str=$route_str." + } + $route_str=$route_str." \t\t\tdefault: begin \t\t\t\tdestport= {DSTPw{1\'bX}}; \t\t\tend \t\t\tendcase\n\t\tend//$src_num\n"; - } - $route_str=$route_str." + } + $route_str=$route_str." \t\tdefault: begin \t\t\tdestport= {DSTPw{1\'bX}}; \t\tend \t\tendcase\n\tend\n"; - - - print $fd "module ${Vname}_conventional_routing #( + + + print $fd "module ${Vname}_conventional_routing #( \tparameter RAw = 3, \tparameter EAw = 3, \tparameter DSTPw=4 @@ -816,12 +807,12 @@ sub generate_routing_v { \tinput [EAw-1 :0] dest_e_addr; \tinput [EAw-1 :0] src_e_addr; -\toutput reg [DSTPw-1 :0] destport; +\toutput reg [DSTPw-1 :0] destport; $route_str - - + + endmodule "; @@ -833,17 +824,17 @@ sub generate_routing_v { ################### #create routing file - $top="$dir/${Vname}_look_ahead_routing.v"; + $top="$dir/${Vname}_look_ahead_routing.v"; open $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } print $fd autogen_warning(); print $fd get_license_header($top); - $route_str="\talways@(*)begin + $route_str="\talways@(*)begin \t\tdestport=0; \t\tcase(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. "; @@ -851,64 +842,64 @@ sub generate_routing_v { foreach my $router (@routers){ - my $PNUM=$self->object_get_attribute($router,"PNUM"); - my $router_num=get_scolar_pos($router,@routers); - my %route; - $route_str=$route_str."\t\t$router_num: begin + my $PNUM=$self->object_get_attribute($router,"PNUM"); + my $router_num=get_scolar_pos($router,@routers); + my %route; + $route_str=$route_str."\t\t$router_num: begin \t\t\tcase({src_e_addr,dest_e_addr}) "; - # for each src-dest check if $router include in path - foreach my $src (@ends){ - foreach my $dst (@ends){ - my $ref = $self->object_get_attribute('Route',"${src}::$dst"); - next if(!defined $ref); - my @path = @{$ref}; - my $loc= get_scolar_pos($router,@path); - next if(!defined $loc);# this router does not exist in path skip it - my $next_router1=$path[$loc+1]; - my $next_router2=$path[$loc+2]; - next if(!defined $next_router2); - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); - next if(!defined $p1); - my $src_num=get_scolar_pos($src,@ends); - my $dest_num = get_scolar_pos($dst,@ends); - $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; - - #print "@path\n"; - #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; - #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; - #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; - #print"***************************\n"; - - } - } - foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin + # for each src-dest check if $router include in path + foreach my $src (@ends){ + foreach my $dst (@ends){ + my $ref = $self->object_get_attribute('Route',"${src}::$dst"); + next if(!defined $ref); + my @path = @{$ref}; + my $loc= get_scolar_pos($router,@path); + next if(!defined $loc);# this router does not exist in path skip it + my $next_router1=$path[$loc+1]; + my $next_router2=$path[$loc+2]; + next if(!defined $next_router2); + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); + next if(!defined $p1); + my $src_num=get_scolar_pos($src,@ends); + my $dest_num = get_scolar_pos($dst,@ends); + $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; + + #print "@path\n"; + #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; + #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; + #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; + #print"***************************\n"; + + } + } + foreach my $q (sort {$a <=> $b} keys %route){ + $route_str=$route_str."\t\t\t$route{$q}: begin \t\t\t\tdestport= $q; \t\t\tend -"; - - } - - $route_str.="\t\t\tdefault: begin +"; + + } + + $route_str.="\t\t\tdefault: begin \t\t\t\tdestport= {DSTPw{1\'bX}}; \t\t\tend \t\t\tendcase\n\t\tend//$router_num\n"; - } + } $route_str.="\t\tdefault: begin \t\t\tdestport= {DSTPw{1\'bX}}; \t\tend \t\tendcase\n\tend\n"; - + my $localparam=""; - my $i=0; - foreach my $src (@ends){ - $localparam= $localparam."localparam [EAw-1 : 0]\tE$i=$i;\n"; - $i++; - } - + my $i=0; + foreach my $src (@ends){ + $localparam= $localparam."localparam [EAw-1 : 0]\tE$i=$i;\n"; + $i++; + } + @@ -935,37 +926,37 @@ sub generate_routing_v { \tinput [RAw-1 :0] current_r_addr; \tinput [EAw-1 :0] dest_e_addr; \tinput [EAw-1 :0] src_e_addr; -\toutput [DSTPw-1 :0] destport; +\toutput [DSTPw-1 :0] destport; \tinput reset,clk; - reg [EAw-1 :0] dest_e_addr_delay; - reg [EAw-1 :0] src_e_addr_delay; + reg [EAw-1 :0] dest_e_addr_delay; + reg [EAw-1 :0] src_e_addr_delay; - always @ (`pronoc_clk_reset_edge )begin + always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset)begin - dest_e_addr_delay<={EAw{1'b0}}; - src_e_addr_delay<={EAw{1'b0}}; - end else begin - dest_e_addr_delay<=dest_e_addr; - src_e_addr_delay<=src_e_addr; - end - end - - ${Vname}_look_ahead_routing_comb #( - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw) - ) - lkp_cmb - ( - .current_r_addr(current_r_addr), - .dest_e_addr(dest_e_addr_delay), - .src_e_addr(src_e_addr_delay), - .destport(destport) - ); - - - + dest_e_addr_delay<={EAw{1'b0}}; + src_e_addr_delay<={EAw{1'b0}}; + end else begin + dest_e_addr_delay<=dest_e_addr; + src_e_addr_delay<=src_e_addr; + end + end + + ${Vname}_look_ahead_routing_comb #( + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw) + ) + lkp_cmb + ( + .current_r_addr(current_r_addr), + .dest_e_addr(dest_e_addr_delay), + .src_e_addr(src_e_addr_delay), + .destport(destport) + ); + + + endmodule /******************* @@ -987,13 +978,13 @@ sub generate_routing_v { \tinput [RAw-1 :0] current_r_addr; \tinput [EAw-1 :0] dest_e_addr; \tinput [EAw-1 :0] src_e_addr; -\toutput reg [DSTPw-1 :0] destport; +\toutput reg [DSTPw-1 :0] destport; $localparam $route_str - + endmodule @@ -1002,65 +993,65 @@ sub generate_routing_v { close($fd); add_info($info,"$top file is created\n "); -######################### +######################### # conventional_routing_genvar ######################### - #create routing file - $top="$dir/${Vname}_conventional_routing_genvar.v"; + #create routing file + $top="$dir/${Vname}_conventional_routing_genvar.v"; open $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } print $fd autogen_warning(); print $fd get_license_header($top); - - - - - - $route_str="\tgenerate + + + + + + $route_str="\tgenerate "; - - foreach my $src (@ends){ - my $PNUM=$self->object_get_attribute($src,"PNUM"); - my $src_num=get_scolar_pos($src,@ends); - my %route; - $route_str=$route_str."\tif(SRC_E_ADDR == $src_num) begin : SRC$src_num -\t\talways@(*)begin + + foreach my $src (@ends){ + my $PNUM=$self->object_get_attribute($src,"PNUM"); + my $src_num=get_scolar_pos($src,@ends); + my %route; + $route_str=$route_str."\tif(SRC_E_ADDR == $src_num) begin : SRC$src_num +\t\talways@(*)begin \t\t\tdestport= 0; \t\t\tcase(dest_e_addr) "; - - foreach my $dst (@ends){ - my $dest_num = get_scolar_pos($dst,@ends); - my $ref = $self->object_get_attribute('Route',"${src}::$dst"); - next if(!defined $ref); - my @path = @{$ref}; - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); - #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; - $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; - } - foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin + + foreach my $dst (@ends){ + my $dest_num = get_scolar_pos($dst,@ends); + my $ref = $self->object_get_attribute('Route',"${src}::$dst"); + next if(!defined $ref); + my @path = @{$ref}; + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); + #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; + $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; + } + foreach my $q (sort {$a <=> $b} keys %route){ + $route_str=$route_str."\t\t\t$route{$q}: begin \t\t\t\tdestport= $q; \t\t\tend "; - } - $route_str=$route_str."\t\t\tdefault: begin + } + $route_str=$route_str."\t\t\tdefault: begin \t\t\t\tdestport= {DSTPw{1\'bX}}; \t\t\tend \t\t\tendcase\n\t\tend\n\tend//SRC$src_num\n\n"; - } - $route_str=$route_str."\tendgenerate\n"; + } + $route_str=$route_str."\tendgenerate\n"; - - - print $fd "module ${Vname}_conventional_routing_genvar #( + + + print $fd "module ${Vname}_conventional_routing_genvar #( \tparameter RAw = 3, \tparameter EAw = 3, \tparameter DSTPw=4, @@ -1072,12 +1063,12 @@ sub generate_routing_v { ); \tinput [EAw-1 :0] dest_e_addr; -\toutput reg [DSTPw-1 :0] destport; +\toutput reg [DSTPw-1 :0] destport; $route_str - - + + endmodule "; @@ -1089,18 +1080,18 @@ sub generate_routing_v { ################### #create routing file - $top="$dir/${Vname}_look_ahead_routing_genvar.v"; + $top="$dir/${Vname}_look_ahead_routing_genvar.v"; open $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } print $fd autogen_warning(); print $fd get_license_header($top); - $route_str="\talways@(*)begin + $route_str="\talways@(*)begin \t\tdestport=0; \t\tcase(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. "; @@ -1109,58 +1100,58 @@ sub generate_routing_v { foreach my $router (@routers){ - my $PNUM=$self->object_get_attribute($router,"PNUM"); - my $router_num=get_scolar_pos($router,@routers); - my %route; - $route_str=$route_str."\tif(CURRENT_R_ADDR == $router_num) begin :R$router_num -\t\talways@(*)begin + my $PNUM=$self->object_get_attribute($router,"PNUM"); + my $router_num=get_scolar_pos($router,@routers); + my %route; + $route_str=$route_str."\tif(CURRENT_R_ADDR == $router_num) begin :R$router_num +\t\talways@(*)begin \t\t\tdestport= 0; \t\t\tcase({src_e_addr,dest_e_addr}) "; - # for each src-dest check if $router include in path - foreach my $src (@ends){ - foreach my $dst (@ends){ - my $ref = $self->object_get_attribute('Route',"${src}::$dst"); - next if(!defined $ref); - my @path = @{$ref}; - my $loc= get_scolar_pos($router,@path); - next if(!defined $loc);# this router does not exist in path skip it - my $next_router1=$path[$loc+1]; - my $next_router2=$path[$loc+2]; - next if(!defined $next_router2); - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); - next if(!defined $p1); - my $src_num=get_scolar_pos($src,@ends); - my $dest_num = get_scolar_pos($dst,@ends); - $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; - - #print "@path\n"; - #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; - #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; - #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; - #print"***************************\n"; - - } - } - foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin + # for each src-dest check if $router include in path + foreach my $src (@ends){ + foreach my $dst (@ends){ + my $ref = $self->object_get_attribute('Route',"${src}::$dst"); + next if(!defined $ref); + my @path = @{$ref}; + my $loc= get_scolar_pos($router,@path); + next if(!defined $loc);# this router does not exist in path skip it + my $next_router1=$path[$loc+1]; + my $next_router2=$path[$loc+2]; + next if(!defined $next_router2); + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); + next if(!defined $p1); + my $src_num=get_scolar_pos($src,@ends); + my $dest_num = get_scolar_pos($dst,@ends); + $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; + + #print "@path\n"; + #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; + #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; + #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; + #print"***************************\n"; + + } + } + foreach my $q (sort {$a <=> $b} keys %route){ + $route_str=$route_str."\t\t\t$route{$q}: begin \t\t\t\tdestport= $q; \t\t\tend -"; - - } - - $route_str=$route_str."\t\t\tendcase\n\t\tend\n\tend//R$router_num\n\n"; - } - $route_str=$route_str."\tendgenerate\n"; - +"; + + } + + $route_str=$route_str."\t\t\tendcase\n\t\tend\n\tend//R$router_num\n\n"; + } + $route_str=$route_str."\tendgenerate\n"; + print $fd " `include \"pronoc_def.v\" /***************************** -* ${Vname}_look_ahead_routing_genvar +* ${Vname}_look_ahead_routing_genvar ******************************/ module ${Vname}_look_ahead_routing_genvar #( \tparameter RAw = 3, @@ -1181,35 +1172,35 @@ sub generate_routing_v { \toutput [DSTPw-1 :0] destport; \tinput reset,clk; - reg [EAw-1 :0] dest_e_addr_delay; - reg [EAw-1 :0] src_e_addr_delay; + reg [EAw-1 :0] dest_e_addr_delay; + reg [EAw-1 :0] src_e_addr_delay; - always @ (`pronoc_clk_reset_edge )begin + always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin - dest_e_addr_delay<={EAw{1'b0}}; - src_e_addr_delay<={EAw{1'b0}}; - end else begin - dest_e_addr_delay<=dest_e_addr; - src_e_addr_delay<=src_e_addr; - end - end - - ${name}_look_ahead_routing_genvar_comb #( - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw), - .CURRENT_R_ADDR(CURRENT_R_ADDR) - ) - lkp_cmb - ( - - .dest_e_addr(dest_e_addr_delay), - .src_e_addr(src_e_addr_delay), - .destport(destport) - ); - - - + dest_e_addr_delay<={EAw{1'b0}}; + src_e_addr_delay<={EAw{1'b0}}; + end else begin + dest_e_addr_delay<=dest_e_addr; + src_e_addr_delay<=src_e_addr; + end + end + + ${name}_look_ahead_routing_genvar_comb #( + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw), + .CURRENT_R_ADDR(CURRENT_R_ADDR) + ) + lkp_cmb + ( + + .dest_e_addr(dest_e_addr_delay), + .src_e_addr(src_e_addr_delay), + .destport(destport) + ); + + + endmodule /******************* @@ -1237,7 +1228,7 @@ sub generate_routing_v { $route_str - + endmodule @@ -1252,17 +1243,17 @@ sub generate_routing_v { sub generate_connection_v{ - my($self,$info,$dir)=@_; - - #create connection top file - my $name=$self->object_get_attribute('save_as'); + my($self,$info,$dir)=@_; + + #create connection top file + my $name=$self->object_get_attribute('save_as'); - my $r; - my $top="$dir/${name}_connection.sv"; + my $r; + my $top="$dir/${name}_connection.sv"; open my $fd, ">$top" or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; + add_colored_info($info,"Error in creating $top: $r",'red'); + return; } print $fd autogen_warning(); print $fd get_license_header($top); @@ -1278,26 +1269,26 @@ sub generate_connection_v{ my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - + my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); my $MAX_P=0; foreach my $p (@routers){ - my $Pnum=$self->object_get_attribute("$p",'PNUM'); - $MAX_P =$Pnum if($Pnum>$MAX_P ); - } + my $Pnum=$self->object_get_attribute("$p",'PNUM'); + $MAX_P =$Pnum if($Pnum>$MAX_P ); + } my $NE= scalar @ends; my $NR= scalar @routers; - - - my @nodes=get_list_of_all_routers($self); - my $i=0; - - my $ports="\treset, + + + my @nodes=get_list_of_all_routers($self); + my $i=0; + + my $ports="\treset, \tclk, \tstart_i, \tstart_o, @@ -1324,116 +1315,116 @@ sub generate_connection_v{ "; - my $router_wires=""; - my $endps_wires=""; - - - - - foreach my $d (@ports){ - my $range = ($d->{width} eq 1)? " " : " [$d->{width}-1 : 0]"; - my $pdef_range = ($d->{pwidth} eq 1)? "[NE-1 : 0]" : "[$d->{pwidth}-1 : 0]"; - my $pdef_range2 = ($d->{pwidth} eq 1)? "" : "[NE-1 : 0]"; - #$ports=$ports.",\n\trouter_$d->{name},\n\trouter_$d->{connect}"; - my $type=$d->{type}; - my $ctype= ($type eq 'input')? 'output' : 'input'; - if( $d->{endp} eq "yes"){ - #$ports_def=$ports_def."\t$type\t$pdef_range ni_$d->{pname} $pdef_range2;\n"; - #$ports_def=$ports_def."\t$ctype\t$pdef_range ni_$d->{pconnect} $pdef_range2;\n"; - #$ports=$ports.",\n\tni_$d->{pname},\n\tni_$d->{pconnect}"; - } - if($d->{width} eq 1){ - #$ports_def=$ports_def. "\t$type\t[NR-1 :0] router_$d->{name};\n"; - #$ports_def=$ports_def. "\t$ctype\t[NR-1 :0] router_$d->{connect};\n"; - }else{ - #$ports_def=$ports_def. "\t$type\t$range router_$d->{name} [NR-1 :0];\n"; - #$ports_def=$ports_def. "\t$ctype\t$range router_$d->{connect} [NR-1 :0];\n"; - } - - - } - - - - - my $routers=' - genvar i; - generate - '; - my $offset=0; - my $assign=""; - my $R_num=0; - for ( my $i=2;$i<=12; $i++){ - my $n= $self->object_get_attribute("ROUTER${i}","NUM"); - $n=0 if(!defined $n); - if($n>0){ - my $router_pos= ($offset==0)? 'i' : "i+$offset"; - my $instant=get_router_genvar_instance_v($self,$i,$router_pos,$NE,$NR,$MAX_P); - - $routers=$routers." + my $router_wires=""; + my $endps_wires=""; + + + + + foreach my $d (@ports){ + my $range = ($d->{width} eq 1)? " " : " [$d->{width}-1 : 0]"; + my $pdef_range = ($d->{pwidth} eq 1)? "[NE-1 : 0]" : "[$d->{pwidth}-1 : 0]"; + my $pdef_range2 = ($d->{pwidth} eq 1)? "" : "[NE-1 : 0]"; + #$ports=$ports.",\n\trouter_$d->{name},\n\trouter_$d->{connect}"; + my $type=$d->{type}; + my $ctype= ($type eq 'input')? 'output' : 'input'; + if( $d->{endp} eq "yes"){ + #$ports_def=$ports_def."\t$type\t$pdef_range ni_$d->{pname} $pdef_range2;\n"; + #$ports_def=$ports_def."\t$ctype\t$pdef_range ni_$d->{pconnect} $pdef_range2;\n"; + #$ports=$ports.",\n\tni_$d->{pname},\n\tni_$d->{pconnect}"; + } + if($d->{width} eq 1){ + #$ports_def=$ports_def. "\t$type\t[NR-1 :0] router_$d->{name};\n"; + #$ports_def=$ports_def. "\t$ctype\t[NR-1 :0] router_$d->{connect};\n"; + }else{ + #$ports_def=$ports_def. "\t$type\t$range router_$d->{name} [NR-1 :0];\n"; + #$ports_def=$ports_def. "\t$ctype\t$range router_$d->{connect} [NR-1 :0];\n"; + } + + + } + + + + + my $routers=' + genvar i; + generate + '; + my $offset=0; + my $assign=""; + my $R_num=0; + for ( my $i=2;$i<=12; $i++){ + my $n= $self->object_get_attribute("ROUTER${i}","NUM"); + $n=0 if(!defined $n); + if($n>0){ + my $router_pos= ($offset==0)? 'i' : "i+$offset"; + my $instant=get_router_genvar_instance_v($self,$i,$router_pos,$NE,$NR,$MAX_P); + + $routers=$routers." \tfor( i=0; i<$n; i=i+1) begin : router_${i}_port_lp \t\t$instant \tend - "; - - for ( my $j=0;$j<$n; $j++){ - my $rname ="ROUTER${i}_$j"; - my ($ass_v, $r2r_h,$r2e_h, $int_h,$gnd_h,$R_num)= get_wires_assignment_genvar_v($self,$rname,1,undef,$R_num); - $assign=$assign.$ass_v; - } - - $offset+= $n; - - } - } - - - - foreach my $end (@ends){ - #$assign=$assign.get_wires_assignment_genvar_v($self,$end,1); - } - - $assign=$assign."\n"; - - - my $pos=0; - $assign.="//The router address connected to each endpoint\n"; - foreach my $end (@ends){ - my $connect = $self->{$end}{'PCONNECT'}{'Port[0]'}; - my ($Rname,$Rport)=split(/\s*,\s*/,$connect); - my $R = get_scolar_pos($Rname,@routers); - my $rname = $self->object_get_attribute("$Rname","NAME"); - my $tname = $self->object_get_attribute("$end","NAME"); - $assign=$assign."\tassign er_addr [$pos] = $R; //$tname -> $rname\n"; - $pos++; - } - - $assign=$assign."\n"; - - $pos=0; - foreach my $router (@routers){ - my $rname = $self->object_get_attribute("$router","NAME"); - $assign=$assign."\tassign current_r_addr [$pos] = $pos; // $rname\n"; - $pos++; - } - - - - - print $fd " + "; + + for ( my $j=0;$j<$n; $j++){ + my $rname ="ROUTER${i}_$j"; + my ($ass_v, $r2r_h,$r2e_h, $int_h,$gnd_h,$R_num)= get_wires_assignment_genvar_v($self,$rname,1,undef,$R_num); + $assign=$assign.$ass_v; + } + + $offset+= $n; + + } + } + + + + foreach my $end (@ends){ + #$assign=$assign.get_wires_assignment_genvar_v($self,$end,1); + } + + $assign=$assign."\n"; + + + my $pos=0; + $assign.="//The router address connected to each endpoint\n"; + foreach my $end (@ends){ + my $connect = $self->{$end}{'PCONNECT'}{'Port[0]'}; + my ($Rname,$Rport)=split(/\s*,\s*/,$connect); + my $R = get_scolar_pos($Rname,@routers); + my $rname = $self->object_get_attribute("$Rname","NAME"); + my $tname = $self->object_get_attribute("$end","NAME"); + $assign=$assign."\tassign er_addr [$pos] = $R; //$tname -> $rname\n"; + $pos++; + } + + $assign=$assign."\n"; + + $pos=0; + foreach my $router (@routers){ + my $rname = $self->object_get_attribute("$router","NAME"); + $assign=$assign."\tassign current_r_addr [$pos] = $pos; // $rname\n"; + $pos++; + } + + + + + print $fd " module ${name}_connection #( - parameter NOC_ID=0 + parameter NOC_ID=0 )( $ports ); - `NOC_CONF + `NOC_CONF - - localparam - P= MAX_P, + + localparam + P= MAX_P, PV = V * P, PFw = P * Fw, CONG_ALw = CONGw * P, @@ -1449,7 +1440,7 @@ sub generate_connection_v{ $assign - start_delay_gen #( + start_delay_gen #( .NC(NE) ) delay_gen @@ -1463,61 +1454,61 @@ sub generate_connection_v{ endmodule "; - - add_info($info,"$top file is created\n "); - close $fd; - - - + + add_info($info,"$top file is created\n "); + close $fd; + + + } sub add_noc_custom_h{ - my ($self,$info,$dir)=@_; - my $name=$self->object_get_attribute('save_as'); - my $str=" - //do not modify this line ===${name}=== - #ifdef IS_${name}_noc - #include \"${name}_noc.h\" - #endif - "; - - - my $file = "$dir/../../../src_verilator/topology/custom/custom.h"; - #check if ***$name**** exist in the file - unless (-f $file){ - add_colored_info($info,"$file dose not exist\n",'red'); - return; - } - my $r = check_file_has_string($file, "===${name}==="); - if ($r==1){ - add_info($info,"The instance ${name}_noc exists in $file. This file is not modified\n ",'blue'); - - }else{ - my $text = read_file_cntent($file,' '); + my ($self,$info,$dir)=@_; + my $name=$self->object_get_attribute('save_as'); + my $str=" + //do not modify this line ===${name}=== + #ifdef IS_${name}_noc + #include \"${name}_noc.h\" + #endif + "; + + + my $file = "$dir/../../../src_verilator/topology/custom/custom.h"; + #check if ***$name**** exist in the file + unless (-f $file){ + add_colored_info($info,"$file dose not exist\n",'red'); + return; + } + my $r = check_file_has_string($file, "===${name}==="); + if ($r==1){ + add_info($info,"The instance ${name}_noc exists in $file. This file is not modified\n ",'blue'); + + }else{ + my $text = read_file_cntent($file,' '); my @a = split('endgenerate',$text); save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${name}_noc has been added to the file\n ",'blue'); - - } - + + } + } sub add_routing_instance_v{ - my ($self,$info,$dir)=@_; - my $name=$self->object_get_attribute('save_as'); - my $rname=$self->object_get_attribute('routing_name'); - my $Vname="T${name}R${rname}"; - ##################################### - # custom_ni_routing - #################################### - my $str=" - //do not modify this line ===${Vname}=== + my ($self,$info,$dir)=@_; + my $name=$self->object_get_attribute('save_as'); + my $rname=$self->object_get_attribute('routing_name'); + my $Vname="T${name}R${rname}"; + ##################################### + # custom_ni_routing + #################################### + my $str=" + //do not modify this line ===${Vname}=== if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : $Vname ${Vname}_conventional_routing #( - .RAw(RAw), + .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) ) @@ -1528,40 +1519,40 @@ sub add_routing_instance_v{ .destport(destport) ); - end + end endgenerate - + "; - - my $file = "$dir/../common/custom_ni_routing.v"; - #check if ***$name**** exist in the file - unless (-f $file){ - add_colored_info($info,"$file dose not exist\n",'red'); - return; - } - my $r = check_file_has_string($file, "===${Vname}==="); - if ($r==1){ - add_info($info,"The instance ${Vname}_conventional_routing exists in $file. This file is not modified\n ",'blue'); - - }else{ - my $text = read_file_cntent($file,' '); + + my $file = "$dir/../common/custom_ni_routing.v"; + #check if ***$name**** exist in the file + unless (-f $file){ + add_colored_info($info,"$file dose not exist\n",'red'); + return; + } + my $r = check_file_has_string($file, "===${Vname}==="); + if ($r==1){ + add_info($info,"The instance ${Vname}_conventional_routing exists in $file. This file is not modified\n ",'blue'); + + }else{ + my $text = read_file_cntent($file,' '); my @a = split('endgenerate',$text); save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${Vname}_conventional_routing has been added to the file\n ",'blue'); - - } - - - - ##################################### - # custom_lkh_routing - #################################### - $str=" - //do not modify this line ===${Vname}=== + + } + + + + ##################################### + # custom_lkh_routing + #################################### + $str=" + //do not modify this line ===${Vname}=== if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : ${Vname} - ${Vname}_look_ahead_routing #( + ${Vname}_look_ahead_routing #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) @@ -1576,42 +1567,42 @@ sub add_routing_instance_v{ .clk(clk) ); - end + end endgenerate - + "; - - $file = "$dir/../common/custom_lkh_routing.v"; - - unless (-f $file){ - add_colored_info($info,"$file dose not exist\n",'red'); - return; - } - $r = check_file_has_string($file, "===${Vname}==="); - if ($r==1){ - add_info($info,"The instance ${Vname}_look_ahead_routing exist in $file. This file is not modified\n ",'blue'); - - }else{ - my $text = read_file_cntent($file,' '); + + $file = "$dir/../common/custom_lkh_routing.v"; + + unless (-f $file){ + add_colored_info($info,"$file dose not exist\n",'red'); + return; + } + $r = check_file_has_string($file, "===${Vname}==="); + if ($r==1){ + add_info($info,"The instance ${Vname}_look_ahead_routing exist in $file. This file is not modified\n ",'blue'); + + }else{ + my $text = read_file_cntent($file,' '); my @a = split('endgenerate',$text); - save_file($file,"$a[0] $str $a[1]"); + save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${Vname}_look_ahead_routing has been added to the file\n ",'blue'); - - } - + + } + } sub add_noc_instance_v{ - my ($self,$info,$dir)=@_; - my $name=$self->object_get_attribute('save_as'); - - ##################################### - # add connection - #################################### - - my $ports="\t\t.reset(reset), + my ($self,$info,$dir)=@_; + my $name=$self->object_get_attribute('save_as'); + + ##################################### + # add connection + #################################### + + my $ports="\t\t.reset(reset), \t\t.clk(clk), \t\t.start_i(start_i), \t\t.start_o(start_o), @@ -1624,111 +1615,111 @@ sub add_noc_instance_v{ "; - - + + - - my $str=" - //do not modify this line ===${name}=== + + my $str=" + //do not modify this line ===${name}=== if(TOPOLOGY == \"$name\" ) begin : T$name ${name}_connection #( - .NOC_ID(NOC_ID) - ) connection ( + .NOC_ID(NOC_ID) + ) connection ( $ports ); - end + end endgenerate - + "; - - #my $file = "$dir/../common/custom_noc_connection.sv"; - #check if ***$name**** exist in the file - #unless (-f $file){ - # add_colored_info($info,"$file dose not exist\n",'red'); - # return; - #} - #my $r = check_file_has_string($file, "===${name}==="); - #if ($r==1){ - #add_info($info,"The instance ${name}_connection exists in $file. This file is not modified\n ",'blue'); - - #}else{ - #my $text = read_file_cntent($file,' '); + + #my $file = "$dir/../common/custom_noc_connection.sv"; + #check if ***$name**** exist in the file + #unless (-f $file){ + # add_colored_info($info,"$file dose not exist\n",'red'); + # return; + #} + #my $r = check_file_has_string($file, "===${name}==="); + #if ($r==1){ + #add_info($info,"The instance ${name}_connection exists in $file. This file is not modified\n ",'blue'); + + #}else{ + #my $text = read_file_cntent($file,' '); # my @a = split('endgenerate',$text); # save_file($file,"$a[0] $str $a[1]"); # add_info($info,"$file has been modified. The ${name}_connection has been added to the file\n ",'blue'); - - #} - - - ##################################### - # add NoC - #################################### - - - my $param_str ="\t\t.TOPOLOGY(TOPOLOGY), + + #} + + + ##################################### + # add NoC + #################################### + + + my $param_str ="\t\t.TOPOLOGY(TOPOLOGY), \t\t.ROUTE_NAME(ROUTE_NAME)"; my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; - foreach my $d (@parameters){ - $param_str = $param_str.",\n\t\t.$d->{param_name}($d->{param_name})"; - } - - $ports="\t\t.reset(reset), + foreach my $d (@parameters){ + $param_str = $param_str.",\n\t\t.$d->{param_name}($d->{param_name})"; + } + + $ports="\t\t.reset(reset), \t\t.clk(clk)"; - - - $str=" - //do not modify this line ===${name}=== + + + $str=" + //do not modify this line ===${name}=== if(TOPOLOGY == \"$name\" ) begin : T$name - ${name}_noc_genvar #( - .NOC_ID(NOC_ID) - ) the_noc ( - .reset(reset), - .clk(clk), - .chan_in_all(chan_in_all), - .chan_out_all(chan_out_all), - .router_event(router_event) - ); + ${name}_noc_genvar #( + .NOC_ID(NOC_ID) + ) the_noc ( + .reset(reset), + .clk(clk), + .chan_in_all(chan_in_all), + .chan_out_all(chan_out_all), + .router_event(router_event) + ); end endgenerate - - "; - - - - my $file = "$dir/../common/custom_noc_top.sv"; - #check if ***$name**** exist in the file - unless (-f $file){ - add_colored_info($info,"$file dose not exist\n",'red'); - return; - } - my $r = check_file_has_string($file, "===${name}==="); - if ($r==1){ - add_info($info,"The instance ${name}_noc exists in $file. This file is not modified\n ",'blue'); - - }else{ - my $text = read_file_cntent($file,' '); + + "; + + + + my $file = "$dir/../common/custom_noc_top.sv"; + #check if ***$name**** exist in the file + unless (-f $file){ + add_colored_info($info,"$file dose not exist\n",'red'); + return; + } + my $r = check_file_has_string($file, "===${name}==="); + if ($r==1){ + add_info($info,"The instance ${name}_noc exists in $file. This file is not modified\n ",'blue'); + + }else{ + my $text = read_file_cntent($file,' '); my @a = split('endgenerate',$text); save_file($file,"$a[0] $str $a[1]"); - add_info($info,"$file has been modified. The ${name}_noc has been added to the file\n ",'blue'); - } - - - - - - - - - - - + add_info($info,"$file has been modified. The ${name}_noc has been added to the file\n ",'blue'); + } + + + + + + + + + + + } diff --git a/mpsoc/rtl/src_noc/fattree_noc_top.sv b/mpsoc/rtl/src_noc/fattree_noc_top.sv index b78f036..8522913 100644 --- a/mpsoc/rtl/src_noc/fattree_noc_top.sv +++ b/mpsoc/rtl/src_noc/fattree_noc_top.sv @@ -1,58 +1,76 @@ `include "pronoc_def.v" -/************************************** -* Module: fattree -* Date:2019-01-01 -* Author: alireza -* -* -Description: - - FatTree - - Each level of the hierarchical indirect Network has - k^(l-1) Routers. The Routers are organized such that - each node has k descendents, and each parent is - replicated k times. - most routers has 2K ports, excep the top level has only K - -***************************************/ - +/********************************************************************** +** File: fattree_noc_top.v +** +** Copyright (C) 2014-2017 Alireza Monemi +** +** This file is part of ProNoC +** +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. +** +** ProNoC 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 Lesser General +** Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . +** +** +** Description: +** +** Fat-Tree NoC Top Module +** +** This module implements a hierarchical indirect Fat-Tree +** Network-on-Chip (NoC) topology. The network is organized +** into multiple levels, with each level containing k^(l-1) +** routers, where *k* is the radix and *l* is the current level. +** +** Key Features: +** - Each router connects to *k* child routers in the level below. +** - Each parent router is replicated *k* times to ensure +** balanced connectivity. +** - Most routers have 2K ports, except for the top-level routers, +** which have only K ports due to reduced fan-out requirements. +** +**************************************************************/ module fattree_noc_top #( parameter NOC_ID=0 ) ( - reset, - clk, - chan_in_all, - chan_out_all, - router_event + reset, + clk, + chan_in_all, + chan_out_all, + router_event ); - - `NOC_CONF - - input clk,reset; - //Endpoints ports - input smartflit_chanel_t chan_in_all [NE-1 : 0]; - output smartflit_chanel_t chan_out_all [NE-1 : 0]; - //Events - output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - - //all routers port - smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; - smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; - - - - localparam - PV = V * MAX_P, - PFw = MAX_P * Fw, - NRL= NE/K, //number of router in each layer - CONG_ALw = CONGw * MAX_P, - PLKw = MAX_P * LKw, - PLw = MAX_P * Lw, - PRAw = MAX_P * RAw; // {layer , Pos} width + + `NOC_CONF + + input clk,reset; + //Endpoints ports + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; + //Events + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; + + //all routers port + smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; + smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; + + localparam + PV = V * MAX_P, + PFw = MAX_P * Fw, + NRL= NE/K, //number of router in each layer + CONG_ALw = CONGw * MAX_P, + PLKw = MAX_P * LKw, + PLw = MAX_P * Lw, + PRAw = MAX_P * RAw; // {layer , Pos} width - function integer addrencode; + function integer addrencode; input integer pos,k,n,kw; integer pow,i,tmp;begin addrencode=0; @@ -66,127 +84,110 @@ module fattree_noc_top #( end end endfunction - + wire [LKw-1 : 0] current_pos_addr [NR-1 :0]; - wire [Lw-1 : 0] current_layer_addr [NR-1 :0]; + wire [Lw-1 : 0] current_layer_addr [NR-1 :0]; wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; -//add roots - -genvar pos,level,port; - - - -generate -for( pos=0; pos0 )? ctrl_in[i].hetero_ovc_presence : {V{1'b1}}; assign ovc_avalable_all_masked [(i+1)*V-1 : i*V] = (SMART_EN)? //TODO for smart, we need to make sure, the hetrro ovc presence in all down stream routers - ovc_avalable_all [(i+1)*V-1 : i*V] & ~smart_ctrl_in[i].mask_available_ovc & ctrl_in[i].hetero_ovc_presence : - ovc_avalable_all [(i+1)*V-1 : i*V] & ctrl_in[i].hetero_ovc_presence; + ovc_avalable_all [(i+1)*V-1 : i*V] & ~smart_ctrl_in[i].mask_available_ovc & hetero_ovc_peresence_all[(i+1)*V-1 : i*V] : + ovc_avalable_all [(i+1)*V-1 : i*V] & hetero_ovc_peresence_all[(i+1)*V-1 : i*V]; assign non_vsa_ivc_num_getting_ovc_grant_all [(i+1)*V-1 : i*V] = ssa_ctrl_in[i].ivc_num_getting_ovc_grant | smart_ctrl_in[i].ivc_num_getting_ovc_grant; for(j=0;j< V;j=j+1) begin :V_ assign ivc_request_all[i*V+j] = ivc_info[i][j].ivc_req; diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 9c08930..df88a45 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -1,7 +1,7 @@ `include "pronoc_def.v" /********************************************************************** -** File: mesh_torus_noc.v +** File: mesh_torus_noc_top.v ** ** Copyright (C) 2014-2017 Alireza Monemi ** @@ -27,220 +27,146 @@ ** **************************************************************/ - -//`define router_id(x,y) ((y * NX) + x) -//`define endp_id(x,y,l) ((y * NX) + x) * NL + l - - - module mesh_torus_noc_top #( - parameter NOC_ID=0 + parameter NOC_ID=0 ) ( reset, - clk, + clk, chan_in_all, chan_out_all, router_event ); - - `NOC_CONF - input clk,reset; - //Endpoints ports - input smartflit_chanel_t chan_in_all [NE-1 : 0]; - output smartflit_chanel_t chan_out_all [NE-1 : 0]; - - //Events - output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - - //all routers port - smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; - smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; + `NOC_CONF - wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; + localparam [0:0] + /* verilator lint_off WIDTH */ + IS_LINE = (TOPOLOGY == "LINE"), + IS_RING = (TOPOLOGY == "RING"), + IS_MESH = (TOPOLOGY == "MESH"), + IS_FMESH= (TOPOLOGY == "FMESH"), + IS_TORUS= (TOPOLOGY == "TORUS"); + /* verilator lint_on WIDTH */ - genvar x,y,l; - generate - /* verilator lint_off WIDTH */ - if( TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin : ring_line - /* verilator lint_on WIDTH */ - for (x=0; x0)begin :not_first_x - assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; - end else begin :first_x - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "LINE") begin : line_first_x - /* verilator lint_on WIDTH */ - assign router_chan_in[x][BACKWARD]={SMARTFLIT_CHANEL_w{1'b0}}; - end else begin : ring_first_x - assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; - end - end - - // connect other local ports - for (l=0; l0) begin : not_first_y - assign router_chan_in[fmesh_router_id(x,y)][NORTH] = router_chan_out [fmesh_router_id(x,(y-1))][SOUTH]; - end else begin :first_y - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin : first_y_mesh - /* verilator lint_on WIDTH */ - assign router_chan_in[fmesh_router_id(x,y)][NORTH] = {SMARTFLIT_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :first_y_torus - /* verilator lint_on WIDTH */ - assign router_chan_in[fmesh_router_id(x,y)][NORTH] = router_chan_out [fmesh_router_id(x,(NY-1))][SOUTH]; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FMESH") begin : first_y_fmesh //connect to endp - /* verilator lint_on WIDTH */ - localparam NORTH_ID = NX*NY*NL + x; - assign router_chan_in [fmesh_router_id(x,y)][NORTH] = chan_in_all [NORTH_ID]; - assign chan_out_all [NORTH_ID] = router_chan_out [fmesh_router_id(x,y)][NORTH]; - end//topology - end//y>0 + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(x), + .P (MAX_P) + ) the_router ( + .current_r_id(x), + .current_r_addr(current_r_addr [x]), + .chan_in(router_chan_in [x]), + .chan_out(router_chan_out[x]), + .router_event(router_event[x]), + .clk(clk), + .reset(reset) + ); + assign router_chan_in[x][FORWARD] = + (x < NX-1) ? router_chan_out[x+1][BACKWARD] : + (IS_LINE) ? {SMARTFLIT_CHANEL_w{1'b0}} : router_chan_out[0][BACKWARD]; - if(x>0)begin :not_first_x - assign router_chan_in[fmesh_router_id(x,y)][WEST] = router_chan_out [fmesh_router_id((x-1),y)][EAST]; - end else begin :first_x - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin :first_x_mesh - /* verilator lint_on WIDTH */ - assign router_chan_in[fmesh_router_id(x,y)][WEST] = {SMARTFLIT_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :first_x_torus - /* verilator lint_on WIDTH */ - assign router_chan_in[fmesh_router_id(x,y)][WEST] = router_chan_out [fmesh_router_id((NX-1),y)][EAST] ; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FMESH") begin : first_x_fmesh //connect to endp - /* verilator lint_on WIDTH */ - localparam WEST_ID = NX*NY*NL +2*NX + y; - assign router_chan_in [fmesh_router_id(x,y)][WEST] = chan_in_all [WEST_ID]; - assign chan_out_all [WEST_ID] = router_chan_out [fmesh_router_id(x,y)][WEST]; - end//topology - end + assign router_chan_in[x][BACKWARD] = + (x > 0) ? router_chan_out[x-1][FORWARD] : + (IS_LINE) ? {SMARTFLIT_CHANEL_w{1'b0}} : router_chan_out[NX-1][FORWARD]; - if(y < NY-1) begin : firsty - assign router_chan_in[fmesh_router_id(x,y)][SOUTH] = router_chan_out [fmesh_router_id(x,(y+1))][NORTH]; - end else begin : lasty - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin :ly_mesh - /* verilator lint_on WIDTH */ - assign router_chan_in[fmesh_router_id(x,y)][SOUTH]= {SMARTFLIT_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :ly_torus - /* verilator lint_on WIDTH */ - assign router_chan_in[fmesh_router_id(x,y)][SOUTH]= router_chan_out [fmesh_router_id(x,0)][NORTH]; - end else if(TOPOLOGY == "FMESH") begin : ly_fmesh //connect to endp - /* verilator lint_on WIDTH */ - localparam SOUTH_ID = NX*NY*NL + NX + x; - assign router_chan_in [fmesh_router_id(x,y)][SOUTH] = chan_in_all [SOUTH_ID]; - assign chan_out_all [SOUTH_ID] = router_chan_out [fmesh_router_id(x,y)][SOUTH]; - end//topology - end - + // connect other local ports + for (l=0; l 0 ) ? router_chan_out[fmesh_router_id(x, y-1)][SOUTH] : //not_first_y + (IS_MESH) ? {SMARTFLIT_CHANEL_w{1'b0}} : //first_y_mesh + (IS_TORUS)? router_chan_out[fmesh_router_id(x, NY-1)][SOUTH] : //first_y_torus + chan_in_all[NORTH_ID]; //first_y_fmesh + assign router_chan_in[fmesh_router_id(x, y)][WEST] = + (x > 0) ? router_chan_out[fmesh_router_id(x-1, y)][EAST] : //not_first_x + (IS_MESH) ? {SMARTFLIT_CHANEL_w{1'b0}} : //first_x_mesh + (IS_TORUS)? router_chan_out[fmesh_router_id(NX-1, y)][EAST] : //first_x_torus + chan_in_all[WEST_ID]; //first_x_fmesh + assign router_chan_in[fmesh_router_id(x, y)][SOUTH] = + (y < NY-1)? router_chan_out[fmesh_router_id(x, y+1)][NORTH] : //not_last_y + (IS_MESH)? {SMARTFLIT_CHANEL_w{1'b0}} : //last_y_mesh + (IS_TORUS)? router_chan_out[fmesh_router_id(x, 0)][NORTH] : //last_y_torus + chan_in_all[SOUTH_ID]; //last_y_fmesh + if(IS_FMESH) begin :IS_FMESH //connect to endpoints + if(x == NX-1) assign chan_out_all [EAST_ID] = router_chan_out [fmesh_router_id(x,y)][EAST]; + if(y ==0 ) assign chan_out_all [NORTH_ID] = router_chan_out [fmesh_router_id(x,y)][NORTH]; + if (x ==0 ) assign chan_out_all [WEST_ID] = router_chan_out[fmesh_router_id(x, y)][WEST]; + if(y == NY-1 ) assign chan_out_all [SOUTH_ID] = router_chan_out[fmesh_router_id(x, y)][SOUTH]; + end + // endpoint(s) connection + // connect other local ports + for (l=0; l. ** ** -** Description: -** the NoC top module. +** Description: +** This is the top-level NoC (Network-on-Chip) module. It generates various network topologies, +** including mesh, torus, ring, line, fattree, bintree or a user-defined custom topology, +** by interconnecting routers. ** **************************************************************/ - - -module noc_top #( - parameter NOC_ID=0 +module noc_top #( + parameter NOC_ID=0 ) ( - reset, - clk, - chan_in_all, - chan_out_all, - router_event + reset, + clk, + chan_in_all, + chan_out_all, + router_event ); - - `NOC_CONF - - input clk,reset; - //Endpoints ports - input smartflit_chanel_t chan_in_all [NE-1 : 0]; - output smartflit_chanel_t chan_out_all [NE-1 : 0]; - //Events - output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - - - - - generate - /* verilator lint_off WIDTH */ - if (TOPOLOGY == "MESH" || TOPOLOGY == "FMESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin : tori_noc - /* verilator lint_on WIDTH */ - mesh_torus_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( - .reset (reset ), - .clk (clk ), - .chan_in_all (chan_in_all ), - .chan_out_all (chan_out_all ), - .router_event (router_event ) - ); - end else if (TOPOLOGY == "FATTREE") begin : fat_ + `NOC_CONF + + input clk,reset; + //Endpoints ports + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; + //Events + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; + generate + /* verilator lint_off WIDTH */ + if (TOPOLOGY == "MESH" || TOPOLOGY == "FMESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin : tori_noc + /* verilator lint_on WIDTH */ + mesh_torus_noc_top #( + .NOC_ID(NOC_ID) + ) noc_top ( + .reset (reset ), + .clk (clk ), + .chan_in_all (chan_in_all ), + .chan_out_all (chan_out_all ), + .router_event (router_event ) + ); + /* verilator lint_off WIDTH */ + end else if (TOPOLOGY == "FATTREE") begin : fat_ + /* verilator lint_on WIDTH */ fattree_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( - .reset (reset ), - .clk (clk ), - .chan_in_all (chan_in_all ), - .chan_out_all (chan_out_all ), - .router_event (router_event ) + .NOC_ID(NOC_ID) + ) noc_top ( + .reset (reset ), + .clk (clk ), + .chan_in_all (chan_in_all ), + .chan_out_all (chan_out_all ), + .router_event (router_event ) ); - - + /* verilator lint_off WIDTH */ end else if (TOPOLOGY == "TREE") begin : tree_ + /* verilator lint_on WIDTH */ tree_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( - .reset (reset ), - .clk (clk ), - .chan_in_all (chan_in_all ), - .chan_out_all (chan_out_all ), - .router_event (router_event ) + .NOC_ID(NOC_ID) + ) noc_top ( + .reset (reset ), + .clk (clk ), + .chan_in_all (chan_in_all ), + .chan_out_all (chan_out_all ), + .router_event (router_event ) ); + /* verilator lint_off WIDTH */ end else if (TOPOLOGY == "STAR") begin : star_ - star_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( - .reset (reset ), - .clk (clk ), - .chan_in_all (chan_in_all ), - .chan_out_all (chan_out_all ), - .router_event (router_event ) - ); - + /* verilator lint_on WIDTH */ + star_noc_top #( + .NOC_ID(NOC_ID) + ) noc_top ( + .reset (reset ), + .clk (clk ), + .chan_in_all (chan_in_all ), + .chan_out_all (chan_out_all ), + .router_event (router_event ) + ); end else begin :custom_ - - custom_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( - .reset (reset ), - .clk (clk ), - .chan_in_all (chan_in_all ), - .chan_out_all (chan_out_all ), - .router_event (router_event ) - ); - - end + + custom_noc_top #( + .NOC_ID(NOC_ID) + ) noc_top ( + .reset (reset ), + .clk (clk ), + .chan_in_all (chan_in_all ), + .chan_out_all (chan_out_all ), + .router_event (router_event ) + ); + end endgenerate endmodule - - - - - -/********************************** -The noc top module that can be called in Verilog module. - -***********************************/ - +/************************** + * noc_top_v: + * This module instantiates noc_top and + * serves as the top module in Verilator simulation. + * It resolves the Verilator error caused by + * noc_top being used in another module, + * preventing it from being defined as the top module. + **************************/ module noc_top_v #( - parameter NOC_ID=0 + parameter NOC_ID=0 )( flit_out_all, flit_out_wr_all, @@ -134,47 +129,42 @@ module noc_top_v #( credit_out_all, reset, clk - ); - - `NOC_CONF - - input clk,reset; - output [NEFw-1 : 0] flit_out_all; +); + + `NOC_CONF + + input clk,reset; + output [NEFw-1 : 0] flit_out_all; output [NE-1 : 0] flit_out_wr_all; input [NEV-1 : 0] credit_in_all; input [NEFw-1 : 0] flit_in_all; input [NE-1 : 0] flit_in_wr_all; output [NEV-1 : 0] credit_out_all; - - - //struct typed array ports which cannot be caled in verilog - smartflit_chanel_t chan_in_all [NE-1 : 0]; - smartflit_chanel_t chan_out_all [NE-1 : 0]; - - noc_top #( - .NOC_ID(NOC_ID) - ) the_top( - .reset(reset), - .clk(clk), - .chan_in_all(chan_in_all), - .chan_out_all(chan_out_all), - .router_event ( ) - ); - - - genvar i; - generate - for (i=0; i. +** +** +** Description: +** This module is responsible for injecting and ejecting packets +** within the NoC router. It allows the simulation of real application +** traffic by injecting pre-recorded trace data into the NoC, enabling +** performance and functionality testing of NoC components under realistic +** conditions. +** +** It can also be used to verify the NoC's ability to handle various +** traffic patterns, including stress testing with synthetic or real +** application traces. +**************************************************************/ module packet_injector #( - parameter NOC_ID=0 + parameter NOC_ID=0 ) ( - //general - current_e_addr, - reset, - clk, - //noc port - chan_in, - chan_out, - //control interafce - pck_injct_in, - pck_injct_out + //general + current_e_addr, + reset, + clk, + //noc port + chan_in, + chan_out, + //control interafce + pck_injct_in, + pck_injct_out ); - - `NOC_CONF - - //general - input reset,clk; - input [EAw-1 :0 ] current_e_addr; - - // the destination endpoint address - //NoC interface - input smartflit_chanel_t chan_in; - output smartflit_chanel_t chan_out; - //control interafce - - input pck_injct_t pck_injct_in; - output pck_injct_t pck_injct_out; - - - wire [RAw-1 :0 ] current_r_addr; - - wire [DSTPw-1 : 0 ] destport; - reg flit_wr; - - - - - - - assign current_r_addr = chan_in.ctrl_chanel.neighbors_r_addr; - - - generate if(CAST_TYPE == "UNICAST") begin : uni - - conventional_routing #( - .NOC_ID(NOC_ID), - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .T1(T1), - .T2(T2), - .T3(T3), - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw), - .LOCATED_IN_NI(1) - ) - routing_module - ( - .reset(reset), - .clk(clk), - .current_r_addr(current_r_addr), - .dest_e_addr(pck_injct_in.endp_addr), - .src_e_addr(current_e_addr), - .destport(destport) - ); - end endgenerate - - - localparam - HDR_BYTE_NUM = HDR_MAX_DATw / 8, // = HDR_MAX_DATw / (8 - HDR_MAX_DATw %8) - HDR_DATA_w_tmp = HDR_BYTE_NUM * 8, - HDR_DATA_w = - (PCK_INJ_Dw < HDR_DATA_w_tmp)? PCK_INJ_Dw : - (HDR_DATA_w_tmp==0)? 1: HDR_DATA_w_tmp; - - wire [HDR_DATA_w-1 : 0] hdr_data_in = pck_injct_in.data [HDR_DATA_w-1 : 0]; - wire [Fw-1 : 0] hdr_flit_out; - - header_flit_generator #( - .NOC_ID(NOC_ID), - .DATA_w(HDR_DATA_w) - ) the_header_flit_generator ( - .flit_out (hdr_flit_out), - .vc_num_in (pck_injct_in.vc), - .class_in (pck_injct_in.class_num), - .dest_e_addr_in (pck_injct_in.endp_addr), - .src_e_addr_in (current_e_addr), - .weight_in (pck_injct_in.init_weight), - .destport_in (destport), - .data_in (hdr_data_in), - .be_in({BEw{1'b1}} )// Be is not used in simulation as we dont sent real data - ); - - - localparam - REMAIN_DATw = PCK_INJ_Dw - HDR_DATA_w, - REMAIN_DAT_FLIT_I = (REMAIN_DATw / Fpay), - REMAIN_DAT_FLIT_F = (REMAIN_DATw % Fpay == 0)? 0 : 1, - REMAIN_DAT_FLIT = REMAIN_DAT_FLIT_I + REMAIN_DAT_FLIT_F, - CNTw = log2(REMAIN_DAT_FLIT), - MIN_PCK_SIZ = REMAIN_DAT_FLIT +1; - - - logic [PCK_SIZw-1 : 0] counter, counter_next; - logic [CNTw-1 : 0] counter2,counter2_next; - reg tail,head; - - wire [Fpay -1 : 0] remain_dat [REMAIN_DAT_FLIT -1 : 0]; - wire [Fpay-1 : 0] dataIn = remain_dat[counter2]; - enum bit [2:0] {HEADER, BODY,TAIL} flit_type,flit_type_next; - - - - wire [V-1 : 0] wr_vc_send = (flit_wr)? pck_injct_in.vc : {V{1'b0}}; - wire [V-1 : 0] vc_fifo_full; - - - wire noc_ready; - - localparam - LAST_TMP =PCK_INJ_Dw - (Fpay*REMAIN_DAT_FLIT_I)-HDR_DATA_w, - LASTw=(LAST_TMP==0)? Fpay : LAST_TMP; - genvar i; - generate - for(i=0; i {V{1'b0}} ) endp_is_active=1'b1; - // if (chan_out.smart_chanel.requests > {SMART_NUM{1'b0}} ) endp_is_active=1'b1; - // end - // `endif - - + + `NOC_CONF + + //general + input reset,clk; + input [EAw-1 :0 ] current_e_addr; + + // the destination endpoint address + //NoC interface + input smartflit_chanel_t chan_in; + output smartflit_chanel_t chan_out; + //control interafce + + input [PCK_INJ_Dw-1 : 0] pck_injct_in_data; + input [PCK_SIZw-1 : 0] pck_injct_in_size; + input [DAw-1 : 0] pck_injct_in_endp_addr; + input [Cw-1 : 0] pck_injct_in_class_num; + input [WEIGHTw-1 : 0] pck_injct_in_init_weight; + input [V-1 : 0] pck_injct_in_vc; + input pck_injct_in_pck_wr; + input [V-1 : 0] pck_injct_in_ready; + + output [PCK_INJ_Dw-1 : 0] pck_injct_out_data; + output [PCK_SIZw-1 : 0] pck_injct_out_size; + output [DAw-1 : 0] pck_injct_out_endp_addr; + output [Cw-1 : 0] pck_injct_out_class_num; + output [WEIGHTw-1 : 0] pck_injct_out_init_weight; + output [V-1 : 0] pck_injct_out_vc; + output pck_injct_out_pck_wr; + output [V-1 : 0] pck_injct_out_ready; + output [DISTw-1 : 0] pck_injct_out_distance; + output [15 : 0] pck_injct_out_h2t_delay; + output [4 : 0] min_pck_size; + + pck_injct_t pck_injct_in; + pck_injct_t pck_injct_out; + + assign pck_injct_in.data = pck_injct_in_data; + assign pck_injct_in.size = pck_injct_in_size; + assign pck_injct_in.endp_addr = pck_injct_in_endp_addr; + assign pck_injct_in.class_num = pck_injct_in_class_num; + assign pck_injct_in.init_weight = pck_injct_in_init_weight; + assign pck_injct_in.vc = pck_injct_in_vc; + assign pck_injct_in.pck_wr = pck_injct_in_pck_wr; + assign pck_injct_in.ready = pck_injct_in_ready; + + assign pck_injct_out_data = pck_injct_out.data; + assign pck_injct_out_size = pck_injct_out.size; + assign pck_injct_out_endp_addr = pck_injct_out.endp_addr; + assign pck_injct_out_class_num = pck_injct_out.class_num; + assign pck_injct_out_init_weight = pck_injct_out.init_weight; + assign pck_injct_out_vc = pck_injct_out.vc; + assign pck_injct_out_pck_wr = pck_injct_out.pck_wr; + assign pck_injct_out_ready = pck_injct_out.ready; + assign pck_injct_out_distance = pck_injct_out.distance; + assign pck_injct_out_h2t_delay = pck_injct_out.h2t_delay; + + packet_injector #( + .NOC_ID(NOC_ID) + ) injector ( + .current_e_addr (current_e_addr ), + .reset (reset ), + .clk (clk ), + .chan_in (chan_in ), + .chan_out (chan_out ), + .pck_injct_in (pck_injct_in ), + .pck_injct_out (pck_injct_out ) + ); + + localparam + HDR_BYTE_NUM = HDR_MAX_DATw / 8, // = HDR_MAX_DATw / (8 - HDR_MAX_DATw %8) + HDR_DATA_w_tmp = HDR_BYTE_NUM * 8, + HDR_DATA_w = + (PCK_INJ_Dw < HDR_DATA_w_tmp)? PCK_INJ_Dw : + (HDR_DATA_w_tmp==0)? 1: HDR_DATA_w_tmp, + REMAIN_DATw = PCK_INJ_Dw - HDR_DATA_w, + REMAIN_DAT_FLIT_I = (REMAIN_DATw / Fpay), + REMAIN_DAT_FLIT_F = (REMAIN_DATw % Fpay == 0)? 0 : 1, + REMAIN_DAT_FLIT = REMAIN_DAT_FLIT_I + REMAIN_DAT_FLIT_F, + CNTw = log2(REMAIN_DAT_FLIT), + MIN_PCK_SIZ = REMAIN_DAT_FLIT +1; + + assign min_pck_size = MIN_PCK_SIZ[4:0]; + + // `ifdef VERILATOR + // logic endp_is_active /*verilator public_flat_rd*/ ; + // + // always @ (*) begin + // endp_is_active = 1'b0; + // if (chan_out.flit_chanel.flit_wr) endp_is_active=1'b1; + // if (chan_out.flit_chanel.credit > {V{1'b0}} ) endp_is_active=1'b1; + // if (chan_out.smart_chanel.requests > {SMART_NUM{1'b0}} ) endp_is_active=1'b1; + // end + // `endif endmodule diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index f56df3e..db9e9cc 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -263,11 +263,10 @@ module router_top #( end //:no_smart endgenerate -/********************************************* -* -* Validating Parameters/Simulation -* -*********************************************/ +/************************************** +* Validating Parameters +* /Simulation +***************************************/ `ifdef SIMULATION /* verilator lint_off WIDTH */ initial begin diff --git a/mpsoc/rtl/src_noc/star_noc.sv b/mpsoc/rtl/src_noc/star_noc.sv index 4ac061a..c1c4c96 100644 --- a/mpsoc/rtl/src_noc/star_noc.sv +++ b/mpsoc/rtl/src_noc/star_noc.sv @@ -1,79 +1,98 @@ `include "pronoc_def.v" +/********************************************************************** +** File: star_noc_top.v +** +** Copyright (C) 2014-2017 Alireza Monemi +** +** This file is part of ProNoC +** +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. +** +** ProNoC 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 Lesser General +** Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . +** +** +** Description: +** +** Star Topology NoC +** +** This module implements a Star Network-on-Chip (NoC) topology. +** In this design, a single central router connects directly to +** multiple endpoints through its ports. All communication between +** endpoints is routed through this central hub, enabling simple +** and efficient data transfer in small-scale networks. +** +** Key Features: +** - Single central router with multiple ports. +** - All ports are directly connected to endpoints. +** - Simplified routing with minimal latency for star configurations. +** +**********************************************************************/ -/************************************** - * Module: tree - * Date:2019-01-01 - * Author: alireza - * - * -Description: - - Star - - ***************************************/ - - module star_noc_top #( - parameter NOC_ID=0 + parameter NOC_ID=0 ) ( - reset, - clk, - chan_in_all, - chan_out_all, - router_event - ); - - `NOC_CONF - - input clk,reset; - //Endpoints ports - input smartflit_chanel_t chan_in_all [NE-1 : 0]; - output smartflit_chanel_t chan_out_all [NE-1 : 0]; - - //Events - output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - - - router_top # ( - .NOC_ID(NOC_ID), - .P(NE) - ) - the_router - ( - .current_r_id (0), - .current_r_addr (1'b0), - .chan_in (chan_in_all), - .chan_out (chan_out_all), - .router_event (router_event[0]), - .clk (clk ), - .reset (reset ) - ); - - + reset, + clk, + chan_in_all, + chan_out_all, + router_event + ); + + `NOC_CONF + + input clk,reset; + //Endpoints ports + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; + + //Events + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; + + router_top # ( + .NOC_ID(NOC_ID), + .ROUTER_ID(0), + .P(NE) + ) the_router ( + .current_r_id (0), + .current_r_addr (1'b0), + .chan_in (chan_in_all), + .chan_out (chan_out_all), + .router_event (router_event[0]), + .clk (clk ), + .reset (reset ) + ); + endmodule - module star_conventional_routing #( - parameter NE = 8 - ) - ( - dest_e_addr, - destport -); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21 || flit_out_hdr!=2'b11) begin - ns = SENT; - end else begin - pck_rd=1'b1; - flit_cnt_rst = 1'b1; - sent_done =1'b1; - cand_wr_vc_en =1'b1; - if(cand_vc>0) begin - wr_vc_next = cand_vc; - end else ns = WAIT; - end //else - end//wr_vc - end + reg not_yet_sent_aflit_next,not_yet_sent_aflit; + + always @(*)begin + wr_vc_next = wr_vc; + cand_wr_vc_en = 1'b0; + flit_out_wr = 1'b0; + flit_cnt_inc = 1'b0; + flit_cnt_rst = 1'b0; + credit_out_next = {V{1'd0}}; + sent_done = 1'b0; + pck_rd = 1'b0; + hdr_flit_sent =1'b0; + ns = ps; + pck_rd =1'b0; + not_yet_sent_aflit_next =not_yet_sent_aflit; + case (ps) + IDEAL: begin + if(pck_ready ) begin + if(wr_vc_avb && valid_dst)begin + + hdr_flit_sent=1'b1; + flit_out_wr = 1'b1;//sending header flit + not_yet_sent_aflit_next = 1'b0; + flit_cnt_inc = 1'b1; + if (MIN_PCK_SIZE>1 || flit_out_hdr!=2'b11) begin + ns = SENT; + end else begin + pck_rd=1'b1; + flit_cnt_rst = 1'b1; + sent_done =1'b1; + cand_wr_vc_en =1'b1; + if(cand_vc>0) begin + wr_vc_next = cand_vc; + end else ns = WAIT; + end //else + end//wr_vc + end - end //IDEAL - SENT: begin - - if(!wr_vc_is_full )begin + end //IDEAL + SENT: begin + if(!wr_vc_is_full )begin - flit_out_wr = 1'b1; - if(flit_counter < pck_size-1) begin - flit_cnt_inc = 1'b1; - end else begin - flit_cnt_rst = 1'b1; - sent_done =1'b1; - pck_rd=1'b1; - cand_wr_vc_en =1'b1; - if(cand_vc>0) begin - wr_vc_next = cand_vc; - ns =IDEAL; - end else ns = WAIT; - end//else - end // if wr_vc_is_full - end//SENT - WAIT:begin - - cand_wr_vc_en =1'b1; - if(cand_vc>0) begin - wr_vc_next = cand_vc; - ns =IDEAL; - end - end - default: begin - ns =IDEAL; - end - endcase - - - // packet sink - if(flit_in_wr) begin - credit_out_next = rd_vc; - end else credit_out_next = {V{1'd0}}; - end - - - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin - inject_en <= 1'b0; - ps <= IDEAL; - wr_vc <=1; - flit_counter <= {PCK_SIZw{1'b0}}; - credit_out <= {V{1'd0}}; - rsv_counter <= 0; - clk_counter <= 0; - not_yet_sent_aflit<=1'b1; + flit_out_wr = 1'b1; + if(flit_counter < pck_size-1) begin + flit_cnt_inc = 1'b1; + end else begin + flit_cnt_rst = 1'b1; + sent_done =1'b1; + pck_rd=1'b1; + cand_wr_vc_en =1'b1; + if(cand_vc>0) begin + wr_vc_next = cand_vc; + ns =IDEAL; + end else ns = WAIT; + end//else + end // if wr_vc_is_full + end//SENT + WAIT:begin + cand_wr_vc_en =1'b1; + if(cand_vc>0) begin + wr_vc_next = cand_vc; + ns =IDEAL; + end + end + default: begin + ns =IDEAL; + end + endcase + // packet sink + if(flit_in_wr) begin + credit_out_next = rd_vc; + end else credit_out_next = {V{1'd0}}; + end //always + + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + inject_en <= 1'b0; + ps <= IDEAL; + wr_vc <= 1; + flit_counter <= {PCK_SIZw{1'b0}}; + credit_out <= {V{1'd0}}; + rsv_counter <= 0; + clk_counter <= 0; + not_yet_sent_aflit<=1'b1; + end else begin + //injection + not_yet_sent_aflit<=not_yet_sent_aflit_next; + inject_en <= (start_injection |inject_en) & ~stop; + ps <= ns; + clk_counter <= clk_counter+1'b1; + wr_vc <= wr_vc_next; + if (flit_cnt_rst) flit_counter <= {PCK_SIZw{1'b0}}; + else if(flit_cnt_inc) flit_counter <= flit_counter + 1'b1; + credit_out <= credit_out_next; + //sink + if(flit_in_wr) begin + if (flit_in[Fw-1])begin //header flit + rsv_pck_src_e_addr[rd_vc_bin] <= rd_src_e_addr; + rsv_pck_class_in[rd_vc_bin] <= rd_class_hdr; + rsv_time_stamp[rd_vc_bin] <= clk_counter; + rsv_counter <= rsv_counter+1'b1; + rsv_pck_size[rd_vc_bin] <=2; + // distance <= {{(32-8){1'b0}},flit_in[7:0]}; + `ifdef SIMULATION + `ifdef RSV_NOTIFICATION + // last_pck_time<=$time; + $display ("total of %d pcks have been recived in core (%d)", rsv_counter,current_e_addr); + `endif + `endif + end else begin + rsv_pck_size[rd_vc_bin] <=rsv_pck_size[rd_vc_bin]+1; + end + end + `ifdef SIMULATION + if(report) begin + $display ("%t,\t total of %d pcks have been recived in core (%d)",$time ,rsv_counter,current_e_addr); + end + `endif + end //else reset + end//always + + wire [NE-1 :0] dest_mcast_all_endp1; + + generate + /* verilator lint_off WIDTH */ + if(CAST_TYPE != "UNICAST") begin :mb_cast + /* verilator lint_on WIDTH */ - end else begin - //injection - not_yet_sent_aflit<=not_yet_sent_aflit_next; - inject_en <= (start_injection |inject_en) & ~stop; - ps <= ns; - clk_counter <= clk_counter+1'b1; - wr_vc <=wr_vc_next; - if (flit_cnt_rst) flit_counter <= {PCK_SIZw{1'b0}}; - else if(flit_cnt_inc) flit_counter <= flit_counter + 1'b1; - credit_out <= credit_out_next; - - - //sink - if(flit_in_wr) begin - if (flit_in[Fw-1])begin //header flit - rsv_pck_src_e_addr[rd_vc_bin] <= rd_src_e_addr; - rsv_pck_class_in[rd_vc_bin] <= rd_class_hdr; - rsv_time_stamp[rd_vc_bin] <= clk_counter; - rsv_counter <= rsv_counter+1'b1; - rsv_pck_size[rd_vc_bin] <=2; - // distance <= {{(32-8){1'b0}},flit_in[7:0]}; - `ifdef RSV_NOTIFICATION - // synopsys translate_off - // synthesis translate_off - // last_pck_time<=$time; - $display ("total of %d pcks have been recived in core (%d)", rsv_counter,current_e_addr); - // synthesis translate_on - // synopsys translate_on - `endif - end else begin - rsv_pck_size[rd_vc_bin] <=rsv_pck_size[rd_vc_bin]+1; - end - end - // synopsys translate_off - // synthesis translate_off - if(report) begin - $display ("%t,\t total of %d pcks have been recived in core (%d)",$time ,rsv_counter,current_e_addr); - end - // synthesis translate_on - // synopsys translate_on + wire [NEw-1 : 0] sum_temp; + wire is_unicast; - + mcast_dest_list_decode #( + .NOC_ID(NOC_ID) + ) decode1 ( + .dest_e_addr(dest_e_addr_o), + .dest_o(dest_mcast_all_endp1), + .row_has_any_dest(), + .is_unicast(is_unicast) + ); - + /* verilator lint_off WIDTH */ + if (CAST_TYPE == "BROADCAST_FULL") begin :bcastf + assign mcast_dst_num_o = (is_unicast) ? 1 : (SELF_LOOP_EN == "NO")? NE-1 : NE; + end else if ( CAST_TYPE == "BROADCAST_PARTIAL" ) begin :bcastp + if (SELF_LOOP_EN == "NO") begin + //check if injector node is included in partial list + wire [NEw-1: 0] current_enp_id; + endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod1 ( .id(current_enp_id), .code(current_e_addr)); + assign mcast_dst_num_o = (is_unicast) ? 1 : (MCAST_ENDP_LIST[current_enp_id]== 1'b1)? MCAST_PRTLw-1 : MCAST_PRTLw; + end else begin + assign mcast_dst_num_o = (is_unicast)? 1 : MCAST_PRTLw; + end + /* verilator lint_on WIDTH */ - end - end//always - - - - - - - wire [NE-1 :0] dest_mcast_all_endp1; - - - generate - /* verilator lint_off WIDTH */ - if(CAST_TYPE != "UNICAST") begin :mb_cast - /* verilator lint_on WIDTH */ - - wire [NEw-1 : 0] sum_temp; - wire is_unicast; - - mcast_dest_list_decode #( - .NOC_ID(NOC_ID) - ) decode1 ( - .dest_e_addr(dest_e_addr_o), - .dest_o(dest_mcast_all_endp1), - .row_has_any_dest(), - .is_unicast(is_unicast) - ); - - /* verilator lint_off WIDTH */ - if (CAST_TYPE == "BROADCAST_FULL") begin :bcastf - assign mcast_dst_num_o = (is_unicast) ? 1 : (SELF_LOOP_EN == "NO")? NE-1 : NE; - end else if ( CAST_TYPE == "BROADCAST_PARTIAL" ) begin :bcastp - - if (SELF_LOOP_EN == "NO") begin - //check if injector node is included in partial list - wire [NEw-1: 0] current_enp_id; - endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod1 ( .id(current_enp_id), .code(current_e_addr)); - assign mcast_dst_num_o = (is_unicast) ? 1 : (MCAST_ENDP_LIST[current_enp_id]== 1'b1)? MCAST_PRTLw-1 : MCAST_PRTLw; - - end else begin - assign mcast_dst_num_o = (is_unicast)? 1 : MCAST_PRTLw; - end - /* verilator lint_on WIDTH */ - end else begin : mcast - accumulator #( - .INw(NE), - .OUTw(NEw), - .NUM(NE) - )accum - ( - .in_all(dest_mcast_all_endp1), - .out(sum_temp) - ); - assign mcast_dst_num_o = sum_temp; - end - end - endgenerate - - - - - -/*************************************************************** - * simulation code - * ************************************************************/ - - - - - -// synthesis translate_off - - wire [NEw-1: 0] src_id,dst_id,current_id; - - endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod1 ( .id(current_id), .code(current_e_addr)); - endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod2 ( .id(dst_id), .code(rd_des_e_addr[EAw-1 : 0]));// only for unicast - endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod3 ( .id(src_id), .code(rd_src_e_addr)); - - - - - - wire [NE-1 :0] dest_mcast_all_endp2; - generate - if(CAST_TYPE != "UNICAST") begin :no_unicast - mcast_dest_list_decode #( - .NOC_ID(NOC_ID) - ) decode2 ( - .dest_e_addr(rd_des_e_addr), - .dest_o(dest_mcast_all_endp2), - .row_has_any_dest(), - .is_unicast() - ); - end - endgenerate - - - - always @(posedge clk) begin - /* verilator lint_off WIDTH */ - if(CAST_TYPE == "UNICAST") begin - /* verilator lint_on WIDTH */ - if(flit_out_wr && hdr_flit && dest_e_addr_o [EAw-1 : 0] == current_e_addr && SELF_LOOP_EN == "NO") begin - $display("%t: ERROR: The self-loop is not enabled in the router while a packet is injected to the NoC with identical source and destination address in endpoint (%h).: %m",$time, dest_e_addr_o ); - $finish; - end - if(flit_in_wr && rd_hdr_flg && (rd_des_e_addr[EAw-1 : 0] != current_e_addr )) begin - $display("%t: ERROR: packet with destination %d (code %h) which is sent by source %d (code %h) has been recieved in wrong destination %d (code %h). %m",$time,dst_id,rd_des_e_addr, src_id,rd_src_e_addr, current_id,current_e_addr); - $finish; - end - - end else begin - /* verilator lint_off WIDTH */ - if((CAST_TYPE == "MULTICAST_FULL") || (CAST_TYPE == "MULTICAST_PARTIAL")) begin - /* verilator lint_on WIDTH */ - - if(flit_out_wr && hdr_flit && dest_mcast_all_endp1[current_id] == 1'b1 && SELF_LOOP_EN == "NO") begin - $display("%t: ERROR: The self-loop is not enabled in the router while a packet is injected to the NoC with identical source and destination address in endpoint %d. destination nodes:0X%h. : %m",$time, current_id,dest_mcast_all_endp1 ); - $finish; - end - end - if(flit_in_wr && rd_hdr_flg && (dest_mcast_all_endp2[current_id] !=1'b1 )) begin - $display("%t: ERROR: packet with destination %b which is sent by source %d (code %h) has been recieved in wrong destination %d (code %h). %m",$time, dest_mcast_all_endp2, src_id,rd_src_e_addr, current_id,current_e_addr); - $finish; - end - - //check multicast packet size to be smaller than B & LB - if(flit_out_wr & hdr_flit & (mcast_dst_num_o>1) & (pck_size >B || pck_size> LB))begin - $display("%t: ERROR: A multicast packat is injected to the NoC which has larger size (%d) than router buffer width. %m",$time, pck_size); - $finish; - end - - end - if(update) begin - if (hdr_flit_timestamp<= rd_timestamp) begin - $display("%t: ERROR: In destination %d packt which is sent by source %d, the time when header flit is recived (%d) should be larger than the packet timestamp %d. %m",$time, current_id ,src_e_addr, hdr_flit_timestamp, rd_timestamp); - $finish; - end - if( clk_counter <= rd_timestamp) begin - $display("%t: ERROR: ERROR: In destination %d packt which is sent by source %d,, the current time (%d) should be larger than the packet timestamp %d. %m",$time, current_id ,src_e_addr, clk_counter, rd_timestamp); - $finish; - end - end//update - if(tail_flit & flit_out_wr) begin - if(wr_timestamp > clk_counter) begin - $display("%t: ERROR: In src %d, the current time (%d) should be larger than or equal to the packet timestamp %d. %m",$time, current_id, clk_counter, wr_timestamp); - $finish; - end - end - - end - - - `ifdef CHECK_PCKS_CONTENT - - - wire [PCK_SIZw-1 : 0] rsv_flit_counter; - reg [PCK_SIZw-1 : 0] old_flit_counter [V-1 : 0]; - wire [PCK_CNTw-1 : 0] rsv_pck_number; - reg [PCK_CNTw-1 : 0] old_pck_number [V-1 : 0]; - - wire [PCK_CNTw+PCK_SIZw-1 : 0] statistics; - generate - if(PCK_CNTw+PCK_SIZw > Fw) assign statistics = {{(PCK_CNTw+PCK_SIZw-Fw){1'b0}},flit_in}; - else assign statistics = flit_in[PCK_CNTw+PCK_SIZw-1 : 0]; - assign {rsv_pck_number,rsv_flit_counter}=statistics; - - endgenerate - - - - integer ii; - - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin - for(ii=0;ii1) & (pck_size >B || pck_size> LB))begin + $display("%t: ERROR: A multicast packat is injected to the NoC which has larger size (%d) than router buffer width. %m",$time, pck_size); + $finish; + end + end + if(update) begin + if (hdr_flit_timestamp<= rd_timestamp) begin + $display("%t: ERROR: In destination %d packt which is sent by source %d, the time when header flit is recived (%d) should be larger than the packet timestamp %d. %m",$time, current_id ,src_e_addr, hdr_flit_timestamp, rd_timestamp); + $finish; + end + if( clk_counter <= rd_timestamp) begin + $display("%t: ERROR: ERROR: In destination %d packt which is sent by source %d,, the current time (%d) should be larger than the packet timestamp %d. %m",$time, current_id ,src_e_addr, clk_counter, rd_timestamp); + $finish; + end + end//update + if(tail_flit & flit_out_wr) begin + if(wr_timestamp > clk_counter) begin + $display("%t: ERROR: In src %d, the current time (%d) should be larger than or equal to the packet timestamp %d. %m",$time, current_id, clk_counter, wr_timestamp); + $finish; + end + end + end //always + `ifdef CHECK_PCKS_CONTENT + wire [PCK_SIZw-1 : 0] rsv_flit_counter; + reg [PCK_SIZw-1 : 0] old_flit_counter [V-1 : 0]; + wire [PCK_CNTw-1 : 0] rsv_pck_number; + reg [PCK_CNTw-1 : 0] old_pck_number [V-1 : 0]; + wire [PCK_CNTw+PCK_SIZw-1 : 0] statistics; - always @(posedge clk) begin - if(flit_in_wr && (flit_in[Fw-1:Fw-2]==2'b00) && (~reset))begin - if( old_flit_counter[rd_vc_bin]!=rsv_flit_counter-1) $display("%t: Error: missmatch flit counter in %m. Expected %d but recieved %d",$time,old_flit_counter[rd_vc_bin]+1,rsv_flit_counter); - if( old_pck_number[rd_vc_bin]!=rsv_pck_number && old_pck_number[rd_vc_bin]!=0) $display("%t: Error: missmatch pck number in %m. expected %d but recieved %d",$time,old_pck_number[rd_vc_bin],rsv_pck_number); - - end - - end - + assign statistics = (PCK_CNTw+PCK_SIZw > Fw)? + {{(PCK_CNTw+PCK_SIZw-Fw){1'b0}},flit_in} : + flit_in[PCK_CNTw+PCK_SIZw-1 : 0]; - `endif + assign {rsv_pck_number,rsv_flit_counter}=statistics; + + integer ii; + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + for(ii=0;ii {V{1'b0}} ) endp_is_active=1'b1; +// if (chan_out.smart_chanel.requests > {SMART_NUM{1'b0}} ) endp_is_active=1'b1; +// end +//`endif -// synthesis translate_on - - - - - -// `ifdef VERILATOR -// logic endp_is_active /*verilator public_flat_rd*/ ; -// -// always @ (*) begin -// endp_is_active = 1'b0; -// if (chan_out.flit_chanel.flit_wr) endp_is_active=1'b1; -// if (chan_out.flit_chanel.credit > {V{1'b0}} ) endp_is_active=1'b1; -// if (chan_out.smart_chanel.requests > {SMART_NUM{1'b0}} ) endp_is_active=1'b1; -// end -// `endif - endmodule - /***************************** - injection_ratio_ctrl - +* injection_ratio_ctrl *****************************/ module injection_ratio_ctrl # - ( - parameter MAX_PCK_SIZ=10, - parameter MAX_RATIO=100 + ( + parameter MAX_PCK_SIZ=10, + parameter MAX_RATIO=100 )( - en, - pck_size_in, // average packet size in flit x10 - clk, - reset, - inject,// inject one packet - freez, - ratio // 0~100 flit injection ratio + en, + pck_size_in, // average packet size in flit x10 + clk, + reset, + inject,// inject one packet + freez, + ratio // 0~100 flit injection ratio ); - - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2= pck_size-1'b1) ? {PCK_SIZw{1'b0}} : flit_counter +1'b1; - next_inject = (flit_counter=={PCK_SIZw{1'b0}}); - if (next_flit_counter >= pck_size-1'b1) begin - if( next_state >= STATE_INIT ) next_sent =1'b0; - end - end - 1'b0:begin - if( next_state < STATE_INIT ) next_sent = 1'b1; - next_inject= 1'b0; - /* verilator lint_off WIDTH */ - next_state = state - on_clks; - /* verilator lint_on WIDTH */ - end - endcase - end else begin - next_inject= 1'b0; - end - end - - - - - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin - state <= STATE_INIT; - inject <= 1'b0; - sent <= 1'b1; - flit_counter<= 0; - pck_size<=2; - end else begin - if(input_changed)begin - state <= STATE_INIT; - inject <= 1'b0; - sent <= 1'b1; - flit_counter<= 0; - end - - if(flit_counter=={PCK_SIZw{1'b0}}) pck_size<=pck_size_in; - state <= next_state; - if(ratio!={CNTw{1'b0}}) inject <= next_inject; - sent <= next_sent; - flit_counter<= next_flit_counter; - - end - end - - + + function integer log2; + input integer number; begin + log2=(number <=1) ? 1: 0; + while(2**log2= pck_size-1'b1) ? {PCK_SIZw{1'b0}} : flit_counter +1'b1; + next_inject = (flit_counter=={PCK_SIZw{1'b0}}); + if (next_flit_counter >= pck_size-1'b1) begin + if( next_state >= STATE_INIT ) next_sent =1'b0; + end + end + 1'b0:begin + if( next_state < STATE_INIT ) next_sent = 1'b1; + next_inject= 1'b0; + /* verilator lint_off WIDTH */ + next_state = state - on_clks; + /* verilator lint_on WIDTH */ + end + endcase + end else begin + next_inject= 1'b0; + end + end + + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + state <= STATE_INIT; + inject <= 1'b0; + sent <= 1'b1; + flit_counter<= 0; + pck_size<=2; + end else begin + if(input_changed)begin + state <= STATE_INIT; + inject <= 1'b0; + sent <= 1'b1; + flit_counter <= 0; + end + if(flit_counter=={PCK_SIZw{1'b0}}) pck_size<=pck_size_in; + state <= next_state; + if(ratio!={CNTw{1'b0}}) inject <= next_inject; + sent <= next_sent; + flit_counter <= next_flit_counter; + end + end + endmodule - - /************************************* - packet_buffer + packet_buffer **************************************/ - module packet_gen #( - parameter NOC_ID=0, - parameter P = 5 + parameter NOC_ID=0, + parameter P = 5 )( - clk_counter, - pck_wr, - pck_rd, - current_r_addr, - current_e_addr, - pck_number, - dest_e_addr_in, - dest_e_addr_o, - pck_timestamp, - destport, - buffer_full, - pck_ready, - valid_dst, - pck_size_in, - pck_size_o, - clk, - reset + clk_counter, + pck_wr, + pck_rd, + current_r_addr, + current_e_addr, + pck_number, + dest_e_addr_in, + dest_e_addr_o, + pck_timestamp, + destport, + buffer_full, + pck_ready, + valid_dst, + pck_size_in, + pck_size_o, + clk, + reset ); - - - `NOC_CONF - - localparam - PCK_CNTw = log2(MAX_PCK_NUM+1), - CLK_CNTw = log2(MAX_SIM_CLKs+1); - - - input reset,clk, pck_wr, pck_rd; - input [RAw-1 :0] current_r_addr; - input [EAw-1 : 0] current_e_addr; - input [CLK_CNTw-1 :0] clk_counter; - input [PCK_SIZw-1 :0] pck_size_in; - input [DAw-1 :0] dest_e_addr_in; - output [DAw-1 :0] dest_e_addr_o; - input valid_dst; - - output [PCK_CNTw-1 :0] pck_number; - output [CLK_CNTw-1 :0] pck_timestamp; - output [PCK_SIZw-1 :0] pck_size_o; - output buffer_full,pck_ready; - - output [DSTPw-1 :0] destport; - reg [PCK_CNTw-1 :0] packet_counter; - wire buffer_empty; - - assign pck_ready = ~buffer_empty & valid_dst; - - generate if(CAST_TYPE == "UNICAST") begin : uni - conventional_routing #( - .NOC_ID(NOC_ID), - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .T1(T1), - .T2(T2), - .T3(T3), - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw), - .LOCATED_IN_NI(1) - ) - routing_module - ( - .reset(reset), - .clk(clk), - .current_r_addr(current_r_addr), - .dest_e_addr(dest_e_addr_o), - .src_e_addr(current_e_addr), - .destport(destport) - ); - end endgenerate - - wire timestamp_fifo_nearly_full , timestamp_fifo_full; - assign buffer_full = (MIN_PCK_SIZE==1) ? timestamp_fifo_nearly_full : timestamp_fifo_full; - - wire [DAw-1 :0] tmp1; - wire [PCK_SIZw-1 : 0] tmp2; - - wire recieve_more_than_0; - fwft_fifo_bram #( - .DATA_WIDTH(CLK_CNTw+PCK_SIZw+DAw), - .MAX_DEPTH(TIMSTMP_FIFO_NUM) - ) - timestamp_fifo - ( - .din({dest_e_addr_in,pck_size_in,clk_counter}), - .wr_en(pck_wr), - .rd_en(pck_rd), - .dout({tmp1,tmp2,pck_timestamp}), - .full(timestamp_fifo_full), - .nearly_full(timestamp_fifo_nearly_full), - .recieve_more_than_0(recieve_more_than_0), - .recieve_more_than_1(), - .reset(reset), - .clk(clk) - ); - - //assign dest_e_addr_o = dest_e_addr_in; - - assign dest_e_addr_o =tmp1; - /* verilator lint_off WIDTH */ - assign pck_size_o = (PCK_TYPE == "SINGLE_FLIT" )? 1 : tmp2; - /* verilator lint_on WIDTH */ - assign buffer_empty = ~recieve_more_than_0; - - /* - + + `NOC_CONF + + localparam + PCK_CNTw = log2(MAX_PCK_NUM+1), + CLK_CNTw = log2(MAX_SIM_CLKs+1); + + input reset,clk, pck_wr, pck_rd; + input [RAw-1 :0] current_r_addr; + input [EAw-1 : 0] current_e_addr; + input [CLK_CNTw-1 :0] clk_counter; + input [PCK_SIZw-1 :0] pck_size_in; + input [DAw-1 :0] dest_e_addr_in; + output [DAw-1 :0] dest_e_addr_o; + input valid_dst; + + output [PCK_CNTw-1 :0] pck_number; + output [CLK_CNTw-1 :0] pck_timestamp; + output [PCK_SIZw-1 :0] pck_size_o; + output buffer_full,pck_ready; + + output [DSTPw-1 :0] destport; + reg [PCK_CNTw-1 :0] packet_counter; + wire buffer_empty; + + assign pck_ready = ~buffer_empty & valid_dst; + + generate + if(CAST_TYPE == "UNICAST") begin : uni + conventional_routing #( + .NOC_ID(NOC_ID), + .TOPOLOGY(TOPOLOGY), + .ROUTE_NAME(ROUTE_NAME), + .ROUTE_TYPE(ROUTE_TYPE), + .T1(T1), + .T2(T2), + .T3(T3), + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw), + .LOCATED_IN_NI(1) + ) routing_module ( + .reset(reset), + .clk(clk), + .current_r_addr(current_r_addr), + .dest_e_addr(dest_e_addr_o), + .src_e_addr(current_e_addr), + .destport(destport) + ); + end + endgenerate + + wire timestamp_fifo_nearly_full , timestamp_fifo_full; + assign buffer_full = (MIN_PCK_SIZE==1) ? timestamp_fifo_nearly_full : timestamp_fifo_full; + + wire [DAw-1 :0] tmp1; + wire [PCK_SIZw-1 : 0] tmp2; + + wire recieve_more_than_0; + fwft_fifo_bram #( + .DATA_WIDTH(CLK_CNTw+PCK_SIZw+DAw), + .MAX_DEPTH(TIMSTMP_FIFO_NUM) + ) timestamp_fifo ( + .din({dest_e_addr_in,pck_size_in,clk_counter}), + .wr_en(pck_wr), + .rd_en(pck_rd), + .dout({tmp1,tmp2,pck_timestamp}), + .full(timestamp_fifo_full), + .nearly_full(timestamp_fifo_nearly_full), + .recieve_more_than_0(recieve_more_than_0), + .recieve_more_than_1(), + .reset(reset), + .clk(clk) + ); + + //assign dest_e_addr_o = dest_e_addr_in; + + assign dest_e_addr_o =tmp1; + /* verilator lint_off WIDTH */ + assign pck_size_o = (PCK_TYPE == "SINGLE_FLIT" )? 1 : tmp2; + /* verilator lint_on WIDTH */ + assign buffer_empty = ~recieve_more_than_0; + + /* bram_based_fifo #( .Dw(CLK_CNTw), .B(TIMSTMP_FIFO_NUM) @@ -1066,108 +940,89 @@ module packet_gen .reset(reset), .clk(clk) ); - */ - - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin - packet_counter <= {PCK_CNTw{1'b0}}; - end else begin - if(pck_rd) begin - packet_counter <= packet_counter+1'b1; - - end - end - end - - assign pck_number = packet_counter; - + */ + + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + packet_counter <= {PCK_CNTw{1'b0}}; + end else begin + if(pck_rd) begin + packet_counter <= packet_counter+1'b1; + end + end + end + + assign pck_number = packet_counter; + +endmodule -endmodule - - - -/******************** +/******************** distance_gen - ********************/ - module distance_gen #( - parameter TOPOLOGY = "MESH", - parameter T1=4, - parameter T2=4, - parameter T3=4, - parameter EAw=2, - parameter DISTw=4 - + parameter TOPOLOGY = "MESH", + parameter T1=4, + parameter T2=4, + parameter T3=4, + parameter EAw=2, + parameter DISTw=4 )( - src_e_addr, - dest_e_addr, - distance + src_e_addr, + dest_e_addr, + distance ); - - input [EAw-1 : 0] src_e_addr; - input [EAw-1 : 0] dest_e_addr; - output [DISTw-1 : 0] distance; - - generate - /* verilator lint_off WIDTH */ - if (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE")begin : tori_noc - /* verilator lint_on WIDTH */ - - mesh_torus_distance_gen #( - .T1(T1), - .T2(T2), - .T3(T3), - .TOPOLOGY(TOPOLOGY), - .DISTw(DISTw), - .EAw(EAw) - ) - distance_gen - ( - .src_e_addr(src_e_addr), - .dest_e_addr(dest_e_addr), - .distance(distance) - ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "FMESH") begin :fmesh - /* verilator lint_on WIDTH */ - fmesh_distance_gen #( - .T1(T1), - .T2(T2), - .T3(T3), - .DISTw(DISTw), - .EAw(EAw) - ) - distance_gen - ( - .src_e_addr(src_e_addr), - .dest_e_addr(dest_e_addr), - .distance(distance) - ); - - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "FATTREE" || TOPOLOGY == "TREE") begin : fat - /* verilator lint_on WIDTH */ - fattree_distance_gen #( - .K(T1), - .L(T2) - ) - distance_gen - ( - .src_addr_encoded(src_e_addr), - .dest_addr_encoded(dest_e_addr), - .distance(distance) - ); - end else if (TOPOLOGY == "STAR") begin - - assign distance =1 ; - end - endgenerate - -endmodule - - - - - + + input [EAw-1 : 0] src_e_addr; + input [EAw-1 : 0] dest_e_addr; + output [DISTw-1 : 0] distance; + + generate + /* verilator lint_off WIDTH */ + if (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE")begin : tori_noc + /* verilator lint_on WIDTH */ + + mesh_torus_distance_gen #( + .T1(T1), + .T2(T2), + .T3(T3), + .TOPOLOGY(TOPOLOGY), + .DISTw(DISTw), + .EAw(EAw) + ) distance_gen ( + .src_e_addr(src_e_addr), + .dest_e_addr(dest_e_addr), + .distance(distance) + ); + /* verilator lint_off WIDTH */ + end else if (TOPOLOGY == "FMESH") begin :fmesh + /* verilator lint_on WIDTH */ + fmesh_distance_gen #( + .T1(T1), + .T2(T2), + .T3(T3), + .DISTw(DISTw), + .EAw(EAw) + ) distance_gen ( + .src_e_addr(src_e_addr), + .dest_e_addr(dest_e_addr), + .distance(distance) + ); + + /* verilator lint_off WIDTH */ + end else if (TOPOLOGY == "FATTREE" || TOPOLOGY == "TREE") begin : fat + /* verilator lint_on WIDTH */ + fattree_distance_gen #( + .K(T1), + .L(T2) + ) distance_gen ( + .src_addr_encoded(src_e_addr), + .dest_addr_encoded(dest_e_addr), + .distance(distance) + ); + end else if (TOPOLOGY == "STAR") begin + assign distance =1; + end + endgenerate + +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/tree_noc_top.sv b/mpsoc/rtl/src_noc/tree_noc_top.sv index 5944d04..8612baa 100644 --- a/mpsoc/rtl/src_noc/tree_noc_top.sv +++ b/mpsoc/rtl/src_noc/tree_noc_top.sv @@ -1,178 +1,184 @@ `include "pronoc_def.v" -/************************************** - * Module: tree - * Date:2019-01-01 - * Author: alireza - * - * -Description: +/********************************************************************** +** File: tree_noc_top.v +** +** Copyright (C) 2014-2017 Alireza Monemi +** +** This file is part of ProNoC +** +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. +** +** ProNoC 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 Lesser General +** Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . +** +** Description: +** +** Tree Topology NoC with Multiple Layers +** +** This module implements a Tree Network-on-Chip (NoC) topology with +** a hierarchical structure consisting of multiple layers. The network +** has a single root router with *k* ports, each of which connects to +** a child router. These child routers (leaves) have *k+1* ports, +** enabling them to connect to their child routers or endpoints. +** The tree structure can have *l* layers, where each layer contains +** routers that further branch out to create a scalable and efficient network. +** +** Key Features: +** - A single root router with *k* ports. +** - Child routers (leaves) each have *k+1* ports. +** - The network can have *l* layers, with each layer connected to the +** previous layer in a hierarchical manner. +** - Scalability through hierarchical routing, allowing for efficient +** communication in large systems. +** - Suitable for systems where hierarchical control and scalability are essential. +** +**********************************************************************/ - Tree - - ***************************************/ - - module tree_noc_top #( - parameter NOC_ID=0 -) ( - reset, - clk, - chan_in_all, - chan_out_all, - router_event + parameter NOC_ID=0 +)( + reset, + clk, + chan_in_all, + chan_out_all, + router_event ); - - `NOC_CONF - - input clk,reset; - //Endpoints ports - input smartflit_chanel_t chan_in_all [NE-1 : 0]; - output smartflit_chanel_t chan_out_all [NE-1 : 0]; - - //Events - output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - - //all routers port - smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; - smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; - - - - function integer addrencode; - input integer pos,k,n,kw; - integer pow,i,tmp;begin - addrencode=0; - pow=1; - for (i = 0; i 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 DP0>y;pWBsQn(jsBZ~j&m*o-z415l-5G7wuOEp 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 diff --git a/mpsoc/rtl/src_topology/custom1/custom1_noc.sv b/mpsoc/rtl/src_topology/custom1/custom1_noc.sv index 2e29eba..f09fec8 100644 --- a/mpsoc/rtl/src_topology/custom1/custom1_noc.sv +++ b/mpsoc/rtl/src_topology/custom1/custom1_noc.sv @@ -6,11 +6,11 @@ /********************************************************************** -** File: /home/alireza/work/git/pronoc/mpsoc/rtl/src_topology/custom1/custom1_noc.sv +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/custom1_noc.sv ** -** Copyright (C) 2014-2021 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.1.0 +** This file is part of ProNoC 2.2.0 ** ** ProNoC ( stands for Prototype Network-on-chip) is free software: ** you can redistribute it and/or modify it under the terms of the GNU @@ -30,10 +30,10 @@ module custom1_noc #( - parameter NOC_ID=0 + parameter NOC_ID=0 ) ( - reset, + reset, clk, //T0, T0_chan_in, @@ -100,127 +100,127 @@ module custom1_noc T15_chan_out, T15_router_event ); - - `NOC_CONF - + + `NOC_CONF + input reset,clk; - /******************* - * T0 - *******************/ + /******************* + * T0 + *******************/ input smartflit_chanel_t T0_chan_in; output smartflit_chanel_t T0_chan_out; output router_event_t T0_router_event; - /******************* - * T1 - *******************/ + /******************* + * T1 + *******************/ input smartflit_chanel_t T1_chan_in; output smartflit_chanel_t T1_chan_out; output router_event_t T1_router_event; - /******************* - * T2 - *******************/ + /******************* + * T2 + *******************/ input smartflit_chanel_t T2_chan_in; output smartflit_chanel_t T2_chan_out; output router_event_t T2_router_event; - /******************* - * T3 - *******************/ + /******************* + * T3 + *******************/ input smartflit_chanel_t T3_chan_in; output smartflit_chanel_t T3_chan_out; output router_event_t T3_router_event; - /******************* - * T4 - *******************/ + /******************* + * T4 + *******************/ input smartflit_chanel_t T4_chan_in; output smartflit_chanel_t T4_chan_out; output router_event_t T4_router_event; - /******************* - * T5 - *******************/ + /******************* + * T5 + *******************/ input smartflit_chanel_t T5_chan_in; output smartflit_chanel_t T5_chan_out; output router_event_t T5_router_event; - /******************* - * T6 - *******************/ + /******************* + * T6 + *******************/ input smartflit_chanel_t T6_chan_in; output smartflit_chanel_t T6_chan_out; output router_event_t T6_router_event; - /******************* - * T7 - *******************/ + /******************* + * T7 + *******************/ input smartflit_chanel_t T7_chan_in; output smartflit_chanel_t T7_chan_out; output router_event_t T7_router_event; - /******************* - * T8 - *******************/ + /******************* + * T8 + *******************/ input smartflit_chanel_t T8_chan_in; output smartflit_chanel_t T8_chan_out; output router_event_t T8_router_event; - /******************* - * T9 - *******************/ + /******************* + * T9 + *******************/ input smartflit_chanel_t T9_chan_in; output smartflit_chanel_t T9_chan_out; output router_event_t T9_router_event; - /******************* - * T10 - *******************/ + /******************* + * T10 + *******************/ input smartflit_chanel_t T10_chan_in; output smartflit_chanel_t T10_chan_out; output router_event_t T10_router_event; - /******************* - * T11 - *******************/ + /******************* + * T11 + *******************/ input smartflit_chanel_t T11_chan_in; output smartflit_chanel_t T11_chan_out; output router_event_t T11_router_event; - /******************* - * T12 - *******************/ + /******************* + * T12 + *******************/ input smartflit_chanel_t T12_chan_in; output smartflit_chanel_t T12_chan_out; output router_event_t T12_router_event; - /******************* - * T13 - *******************/ + /******************* + * T13 + *******************/ input smartflit_chanel_t T13_chan_in; output smartflit_chanel_t T13_chan_out; output router_event_t T13_router_event; - /******************* - * T14 - *******************/ + /******************* + * T14 + *******************/ input smartflit_chanel_t T14_chan_in; output smartflit_chanel_t T14_chan_out; output router_event_t T14_router_event; - /******************* - * T15 - *******************/ + /******************* + * T15 + *******************/ input smartflit_chanel_t T15_chan_in; output smartflit_chanel_t T15_chan_out; output router_event_t T15_router_event; - /******************* - * R0 - *******************/ + /******************* + * R0 + *******************/ wire R0_clk; wire R0_reset; @@ -231,9 +231,9 @@ module custom1_noc router_event_t R0_router_event [3-1 : 0]; - /******************* - * R1 - *******************/ + /******************* + * R1 + *******************/ wire R1_clk; wire R1_reset; @@ -244,9 +244,9 @@ module custom1_noc router_event_t R1_router_event [3-1 : 0]; - /******************* - * R2 - *******************/ + /******************* + * R2 + *******************/ wire R2_clk; wire R2_reset; @@ -257,9 +257,9 @@ module custom1_noc router_event_t R2_router_event [3-1 : 0]; - /******************* - * R3 - *******************/ + /******************* + * R3 + *******************/ wire R3_clk; wire R3_reset; @@ -270,9 +270,9 @@ module custom1_noc router_event_t R3_router_event [3-1 : 0]; - /******************* - * R4 - *******************/ + /******************* + * R4 + *******************/ wire R4_clk; wire R4_reset; @@ -283,9 +283,9 @@ module custom1_noc router_event_t R4_router_event [4-1 : 0]; - /******************* - * R5 - *******************/ + /******************* + * R5 + *******************/ wire R5_clk; wire R5_reset; @@ -296,9 +296,9 @@ module custom1_noc router_event_t R5_router_event [4-1 : 0]; - /******************* - * R6 - *******************/ + /******************* + * R6 + *******************/ wire R6_clk; wire R6_reset; @@ -309,9 +309,9 @@ module custom1_noc router_event_t R6_router_event [4-1 : 0]; - /******************* - * R7 - *******************/ + /******************* + * R7 + *******************/ wire R7_clk; wire R7_reset; @@ -322,9 +322,9 @@ module custom1_noc router_event_t R7_router_event [4-1 : 0]; - /******************* - * R12 - *******************/ + /******************* + * R12 + *******************/ wire R12_clk; wire R12_reset; @@ -335,9 +335,9 @@ module custom1_noc router_event_t R12_router_event [4-1 : 0]; - /******************* - * R13 - *******************/ + /******************* + * R13 + *******************/ wire R13_clk; wire R13_reset; @@ -348,9 +348,9 @@ module custom1_noc router_event_t R13_router_event [4-1 : 0]; - /******************* - * R14 - *******************/ + /******************* + * R14 + *******************/ wire R14_clk; wire R14_reset; @@ -361,9 +361,9 @@ module custom1_noc router_event_t R14_router_event [4-1 : 0]; - /******************* - * R15 - *******************/ + /******************* + * R15 + *******************/ wire R15_clk; wire R15_reset; @@ -374,9 +374,9 @@ module custom1_noc router_event_t R15_router_event [4-1 : 0]; - /******************* - * R8 - *******************/ + /******************* + * R8 + *******************/ wire R8_clk; wire R8_reset; @@ -387,9 +387,9 @@ module custom1_noc router_event_t R8_router_event [5-1 : 0]; - /******************* - * R9 - *******************/ + /******************* + * R9 + *******************/ wire R9_clk; wire R9_reset; @@ -400,9 +400,9 @@ module custom1_noc router_event_t R9_router_event [5-1 : 0]; - /******************* - * R10 - *******************/ + /******************* + * R10 + *******************/ wire R10_clk; wire R10_reset; @@ -413,9 +413,9 @@ module custom1_noc router_event_t R10_router_event [5-1 : 0]; - /******************* - * R11 - *******************/ + /******************* + * R11 + *******************/ wire R11_clk; wire R11_reset; @@ -427,24 +427,23 @@ module custom1_noc - - /******************* - * R0 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(3) - ) - R0 - ( - .clk(R0_clk), - .reset(R0_reset), - .current_r_id(0), - .current_r_addr (R0_current_r_addr), - .chan_in (R0_chan_in), - .chan_out (R0_chan_out), - .router_event (R0_router_event) - ); + + /******************* + * R0 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(0), + .P(3) + ) R0 ( + .clk(R0_clk), + .reset(R0_reset), + .current_r_id(0), + .current_r_addr (R0_current_r_addr), + .chan_in (R0_chan_in), + .chan_out (R0_chan_out), + .router_event (R0_router_event) + ); assign R0_clk = clk; assign R0_reset = reset; @@ -457,24 +456,23 @@ module custom1_noc assign R0_chan_in [1] = R14_chan_out [3]; //Connect R0 port 2 to R13 port 3 assign R0_chan_in [2] = R13_chan_out [3]; - - /******************* - * R1 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(3) - ) - R1 - ( - .clk(R1_clk), - .reset(R1_reset), - .current_r_id(1), - .current_r_addr (R1_current_r_addr), - .chan_in (R1_chan_in), - .chan_out (R1_chan_out), - .router_event (R1_router_event) - ); + + /******************* + * R1 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(1), + .P(3) + ) R1 ( + .clk(R1_clk), + .reset(R1_reset), + .current_r_id(1), + .current_r_addr (R1_current_r_addr), + .chan_in (R1_chan_in), + .chan_out (R1_chan_out), + .router_event (R1_router_event) + ); assign R1_clk = clk; assign R1_reset = reset; @@ -487,24 +485,23 @@ module custom1_noc assign R1_chan_in [1] = R7_chan_out [3]; //Connect R1 port 2 to R2 port 2 assign R1_chan_in [2] = R2_chan_out [2]; - - /******************* - * R2 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(3) - ) - R2 - ( - .clk(R2_clk), - .reset(R2_reset), - .current_r_id(2), - .current_r_addr (R2_current_r_addr), - .chan_in (R2_chan_in), - .chan_out (R2_chan_out), - .router_event (R2_router_event) - ); + + /******************* + * R2 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(2), + .P(3) + ) R2 ( + .clk(R2_clk), + .reset(R2_reset), + .current_r_id(2), + .current_r_addr (R2_current_r_addr), + .chan_in (R2_chan_in), + .chan_out (R2_chan_out), + .router_event (R2_router_event) + ); assign R2_clk = clk; assign R2_reset = reset; @@ -517,24 +514,23 @@ module custom1_noc assign R2_chan_in [1] = R15_chan_out [2]; //Connect R2 port 2 to R1 port 2 assign R2_chan_in [2] = R1_chan_out [2]; - - /******************* - * R3 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(3) - ) - R3 - ( - .clk(R3_clk), - .reset(R3_reset), - .current_r_id(3), - .current_r_addr (R3_current_r_addr), - .chan_in (R3_chan_in), - .chan_out (R3_chan_out), - .router_event (R3_router_event) - ); + + /******************* + * R3 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(3), + .P(3) + ) R3 ( + .clk(R3_clk), + .reset(R3_reset), + .current_r_id(3), + .current_r_addr (R3_current_r_addr), + .chan_in (R3_chan_in), + .chan_out (R3_chan_out), + .router_event (R3_router_event) + ); assign R3_clk = clk; assign R3_reset = reset; @@ -547,24 +543,23 @@ module custom1_noc assign R3_chan_in [1] = R15_chan_out [3]; //Connect R3 port 2 to R4 port 2 assign R3_chan_in [2] = R4_chan_out [2]; - - /******************* - * R4 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R4 - ( - .clk(R4_clk), - .reset(R4_reset), - .current_r_id(4), - .current_r_addr (R4_current_r_addr), - .chan_in (R4_chan_in), - .chan_out (R4_chan_out), - .router_event (R4_router_event) - ); + + /******************* + * R4 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(4), + .P(4) + ) R4 ( + .clk(R4_clk), + .reset(R4_reset), + .current_r_id(4), + .current_r_addr (R4_current_r_addr), + .chan_in (R4_chan_in), + .chan_out (R4_chan_out), + .router_event (R4_router_event) + ); assign R4_clk = clk; assign R4_reset = reset; @@ -579,24 +574,23 @@ module custom1_noc assign R4_chan_in [2] = R3_chan_out [2]; //Connect R4 port 3 to R6 port 3 assign R4_chan_in [3] = R6_chan_out [3]; - - /******************* - * R5 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R5 - ( - .clk(R5_clk), - .reset(R5_reset), - .current_r_id(5), - .current_r_addr (R5_current_r_addr), - .chan_in (R5_chan_in), - .chan_out (R5_chan_out), - .router_event (R5_router_event) - ); + + /******************* + * R5 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(5), + .P(4) + ) R5 ( + .clk(R5_clk), + .reset(R5_reset), + .current_r_id(5), + .current_r_addr (R5_current_r_addr), + .chan_in (R5_chan_in), + .chan_out (R5_chan_out), + .router_event (R5_router_event) + ); assign R5_clk = clk; assign R5_reset = reset; @@ -611,24 +605,23 @@ module custom1_noc assign R5_chan_in [2] = R6_chan_out [2]; //Connect R5 port 3 to R13 port 2 assign R5_chan_in [3] = R13_chan_out [2]; - - /******************* - * R6 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R6 - ( - .clk(R6_clk), - .reset(R6_reset), - .current_r_id(6), - .current_r_addr (R6_current_r_addr), - .chan_in (R6_chan_in), - .chan_out (R6_chan_out), - .router_event (R6_router_event) - ); + + /******************* + * R6 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(6), + .P(4) + ) R6 ( + .clk(R6_clk), + .reset(R6_reset), + .current_r_id(6), + .current_r_addr (R6_current_r_addr), + .chan_in (R6_chan_in), + .chan_out (R6_chan_out), + .router_event (R6_router_event) + ); assign R6_clk = clk; assign R6_reset = reset; @@ -643,24 +636,23 @@ module custom1_noc assign R6_chan_in [2] = R5_chan_out [2]; //Connect R6 port 3 to R4 port 3 assign R6_chan_in [3] = R4_chan_out [3]; - - /******************* - * R7 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R7 - ( - .clk(R7_clk), - .reset(R7_reset), - .current_r_id(7), - .current_r_addr (R7_current_r_addr), - .chan_in (R7_chan_in), - .chan_out (R7_chan_out), - .router_event (R7_router_event) - ); + + /******************* + * R7 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(7), + .P(4) + ) R7 ( + .clk(R7_clk), + .reset(R7_reset), + .current_r_id(7), + .current_r_addr (R7_current_r_addr), + .chan_in (R7_chan_in), + .chan_out (R7_chan_out), + .router_event (R7_router_event) + ); assign R7_clk = clk; assign R7_reset = reset; @@ -675,24 +667,23 @@ module custom1_noc assign R7_chan_in [2] = R14_chan_out [2]; //Connect R7 port 3 to R1 port 1 assign R7_chan_in [3] = R1_chan_out [1]; - - /******************* - * R12 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R12 - ( - .clk(R12_clk), - .reset(R12_reset), - .current_r_id(8), - .current_r_addr (R12_current_r_addr), - .chan_in (R12_chan_in), - .chan_out (R12_chan_out), - .router_event (R12_router_event) - ); + + /******************* + * R12 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(8), + .P(4) + ) R12 ( + .clk(R12_clk), + .reset(R12_reset), + .current_r_id(8), + .current_r_addr (R12_current_r_addr), + .chan_in (R12_chan_in), + .chan_out (R12_chan_out), + .router_event (R12_router_event) + ); assign R12_clk = clk; assign R12_reset = reset; @@ -707,24 +698,23 @@ module custom1_noc assign R12_chan_in [2] = R10_chan_out [3]; //Connect R12 port 3 to R7 port 1 assign R12_chan_in [3] = R7_chan_out [1]; - - /******************* - * R13 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R13 - ( - .clk(R13_clk), - .reset(R13_reset), - .current_r_id(9), - .current_r_addr (R13_current_r_addr), - .chan_in (R13_chan_in), - .chan_out (R13_chan_out), - .router_event (R13_router_event) - ); + + /******************* + * R13 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(9), + .P(4) + ) R13 ( + .clk(R13_clk), + .reset(R13_reset), + .current_r_id(9), + .current_r_addr (R13_current_r_addr), + .chan_in (R13_chan_in), + .chan_out (R13_chan_out), + .router_event (R13_router_event) + ); assign R13_clk = clk; assign R13_reset = reset; @@ -739,24 +729,23 @@ module custom1_noc assign R13_chan_in [2] = R5_chan_out [3]; //Connect R13 port 3 to R0 port 2 assign R13_chan_in [3] = R0_chan_out [2]; - - /******************* - * R14 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R14 - ( - .clk(R14_clk), - .reset(R14_reset), - .current_r_id(10), - .current_r_addr (R14_current_r_addr), - .chan_in (R14_chan_in), - .chan_out (R14_chan_out), - .router_event (R14_router_event) - ); + + /******************* + * R14 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(10), + .P(4) + ) R14 ( + .clk(R14_clk), + .reset(R14_reset), + .current_r_id(10), + .current_r_addr (R14_current_r_addr), + .chan_in (R14_chan_in), + .chan_out (R14_chan_out), + .router_event (R14_router_event) + ); assign R14_clk = clk; assign R14_reset = reset; @@ -771,24 +760,23 @@ module custom1_noc assign R14_chan_in [2] = R7_chan_out [2]; //Connect R14 port 3 to R0 port 1 assign R14_chan_in [3] = R0_chan_out [1]; - - /******************* - * R15 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - R15 - ( - .clk(R15_clk), - .reset(R15_reset), - .current_r_id(11), - .current_r_addr (R15_current_r_addr), - .chan_in (R15_chan_in), - .chan_out (R15_chan_out), - .router_event (R15_router_event) - ); + + /******************* + * R15 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(11), + .P(4) + ) R15 ( + .clk(R15_clk), + .reset(R15_reset), + .current_r_id(11), + .current_r_addr (R15_current_r_addr), + .chan_in (R15_chan_in), + .chan_out (R15_chan_out), + .router_event (R15_router_event) + ); assign R15_clk = clk; assign R15_reset = reset; @@ -803,24 +791,23 @@ module custom1_noc assign R15_chan_in [2] = R2_chan_out [1]; //Connect R15 port 3 to R3 port 1 assign R15_chan_in [3] = R3_chan_out [1]; - - /******************* - * R8 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(5) - ) - R8 - ( - .clk(R8_clk), - .reset(R8_reset), - .current_r_id(12), - .current_r_addr (R8_current_r_addr), - .chan_in (R8_chan_in), - .chan_out (R8_chan_out), - .router_event (R8_router_event) - ); + + /******************* + * R8 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(12), + .P(5) + ) R8 ( + .clk(R8_clk), + .reset(R8_reset), + .current_r_id(12), + .current_r_addr (R8_current_r_addr), + .chan_in (R8_chan_in), + .chan_out (R8_chan_out), + .router_event (R8_router_event) + ); assign R8_clk = clk; assign R8_reset = reset; @@ -837,24 +824,23 @@ module custom1_noc assign R8_chan_in [3] = R14_chan_out [1]; //Connect R8 port 4 to R12 port 1 assign R8_chan_in [4] = R12_chan_out [1]; - - /******************* - * R9 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(5) - ) - R9 - ( - .clk(R9_clk), - .reset(R9_reset), - .current_r_id(13), - .current_r_addr (R9_current_r_addr), - .chan_in (R9_chan_in), - .chan_out (R9_chan_out), - .router_event (R9_router_event) - ); + + /******************* + * R9 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(13), + .P(5) + ) R9 ( + .clk(R9_clk), + .reset(R9_reset), + .current_r_id(13), + .current_r_addr (R9_current_r_addr), + .chan_in (R9_chan_in), + .chan_out (R9_chan_out), + .router_event (R9_router_event) + ); assign R9_clk = clk; assign R9_reset = reset; @@ -871,24 +857,23 @@ module custom1_noc assign R9_chan_in [3] = R6_chan_out [1]; //Connect R9 port 4 to R10 port 2 assign R9_chan_in [4] = R10_chan_out [2]; - - /******************* - * R10 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(5) - ) - R10 - ( - .clk(R10_clk), - .reset(R10_reset), - .current_r_id(14), - .current_r_addr (R10_current_r_addr), - .chan_in (R10_chan_in), - .chan_out (R10_chan_out), - .router_event (R10_router_event) - ); + + /******************* + * R10 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(14), + .P(5) + ) R10 ( + .clk(R10_clk), + .reset(R10_reset), + .current_r_id(14), + .current_r_addr (R10_current_r_addr), + .chan_in (R10_chan_in), + .chan_out (R10_chan_out), + .router_event (R10_router_event) + ); assign R10_clk = clk; assign R10_reset = reset; @@ -905,24 +890,23 @@ module custom1_noc assign R10_chan_in [3] = R12_chan_out [2]; //Connect R10 port 4 to R15 port 1 assign R10_chan_in [4] = R15_chan_out [1]; - - /******************* - * R11 - *******************/ - router_top #( - .NOC_ID(NOC_ID), - .P(5) - ) - R11 - ( - .clk(R11_clk), - .reset(R11_reset), - .current_r_id(15), - .current_r_addr (R11_current_r_addr), - .chan_in (R11_chan_in), - .chan_out (R11_chan_out), - .router_event (R11_router_event) - ); + + /******************* + * R11 + *******************/ + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(15), + .P(5) + ) R11 ( + .clk(R11_clk), + .reset(R11_reset), + .current_r_id(15), + .current_r_addr (R11_current_r_addr), + .chan_in (R11_chan_in), + .chan_out (R11_chan_out), + .router_event (R11_router_event) + ); assign R11_clk = clk; assign R11_reset = reset; diff --git a/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv b/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv index 2b2a459..2ead929 100644 --- a/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv +++ b/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv @@ -6,11 +6,11 @@ /********************************************************************** -** File: /home/alireza/work/git/pronoc/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv ** -** Copyright (C) 2014-2021 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.1.0 +** This file is part of ProNoC 2.2.0 ** ** ProNoC ( stands for Prototype Network-on-chip) is free software: ** you can redistribute it and/or modify it under the terms of the GNU @@ -30,7 +30,7 @@ module custom1_noc_genvar #( - parameter NOC_ID=0 + parameter NOC_ID=0 )( reset, @@ -66,78 +66,75 @@ module custom1_noc_genvar - genvar i; - generate - + genvar i; + generate + for( i=0; i<4; i=i+1) begin : router_3_port_lp - localparam RID = i; - assign current_r_addr [RID] = RID[RAw-1: 0]; + localparam RID = i; + assign current_r_addr [RID] = RID[RAw-1: 0]; - router_top #( - .NOC_ID(NOC_ID), - .P(3) - ) - router_3_port - ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr[RID]), - .chan_in (router_chan_in [RID] [2 : 0]), - .chan_out (router_chan_out[RID] [2 : 0]), - .router_event(router_event[RID] [2 : 0]) - ); + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P(3) + ) router_3_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr[RID]), + .chan_in (router_chan_in [RID] [2 : 0]), + .chan_out (router_chan_out[RID] [2 : 0]), + .router_event(router_event[RID] [2 : 0]) + ); - end - + end + for( i=0; i<8; i=i+1) begin : router_4_port_lp - localparam RID = i+4; - assign current_r_addr [RID] = RID[RAw-1: 0]; + localparam RID = i+4; + assign current_r_addr [RID] = RID[RAw-1: 0]; - router_top #( - .NOC_ID(NOC_ID), - .P(4) - ) - router_4_port - ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr[RID]), - .chan_in (router_chan_in [RID] [3 : 0]), - .chan_out (router_chan_out[RID] [3 : 0]), - .router_event(router_event[RID] [3 : 0]) - ); + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P(4) + ) router_4_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr[RID]), + .chan_in (router_chan_in [RID] [3 : 0]), + .chan_out (router_chan_out[RID] [3 : 0]), + .router_event(router_event[RID] [3 : 0]) + ); - end - + end + for( i=0; i<4; i=i+1) begin : router_5_port_lp - localparam RID = i+12; - assign current_r_addr [RID] = RID[RAw-1: 0]; + localparam RID = i+12; + assign current_r_addr [RID] = RID[RAw-1: 0]; - router_top #( - .NOC_ID(NOC_ID), - .P(5) - ) - router_5_port - ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr[RID]), - .chan_in (router_chan_in [RID] [4 : 0]), - .chan_out (router_chan_out[RID] [4 : 0]), - .router_event(router_event[RID] [4 : 0]) - ); + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P(5) + ) router_5_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr[RID]), + .chan_in (router_chan_in [RID] [4 : 0]), + .chan_out (router_chan_out[RID] [4 : 0]), + .router_event(router_event[RID] [4 : 0]) + ); - end - endgenerate + end + endgenerate //Connect R0 input ports 0 to T0 output ports 0 diff --git a/mpsoc/rtl/src_topology/custom_flist.f b/mpsoc/rtl/src_topology/custom_flist.f index 84acb86..3a4b667 100644 --- a/mpsoc/rtl/src_topology/custom_flist.f +++ b/mpsoc/rtl/src_topology/custom_flist.f @@ -1,10 +1,10 @@ +incdir+./ +./common/custom_lkh_routing.v +./common/custom_ni_routing.v +./common/custom_noc_top.sv +./custom1/custom1_noc.sv +./custom1/Tcustom1Rcustom_look_ahead_routing.v ./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v ./custom1/custom1_noc_genvar.sv -./custom1/Tcustom1Rcustom_conventional_routing_genvar.v -./custom1/custom1_noc.sv ./custom1/Tcustom1Rcustom_conventional_routing.v -./custom1/Tcustom1Rcustom_look_ahead_routing.v -./common/custom_ni_routing.v -./common/custom_noc_top.sv -./common/custom_lkh_routing.v +./custom1/Tcustom1Rcustom_conventional_routing_genvar.v diff --git a/mpsoc/rtl/src_topology/param.obj b/mpsoc/rtl/src_topology/param.obj index 0d11666..0315176 100644 --- a/mpsoc/rtl/src_topology/param.obj +++ b/mpsoc/rtl/src_topology/param.obj @@ -1,9 +1,9 @@ ####################################################################### -## File: /home/alireza/work/git/pronoc/mpsoc/rtl/src_topology/param.obj +## File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/param.obj ## -## Copyright (C) 2014-2021 Alireza Monemi +## Copyright (C) 2014-2022 Alireza Monemi ## -## This file is part of ProNoC 2.1.0 +## This file is part of ProNoC 2.2.0 ## ## WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ## MAY CAUSE UNEXPECTED BEHAVIOR. @@ -11,6 +11,10 @@ $Topology = { '"mesh4x4"' => { + 'ROUTER_Ps' => { + '5' => 16 + }, + 'T1' => 16, 'er_addr' => [ 4, 5, @@ -29,15 +33,14 @@ $Topology = { 14, 15 ], - 'T3' => 5, - 'T1' => 16, - 'ROUTE_NAME' => '"custom","m4"', 'T2' => 16, - 'ROUTER_Ps' => { - '5' => 16 - } + 'T3' => 5, + 'ROUTE_NAME' => '"custom","m4"' }, '"custom1"' => { + 'ROUTE_NAME' => '"custom"', + 'T3' => 5, + 'T1' => 16, 'T2' => 16, 'er_addr' => [ 0, @@ -58,12 +61,9 @@ $Topology = { 15 ], 'ROUTER_Ps' => { - '3' => 4, '5' => 4, + '3' => 4, '4' => 8 - }, - 'T1' => 16, - 'ROUTE_NAME' => '"custom"', - 'T3' => 5 + } } }; diff --git a/mpsoc/src_verilator/topology/custom/custom1_noc.h b/mpsoc/src_verilator/topology/custom/custom1_noc.h index e5dbcc4..7f9d34b 100644 --- a/mpsoc/src_verilator/topology/custom/custom1_noc.h +++ b/mpsoc/src_verilator/topology/custom/custom1_noc.h @@ -145,17 +145,17 @@ single_r2e0,single_r2e1,single_r2e2,single_r2e3,single_r2e4,single_r2e5,single_r ,single_r2e10,single_r2e11,single_r2e12,single_r2e13,single_r2e14,single_r2e15}; void topology_connect_r2r (int n){ - (*r2r_func_ptr[n])(); + (*r2r_func_ptr[n])(); } void topology_connect_r2e (int n){ - (*r2e_func_ptr[n])(); + (*r2e_func_ptr[n])(); } void topology_init(void){ - router1[0]->current_r_addr=0; + router1[0]->current_r_addr=0; router1[0]->current_r_id=0; router1[1]->current_r_addr=1; router1[1]->current_r_id=1; @@ -236,6 +236,6 @@ router3[3]->current_r_id=15; r2r_cnt_all[46] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=3,.id2=13, .t2=3, .r2=1, .p2=1 }; r2r_cnt_all[47] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=4,.id2=5, .t2=2, .r2=1, .p2=1 }; - R2R_TABLE_SIZ=48; - + R2R_TABLE_SIZ=48; + } From 3a9a32df31e17e22974a40ce1f977b7eedc84400 Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 5 Feb 2025 01:31:33 +0100 Subject: [PATCH 007/107] fix questasim NoC simulation bug --- mpsoc/perl_gui/lib/perl/compile.pl | 4892 ++++++++----------- mpsoc/perl_gui/lib/perl/simulator.pl | 57 +- mpsoc/rtl/src_modelsim/noc_sim_statistic.sv | 235 +- mpsoc/rtl/src_modelsim/testbench_noc.sv | 1611 +++--- mpsoc/rtl/src_noc/input_ports.sv | 2 +- mpsoc/rtl/src_noc/pronoc_pkg.sv | 19 +- mpsoc/rtl/src_noc/router_two_stage.sv | 2 +- mpsoc/src_verilator/simulator.cpp | 938 ++-- 8 files changed, 3357 insertions(+), 4399 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/compile.pl b/mpsoc/perl_gui/lib/perl/compile.pl index fdd3378..f63d7bd 100644 --- a/mpsoc/perl_gui/lib/perl/compile.pl +++ b/mpsoc/perl_gui/lib/perl/compile.pl @@ -2,814 +2,642 @@ use constant::boolean; use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - use soc; - - use File::Path; use File::Find::Rule; use File::Copy; use File::Copy::Recursive qw(dircopy); use Cwd 'abs_path'; use Verilog::EditFiles; - - - use List::MoreUtils qw( minmax ); - - ################ -# Compile +# Compile ################# - - sub is_capital_sensitive() { - my ($cell_layout, $cell, $tree_model, $iter, $data) = @_; - my $sensitive = !$tree_model->iter_has_child($iter); - $cell->set('sensitive', $sensitive); + my ($cell_layout, $cell, $tree_model, $iter, $data) = @_; + my $sensitive = !$tree_model->iter_has_child($iter); + $cell->set('sensitive', $sensitive); } - - sub get_range { - my ($board,$self,$porttype,$assignname,$portrange,$portname) =@_; - my $box= def_hbox(FALSE,0); - my @range=$board->board_get_pin_range($porttype,$assignname); - - - if ($range[0] ne '*undefine*'){ - my $content = join(",", @range); - my ($min, $max) = minmax @range; - if (length($portrange)!=0){ - my $range_hsb=gen_combobox_object($self,'compile_pin_range_hsb',$portname,$content,$max,undef,undef); - $box->pack_start( $range_hsb, FALSE, FALSE, 0); - $box->pack_start(gen_label_in_center(':'),, FALSE, FALSE, 0); - } - - my $range_lsb=gen_combobox_object($self,'compile_pin_range_lsb',$portname,$content,$min,undef,undef); - $box->pack_start( $range_lsb, FALSE, FALSE, 0); - - } - return $box; - + my ($board,$self,$porttype,$assignname,$portrange,$portname) =@_; + my $box= def_hbox(FALSE,0); + my @range=$board->board_get_pin_range($porttype,$assignname); + if ($range[0] ne '*undefine*'){ + my $content = join(",", @range); + my ($min, $max) = minmax @range; + if (length($portrange)!=0){ + my $range_hsb=gen_combobox_object($self,'compile_pin_range_hsb',$portname,$content,$max,undef,undef); + $box->pack_start( $range_hsb, FALSE, FALSE, 0); + $box->pack_start(gen_label_in_center(':'),, FALSE, FALSE, 0); + } + my $range_lsb=gen_combobox_object($self,'compile_pin_range_lsb',$portname,$content,$min,undef,undef); + $box->pack_start( $range_lsb, FALSE, FALSE, 0); + + } + return $box; } - sub read_top_v_file{ - my $top_v=shift; - my $board = soc->board_new(); - my $vdb=read_verilog_file($top_v); - my @modules=sort $vdb->get_modules($top_v); - my %Ptypes=get_ports_type($vdb,$modules[0]); - my %Pranges=get_ports_rang($vdb,$modules[0]); - foreach my $p (sort keys %Ptypes){ - my $Ptype=$Ptypes{$p}; - my $Prange=$Pranges{$p}; - my $type=($Ptype eq "input")? "Input" : ($Ptype eq "output")? 'Output' : 'Bidir'; - if ( $Prange ne ''){ - my @r=split(":",$Prange); - my $a=($r[0]<$r[1])? $r[0] : $r[1]; - my $b=($r[0]<$r[1])? $r[1] : $r[0]; - for (my $i=$a; $i<=$b; $i++){ - $board->board_add_pin ($type,"$p\[$i\]"); - - } - } - else {$board->board_add_pin ($type,$p);} - } - return $board; + my $top_v=shift; + my $board = soc->board_new(); + my $vdb=read_verilog_file($top_v); + my @modules=sort $vdb->get_modules($top_v); + my %Ptypes=get_ports_type($vdb,$modules[0]); + my %Pranges=get_ports_rang($vdb,$modules[0]); + foreach my $p (sort keys %Ptypes){ + my $Ptype=$Ptypes{$p}; + my $Prange=$Pranges{$p}; + my $type=($Ptype eq "input")? "Input" : ($Ptype eq "output")? 'Output' : 'Bidir'; + if ( $Prange ne ''){ + my @r=split(":",$Prange); + my $a=($r[0]<$r[1])? $r[0] : $r[1]; + my $b=($r[0]<$r[1])? $r[1] : $r[0]; + for (my $i=$a; $i<=$b; $i++){ + $board->board_add_pin ($type,"$p\[$i\]"); + + } + } + else {$board->board_add_pin ($type,$p);} + } + return $board; } - - - sub gen_top_v{ - my ($self,$board,$name,$top)=@_; - - my $top_v=get_license_header("Top.v"); - #read port list - my $vdb=read_verilog_file($top); - my %port_type=get_ports_type($vdb,"${name}_top"); - my %port_range=get_ports_rang($vdb,"${name}_top"); - - - my $io=''; - my $io_def=''; - my $io_assign=''; - my %board_io; - my $first=1; - foreach my $p (sort keys %port_type){ - my $porttype=$port_type{$p}; - my $portrange=$port_range{$p}; - my $assign_type = $self->object_get_attribute('compile_assign_type',$p); - my $assign_name = $self->object_get_attribute('compile_pin',$p); - my $range_hsb = $self->object_get_attribute('compile_pin_range_hsb',$p); - my $range_lsb = $self->object_get_attribute('compile_pin_range_lsb',$p); - my $assign="\t"; - if (defined $assign_name){ - if($assign_name eq '*VCC'){ - $assign= (length($portrange)!=0)? '{32{1\'b1}}' : '1\'b1'; - } elsif ($assign_name eq '*GND'){ - $assign= (length($portrange)!=0)? '{32{1\'b0}}' : '1\'b0'; - }elsif ($assign_name eq '*NOCONNECT'){ - $assign="\t"; - - }else{ - - $board_io{$assign_name}=$porttype; - - - my $range = (defined $range_hsb) ? "[$range_hsb : $range_lsb]" : - (defined $range_lsb) ? "[ $range_lsb]" : " "; - my $l=(defined $assign_type)? - ($assign_type eq 'Direct') ? '' : '~' : ''; - $assign="$l $assign_name $range"; - - - } - } - $io_assign= ($first)? "$io_assign \t .$p($assign)":"$io_assign,\n \t .$p($assign)"; - $first=0; - } - $first=1; - foreach my $p (sort keys %board_io){ - $io=($first)? "\t$p" : "$io,\n\t$p"; - my $dir=$board_io{$p}; - my $range; - my $type= ($dir eq 'input') ? 'Input' : - ($dir eq 'output')? 'Output' : 'Bidir'; - my @r= $board->board_get_pin_range($type,$p); - if ($r[0] eq '*undefine*'){ - $range="\t\t\t"; - } else { - my ($min, $max) = minmax @r; - $range="\t[$max : $min]\t"; - } - $io_def = "$io_def \t $dir $range $p;\n"; - $first=0; - - } - $top_v="$top_v + my ($self,$board,$name,$top)=@_; + my $top_v=get_license_header("Top.v"); + #read port list + my $vdb=read_verilog_file($top); + my %port_type=get_ports_type($vdb,"${name}_top"); + my %port_range=get_ports_rang($vdb,"${name}_top"); + my $io=''; + my $io_def=''; + my $io_assign=''; + my %board_io; + my $first=1; + foreach my $p (sort keys %port_type){ + my $porttype=$port_type{$p}; + my $portrange=$port_range{$p}; + my $assign_type = $self->object_get_attribute('compile_assign_type',$p); + my $assign_name = $self->object_get_attribute('compile_pin',$p); + my $range_hsb = $self->object_get_attribute('compile_pin_range_hsb',$p); + my $range_lsb = $self->object_get_attribute('compile_pin_range_lsb',$p); + my $assign="\t"; + if (defined $assign_name){ + if($assign_name eq '*VCC'){ + $assign= (length($portrange)!=0)? '{32{1\'b1}}' : '1\'b1'; + } elsif ($assign_name eq '*GND'){ + $assign= (length($portrange)!=0)? '{32{1\'b0}}' : '1\'b0'; + }elsif ($assign_name eq '*NOCONNECT'){ + $assign="\t"; + }else{ + $board_io{$assign_name}=$porttype; + my $range = (defined $range_hsb) ? "[$range_hsb : $range_lsb]" : + (defined $range_lsb) ? "[ $range_lsb]" : " "; + my $l=(defined $assign_type)? + ($assign_type eq 'Direct') ? '' : '~' : ''; + $assign="$l $assign_name $range"; + } + } + $io_assign= ($first)? "$io_assign \t .$p($assign)":"$io_assign,\n \t .$p($assign)"; + $first=0; + } + $first=1; + foreach my $p (sort keys %board_io){ + $io=($first)? "\t$p" : "$io,\n\t$p"; + my $dir=$board_io{$p}; + my $range; + my $type= ($dir eq 'input') ? 'Input' : + ($dir eq 'output')? 'Output' : 'Bidir'; + my @r= $board->board_get_pin_range($type,$p); + if ($r[0] eq '*undefine*'){ + $range="\t\t\t"; + } else { + my ($min, $max) = minmax @r; + $range="\t[$max : $min]\t"; + } + $io_def = "$io_def \t $dir $range $p;\n"; + $first=0; + } + $top_v="$top_v module Top ( $io ); $io_def - ${name}_top uut( + ${name}_top uut( $io_assign - ); - + ); endmodule "; - my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); - my $board_top_file= "$fpath/Top.v"; - save_file($board_top_file,$top_v); + my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); + my $board_top_file= "$fpath/Top.v"; + save_file($board_top_file,$top_v); } - - - sub select_compiler { - my ($self,$name,$top,$target_dir,$end_func)=@_; - my $window = def_popwin_size(40,40,"Step 1: Select Compiler",'percent'); - - my $table = def_table(2, 2, FALSE); - my $col=0; - my $row=0; - - my $compilers=$self->object_get_attribute('compile','compilers');#"QuartusII,Vivado,Verilator,Modelsim" - - my $compiler=gen_combobox_object ($self,'compile','type',$compilers,"QuartusII",undef,undef); - $table->attach(gen_label_in_center("Compiler tool"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - $table->attach($compiler,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - $row++;$col=0; - - my $old_board_name=$self->object_get_attribute('compile','board'); - my $old_compiler=$self->object_get_attribute('compile','type'); - my $vendor= ($old_compiler eq "QuartusII")? 'Altera' : 'Xilinx'; - - #get the list of boards located in "boards/*" folder - my @dirs = grep {-d} glob("../boards/$vendor/*"); - my ($fpgas,$init); - foreach my $dir (@dirs) { - my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); - $init=$name; - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - } - - - my $compiler_options = - ($old_compiler eq "QuartusII")? select_board ($self,$name,$top,$target_dir,$vendor): - ($old_compiler eq "Vivado" )? select_board ($self,$name,$top,$target_dir,$vendor): - ($old_compiler eq "Modelsim" )? select_model_path ($self,$name,$top,$target_dir): - ($old_compiler eq "Verilator")? select_parallel_process_num ($self,$name,$top,$target_dir): - gen_label_in_center(" "); - - $table->attach($compiler_options,$col,$col+2,$row,$row+1,'fill','shrink',2,2); $row++; - - $col=1; - my $i; - for ($i=$row; $i<5; $i++){ - - my $temp=gen_label_in_center(" "); - $table->attach_defaults ($temp, 0, 1 , $i, $i+1); - } - $row=$i; - - - $window->add ($table); - $window->show_all(); - my $next=def_image_button('icons/right.png','_Next',FALSE,1); - $table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; - $next-> signal_connect("clicked" => sub{ - my $compiler_type=$self->object_get_attribute('compile','type'); - if($compiler_type eq "QuartusII" || $compiler_type eq "Vivado"){ - $vendor= ($compiler_type eq "QuartusII")? 'Altera' : 'Xilinx'; - my $new_board_name=$self->object_get_attribute('compile','board'); - if(defined $old_board_name) { - if ($old_board_name ne $new_board_name){ - remove_pin_assignment($self); - my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); - #delete jtag_intfc.sh file - unlink "${fpath}../sw/jtag_intfc.sh"; - #program_device.sh file - unlink "${fpath}../program_device.sh"; - } - - my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); - my $board_top_file= "$fpath/Top.v"; - unlink $board_top_file if ($old_board_name ne $new_board_name); - - - } - if($new_board_name eq "Add New Board") {add_new_fpga_board($self,$name,$top,$target_dir,$end_func,$vendor);} - else {get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor);} - } - - - - - - - elsif($compiler_type eq "Modelsim"){ - modelsim_compilation($self,$name,$top,$target_dir,$vendor); - - }else{#verilator - verilator_compilation_win($self,$name,$top,$target_dir,$vendor); - - } - - $window->destroy; - - }); - - $compiler->signal_connect("changed" => sub{ - $compiler_options->destroy; - my $new_board_name=$self->object_get_attribute('compile','type'); - $compiler_options = - ($new_board_name eq "QuartusII")? select_board ($self,$name,$top,$target_dir,"Altera"): - ($new_board_name eq "Vivado")? select_board ($self,$name,$top,$target_dir,"Xilinx"): - ($new_board_name eq "Modelsim")? select_model_path ($self,$name,$top,$target_dir): - ($new_board_name eq "Verilator")? select_parallel_process_num ($self,$name,$top,$target_dir): - gen_label_in_center(" "); - $table->attach($compiler_options,0,2,1,2,'fill','shrink',2,2); - $table->show_all; - - }); - + my ($self,$name,$top,$target_dir,$end_func)=@_; + my $window = def_popwin_size(40,40,"Step 1: Select Compiler",'percent'); + my $table = def_table(2, 2, FALSE); + my $col=0; + my $row=0; + my $compilers=$self->object_get_attribute('compile','compilers');#"QuartusII,Vivado,Verilator,Modelsim" + my $compiler=gen_combobox_object ($self,'compile','type',$compilers,"QuartusII",undef,undef); + $table->attach(gen_label_in_center("Compiler tool"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; + $table->attach($compiler,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; + $row++;$col=0; + my $old_board_name=$self->object_get_attribute('compile','board'); + my $old_compiler=$self->object_get_attribute('compile','type'); + my $vendor= ($old_compiler eq "QuartusII")? 'Altera' : 'Xilinx'; + + #get the list of boards located in "boards/*" folder + my @dirs = grep {-d} glob("../boards/$vendor/*"); + my ($fpgas,$init); + foreach my $dir (@dirs) { + my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); + $init=$name; + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + } + + my $compiler_options = + ($old_compiler eq "QuartusII")? select_board ($self,$name,$top,$target_dir,$vendor): + ($old_compiler eq "Vivado" )? select_board ($self,$name,$top,$target_dir,$vendor): + ($old_compiler eq "Modelsim" )? select_model_path ($self,$name,$top,$target_dir): + ($old_compiler eq "Verilator")? select_parallel_process_num ($self,$name,$top,$target_dir): + gen_label_in_center(" "); + $table->attach($compiler_options,$col,$col+2,$row,$row+1,'fill','shrink',2,2); $row++; + $col=1; + my $i; + for ($i=$row; $i<5; $i++){ + my $temp=gen_label_in_center(" "); + $table->attach_defaults ($temp, 0, 1 , $i, $i+1); + } + $row=$i; + $window->add ($table); + $window->show_all(); + my $next=def_image_button('icons/right.png','_Next',FALSE,1); + $table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; + $next-> signal_connect("clicked" => sub{ + my $compiler_type=$self->object_get_attribute('compile','type'); + if($compiler_type eq "QuartusII" || $compiler_type eq "Vivado"){ + $vendor= ($compiler_type eq "QuartusII")? 'Altera' : 'Xilinx'; + my $new_board_name=$self->object_get_attribute('compile','board'); + if(defined $old_board_name) { + if ($old_board_name ne $new_board_name){ + remove_pin_assignment($self); + my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); + #delete jtag_intfc.sh file + unlink "${fpath}../sw/jtag_intfc.sh"; + #program_device.sh file + unlink "${fpath}../program_device.sh"; + } + my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); + my $board_top_file= "$fpath/Top.v"; + unlink $board_top_file if ($old_board_name ne $new_board_name); + } + if($new_board_name eq "Add New Board") {add_new_fpga_board($self,$name,$top,$target_dir,$end_func,$vendor);} + else {get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor);} + } + elsif($compiler_type eq "Modelsim"){ + modelsim_compilation($self,$name,$top,$target_dir,$vendor); + }else{#verilator + verilator_compilation_win($self,$name,$top,$target_dir,$vendor); + } + $window->destroy; + }); + + $compiler->signal_connect("changed" => sub{ + $compiler_options->destroy; + my $new_board_name=$self->object_get_attribute('compile','type'); + $compiler_options = + ($new_board_name eq "QuartusII")? select_board ($self,$name,$top,$target_dir,"Altera"): + ($new_board_name eq "Vivado")? select_board ($self,$name,$top,$target_dir,"Xilinx"): + ($new_board_name eq "Modelsim")? select_model_path ($self,$name,$top,$target_dir): + ($new_board_name eq "Verilator")? select_parallel_process_num ($self,$name,$top,$target_dir): + gen_label_in_center(" "); + $table->attach($compiler_options,0,2,1,2,'fill','shrink',2,2); + $table->show_all; + }); } - - - - - sub select_board { - my ($self,$name,$top,$target_dir,$vendor)=@_; - - #get the list of boards located in "boards/*" folder - my @dirs = grep {-d} glob("../boards/$vendor/*"); - my ($fpgas,$init); - $fpgas="Add New Board"; - - foreach my $dir (@dirs) { - my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); - - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - $init="$name"; - } - my $table = def_table(2, 2, FALSE); - my $col=0; - my $row=0; + my ($self,$name,$top,$target_dir,$vendor)=@_; + #get the list of boards located in "boards/*" folder + my @dirs = grep {-d} glob("../boards/$vendor/*"); + my ($fpgas,$init); + $fpgas="Add New Board"; + foreach my $dir (@dirs) { + my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + $init="$name"; + } + my $table = def_table(2, 2, FALSE); + my $col=0; + my $row=0; my $compiler = ($vendor eq "Altera")? 'quartus' : 'vivado'; my $bin_name = "$compiler bin"; my $env = ($vendor eq "Altera")? "QUARTUS_BIN" : "VIVADO_BIN"; - my $Fpga_bin= $ENV{$env}; - - my $old_board_name=$self->object_get_attribute('compile','board'); - $table->attach(gen_label_help("The list of supported boards are obtained from \"mpsoc/boards/$vendor\" path. You can add your boards by adding its required files in aformentioned path. Note that currently Altera and Xilinx FPGAs are supported.",'Targeted Board:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - $table->attach(gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; - my $bin = $self->object_get_attribute('compile',$bin_name); - - $col=0; - $self->object_add_attribute('compile',$bin_name,$Fpga_bin) if (!defined $bin && defined $Fpga_bin); - $table->attach(gen_label_help("Path to $vendor/bin directory. You can set a default path as $env environment variable in ~/.bashrc file. + my $Fpga_bin= $ENV{$env}; + my $old_board_name=$self->object_get_attribute('compile','board'); + $table->attach(gen_label_help("The list of supported boards are obtained from \"mpsoc/boards/$vendor\" path. You can add your boards by adding its required files in aformentioned path. Note that currently Altera and Xilinx FPGAs are supported.",'Targeted Board:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; + $table->attach(gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; + my $bin = $self->object_get_attribute('compile',$bin_name); + $col=0; + $self->object_add_attribute('compile',$bin_name,$Fpga_bin) if (!defined $bin && defined $Fpga_bin); + $table->attach(gen_label_help("Path to $vendor/bin directory. You can set a default path as $env environment variable in ~/.bashrc file. e.g: export $env=/home/alireza/$compiler/bin","$env:"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - $table->attach(get_dir_in_object ($self,'compile',$bin_name,undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; - - - - - - return $table; - + $table->attach(get_dir_in_object ($self,'compile',$bin_name,undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; + return $table; } - - - sub select_model_path { - my ($self,$name,$top,$target_dir)=@_; - - - my $table = def_table(2, 2, FALSE); - my $col=0; - my $row=0; - - - - - my $bin = $self->object_get_attribute('compile','modelsim_bin'); - my $modelsim_bin= $ENV{MODELSIM_BIN}; - $col=0; - $self->object_add_attribute('compile','modelsim_bin',$modelsim_bin) if (!defined $bin && defined $modelsim_bin); - $table->attach(gen_label_help("Path to modelsim/bin directory. You can set a default path as MODELSIM_BIN environment variable in ~/.bashrc file. + my ($self,$name,$top,$target_dir)=@_; + my $table = def_table(2, 2, FALSE); + my $col=0; + my $row=0; + my $bin = $self->object_get_attribute('compile','modelsim_bin'); + my $modelsim_bin= $ENV{MODELSIM_BIN}; + $col=0; + $self->object_add_attribute('compile','modelsim_bin',$modelsim_bin) if (!defined $bin && defined $modelsim_bin); + $table->attach(gen_label_help("Path to modelsim/bin directory. You can set a default path as MODELSIM_BIN environment variable in ~/.bashrc file. e.g. export MODELSIM_BIN=/home/alireza/altera/modeltech/bin",'Modelsim bin:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - $table->attach(get_dir_in_object ($self,'compile','modelsim_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; - - return $table; - + $table->attach(get_dir_in_object ($self,'compile','modelsim_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; + return $table; } my $cpu_num; sub select_parallel_process_num { - my ($self,$name,$top,$target_dir)=@_; - my $table = def_table(2, 2, FALSE); - my $col=0; - my $row=0; - - #get total number of processor in the system - my $cmd = "nproc\n"; - if(!defined $cpu_num){ - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - #nproc command has failed. set default 4 paralel processor - - }else { - my ($number ) = $stdout =~ /(\d+)/; - if (defined $number ){ - $cpu_num =$number if ($number > 0 ); - } - } - } - ($row,$col)= add_param_widget ($self,"Paralle run:" , "cpu_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of processors the Verilator can use at once to run parallel compilations/simulations", $table,$row,$col,1, 'compile', undef,undef,'vertical'); - return $table; + my ($self,$name,$top,$target_dir)=@_; + my $table = def_table(2, 2, FALSE); + my $col=0; + my $row=0; + #get total number of processor in the system + my $cmd = "nproc\n"; + if(!defined $cpu_num){ + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + #nproc command has failed. set default 4 paralel processor + }else { + my ($number ) = $stdout =~ /(\d+)/; + if (defined $number ){ + $cpu_num =$number if ($number > 0 ); + } + } + } + ($row,$col)= add_param_widget ($self,"Paralle run:" , "cpu_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of processors the Verilator can use at once to run parallel compilations/simulations", $table,$row,$col,1, 'compile', undef,undef,'vertical'); + return $table; } sub select_parallel_thread_num { - my ($self,$name,$top,$target_dir)=@_; - my $table = def_table(2, 2, FALSE); - my $col=0; - my $row=0; - - #get total number of processor in the system - my $cmd = "nproc\n"; - if(!defined $cpu_num){ - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - #nproc command has failed. set default 4 paralel processor - - }else { - my ($number ) = $stdout =~ /(\d+)/; - if (defined $number ){ - $cpu_num =$number if ($number > 0 ); - } - } - } - ($row,$col)= add_param_widget ($self,"Thread run:" , "thread_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of threads the Verilator can use at once in one simulation", $table,$row,$col,1, 'compile', undef,undef,'vertical'); - return $table; + my ($self,$name,$top,$target_dir)=@_; + my $table = def_table(2, 2, FALSE); + my $col=0; + my $row=0; + #get total number of processor in the system + my $cmd = "nproc\n"; + if(!defined $cpu_num){ + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + #nproc command has failed. set default 4 paralel processor + }else { + my ($number ) = $stdout =~ /(\d+)/; + if (defined $number ){ + $cpu_num =$number if ($number > 0 ); + } + } + } + ($row,$col)= add_param_widget ($self,"Thread run:" , "thread_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of threads the Verilator can use at once in one simulation", $table,$row,$col,1, 'compile', undef,undef,'vertical'); + return $table; } - - - sub remove_pin_assignment{ - my $self=shift; - $self->object_remove_attribute('compile_pin_pos'); - $self->object_remove_attribute('compile_pin'); - $self->object_remove_attribute('compile_assign_type'); - $self->object_remove_attribute('compile_pin_range_hsb'); - $self->object_remove_attribute('compile_pin_range_lsb'); + my $self=shift; + $self->object_remove_attribute('compile_pin_pos'); + $self->object_remove_attribute('compile_pin'); + $self->object_remove_attribute('compile_assign_type'); + $self->object_remove_attribute('compile_pin_range_hsb'); + $self->object_remove_attribute('compile_pin_range_lsb'); } - - sub add_new_fpga_board{ - - my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_; - - my $window = def_popwin_size(50,80,"Add New $vendor FPGA Board",'percent'); - my $table = def_table(2, 2, FALSE); - my $scrolled_win=add_widget_to_scrolled_win($table); - - - my $mtable = def_table(10, 10, FALSE); - - my $next=def_image_button('icons/plus.png','Add'); - my $back=def_image_button('icons/left.png','Previous'); - $mtable->attach_defaults($scrolled_win,0,10,0,9); - $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2) if (defined $name); - $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2); - - - my ($Twin,$tview)=create_txview(); - - - my $widgets= - ($vendor eq 'Altera')? add_new_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor): - add_new_xilinx_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor,$tview); - - - - my $v1=gen_vpaned($widgets,0.3,$Twin); - - $table->attach_defaults($v1,0,3,0,2); - #$table->attach_defaults( $Twin,0,3,1,2); - - - - - $back-> signal_connect("clicked" => sub{ - - $window->destroy; - select_compiler($self,$name,$top,$target_dir,$end_func); - - }); - - $next-> signal_connect("clicked" => sub{ - my $result = ($vendor eq 'Altera')? - add_new_altera_fpga_board_files($self,$vendor): - add_new_xilinx_fpga_board_files($self,$vendor); - - if(! defined $result ){ - select_compiler($self,$name,$top,$target_dir,$end_func) if (defined $name); - $window->destroy; - message_dialog("The new board has been added successfully!"); - }else { - show_info($tview," "); - show_colored_info($tview,$result,'red'); - } - - }); - - - - if($vendor eq 'Altera'){ - my $auto=def_image_button('icons/advance.png','Auto-fill'); - set_tip($auto, "Auto-fill JTAG configuration. The board must be powered on and be connected to the PC."); - $mtable->attach($auto,5,6,9,10,'shrink','shrink',2,2); - $auto-> signal_connect("clicked" => sub{ - my $pid; - my $hw; - - my $project_dir = get_project_dir(); - my $command= "$project_dir/mpsoc/src_c/jtag/jtag_libusb/list_usb_dev"; - add_info($tview,"$command\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); - if(length $stderr>1){ - add_colored_info($tview,"$stderr\n",'red'); - add_colored_info($tview,"$command was not run successfully!\n",'red'); - }else { - - if($exit){ - add_colored_info($tview,"$stdout\n",'red'); - add_colored_info($tview,"$command was not run successfully!\n",'red'); - }else{ - add_info($tview,"$stdout\n"); - my @a=split /vid=9fb/, $stdout; - if(defined $a[1]){ - my @b=split /pid=/, $a[1]; - my @c=split /\n/, $b[1]; - $pid=$c[0]; - $self->object_add_attribute('compile','quartus_pid',$pid); - add_colored_info($tview,"Detected PID: $pid\n",'blue'); - - }else{ - add_colored_info($tview,"The Altera vendor ID of 9fb is not detected. Make sure You have connected your Altera board to your USB port\n",'red'); - return; - } - } - } - - - $command= "$ENV{QUARTUS_BIN}/jtagconfig"; - add_info($tview,"$command\n"); - ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); - if(length $stderr>1){ - add_colored_info($tview,"$stderr\n",'red'); - add_colored_info($tview,"$command was not run successfully!\n",'red'); - }else { - - if($exit){ - add_colored_info($tview,"$stdout\n",'red'); - add_colored_info($tview,"$command was not run successfully!\n",'red'); - }else{ - add_info($tview,"$stdout\n"); - my @a=split /1\)\s+/, $stdout; - if(defined $a[1]){ - my @b=split /\s+/, $a[1]; - $hw=$b[0]; - $self->object_add_attribute('compile','quartus_hardware',$hw); - add_colored_info($tview,"Detected Hardware: $hw\n",'blue'); - my $qsf=$self->object_get_attribute('compile','board_confg_file'); - if(!defined $qsf ){ - add_colored_info ($tview,"Cannot detect device location in JTAG chin. Please enter the QSF file or fill in manually \n",'red'); - - }else{ - #search for device name in qsf file - $qsf=add_project_dir_to_addr($qsf); - if (!(-f $qsf)){ - add_colored_info($tview, "Error Could not find $qsf file!\n"); - return; - } - my $str=load_file($qsf); - my $dw= capture_string_between(' DEVICE ',$str,"\n"); - if(defined $dw){ - add_colored_info($tview,"Device name in qsf file is: $dw\n",'blue'); - @b=split /\n/, $a[1]; - - #capture device name in JTAG chain - my @f=(0); - foreach my $c (@b){ - my @e=split /\s+/, $c; - push(@f,$e[2]) if(defined $e[2]); - } - - my $pos=find_the_most_similar_position($dw ,@f); - $self->object_add_attribute('compile','quartus_device',$pos); - add_colored_info($tview,"$dw has the most similarity with $f[$pos] in JTAG chain\n",'blue'); - - - }else{ - add_colored_info ($tview, "Could not find device name in the $qsf file!\n"); - } - - } - - - }else{ - #add_colored_info($tview,"The Altera vendor ID of 9fb is not detected. Make sure You have connected your Altera board to your USB port\n",'red'); - - } - - } - } - $widgets->destroy(); - $widgets= add_new_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor); - $v1-> pack1($widgets, TRUE, TRUE); - #$table->attach_defaults($widgets,0,3,0,1); - $table->show_all(); - # my $cmd=" $ENV{'QUARTUS_BIN'}" - - }); - - - } - - - - - $window->add ($mtable); - $window->show_all(); - + my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_; + my $window = def_popwin_size(50,80,"Add New $vendor FPGA Board",'percent'); + my $table = def_table(2, 2, FALSE); + my $scrolled_win=add_widget_to_scrolled_win($table); + my $mtable = def_table(10, 10, FALSE); + my $next=def_image_button('icons/plus.png','Add'); + my $back=def_image_button('icons/left.png','Previous'); + $mtable->attach_defaults($scrolled_win,0,10,0,9); + $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2) if (defined $name); + $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2); + my ($Twin,$tview)=create_txview(); + my $widgets= + ($vendor eq 'Altera')? add_new_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor): + add_new_xilinx_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor,$tview); + my $v1=gen_vpaned($widgets,0.3,$Twin); + $table->attach_defaults($v1,0,3,0,2); + #$table->attach_defaults( $Twin,0,3,1,2); + $back-> signal_connect("clicked" => sub{ + $window->destroy; + select_compiler($self,$name,$top,$target_dir,$end_func); + }); + $next-> signal_connect("clicked" => sub{ + my $result = ($vendor eq 'Altera')? + add_new_altera_fpga_board_files($self,$vendor): + add_new_xilinx_fpga_board_files($self,$vendor); + + if(! defined $result ){ + select_compiler($self,$name,$top,$target_dir,$end_func) if (defined $name); + $window->destroy; + message_dialog("The new board has been added successfully!"); + }else { + show_info($tview," "); + show_colored_info($tview,$result,'red'); + } + }); + + if($vendor eq 'Altera'){ + my $auto=def_image_button('icons/advance.png','Auto-fill'); + set_tip($auto, "Auto-fill JTAG configuration. The board must be powered on and be connected to the PC."); + $mtable->attach($auto,5,6,9,10,'shrink','shrink',2,2); + $auto-> signal_connect("clicked" => sub{ + my $pid; + my $hw; + my $project_dir = get_project_dir(); + my $command= "$project_dir/mpsoc/src_c/jtag/jtag_libusb/list_usb_dev"; + add_info($tview,"$command\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); + if(length $stderr>1){ + add_colored_info($tview,"$stderr\n",'red'); + add_colored_info($tview,"$command was not run successfully!\n",'red'); + }else { + if($exit){ + add_colored_info($tview,"$stdout\n",'red'); + add_colored_info($tview,"$command was not run successfully!\n",'red'); + }else{ + add_info($tview,"$stdout\n"); + my @a=split /vid=9fb/, $stdout; + if(defined $a[1]){ + my @b=split /pid=/, $a[1]; + my @c=split /\n/, $b[1]; + $pid=$c[0]; + $self->object_add_attribute('compile','quartus_pid',$pid); + add_colored_info($tview,"Detected PID: $pid\n",'blue'); + }else{ + add_colored_info($tview,"The Altera vendor ID of 9fb is not detected. Make sure You have connected your Altera board to your USB port\n",'red'); + return; + } + } + } + $command= "$ENV{QUARTUS_BIN}/jtagconfig"; + add_info($tview,"$command\n"); + ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); + if(length $stderr>1){ + add_colored_info($tview,"$stderr\n",'red'); + add_colored_info($tview,"$command was not run successfully!\n",'red'); + }else { + if($exit){ + add_colored_info($tview,"$stdout\n",'red'); + add_colored_info($tview,"$command was not run successfully!\n",'red'); + }else{ + add_info($tview,"$stdout\n"); + my @a=split /1\)\s+/, $stdout; + if(defined $a[1]){ + my @b=split /\s+/, $a[1]; + $hw=$b[0]; + $self->object_add_attribute('compile','quartus_hardware',$hw); + add_colored_info($tview,"Detected Hardware: $hw\n",'blue'); + my $qsf=$self->object_get_attribute('compile','board_confg_file'); + if(!defined $qsf ){ + add_colored_info ($tview,"Cannot detect device location in JTAG chin. Please enter the QSF file or fill in manually \n",'red'); + + }else{ + #search for device name in qsf file + $qsf=add_project_dir_to_addr($qsf); + if (!(-f $qsf)){ + add_colored_info($tview, "Error Could not find $qsf file!\n"); + return; + } + my $str=load_file($qsf); + my $dw= capture_string_between(' DEVICE ',$str,"\n"); + if(defined $dw){ + add_colored_info($tview,"Device name in qsf file is: $dw\n",'blue'); + @b=split /\n/, $a[1]; + + #capture device name in JTAG chain + my @f=(0); + foreach my $c (@b){ + my @e=split /\s+/, $c; + push(@f,$e[2]) if(defined $e[2]); + } + my $pos=find_the_most_similar_position($dw ,@f); + $self->object_add_attribute('compile','quartus_device',$pos); + add_colored_info($tview,"$dw has the most similarity with $f[$pos] in JTAG chain\n",'blue'); + }else{ + add_colored_info ($tview, "Could not find device name in the $qsf file!\n"); + } + } + }else{ + #add_colored_info($tview,"The Altera vendor ID of 9fb is not detected. Make sure You have connected your Altera board to your USB port\n",'red'); + } + } + } + $widgets->destroy(); + $widgets= add_new_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor); + $v1-> pack1($widgets, TRUE, TRUE); + #$table->attach_defaults($widgets,0,3,0,1); + $table->show_all(); + #my $cmd=" $ENV{'QUARTUS_BIN'}" + }); + } + $window->add ($mtable); + $window->show_all(); } - - sub add_new_xilinx_fpga_board_widgets{ - my ($self,$name,$top,$target_dir,$end_func,$vendor,$tview)=@_; - my $table = def_table(2, 2, FALSE); - - my $col=0; - my $row=0; - - my $help1="Your given FPGA Board name. Do not use any space in given name"; - my $help2="Path to FPGA board xdc file. In your Xilinx board installation CD or in the Internet, search for a xdc file containing your FPGA device pin assignment constrain)."; - my $help3="Path to FPGA_board_top.v file. A Verilog file containing all your FPGA device IO ports."; - my $help4="Your Board name (Board PART) e.g. digilentinc.com:arty-z7-20:part0:1.0"; - my $help5="Your FPGA device name (PART) e.g. xc7z020clg400-1 "; - my $help6="The order number of target device in jtag chain. Run jtag targets after \"connect\" command in xsct terminal to list all available targets."; - my $help7="Path to Vivado board files repository. E.g download the repo from https://github.com/Digilent/vivado-boards and save in \$ProNoC_work/toolchain/board_files folder."; - my $help8="Hardware device name e.g. xc7z020_1. To find it you can connect your FPGA board to your PC. In tcl terminal run - open_hw - connect_hw_server - open_hw_target - get_hw_devices -It supposed to show the list of your hardware devices in your FPGA. Select the name represent your FPGA device - "; - - - my $repo ="$ENV{PRONOC_WORK}/toolchain/board_files"; - - - $row++; - - my @info = ( - { label=>"FPGA board display name:", param_name=>'fpga_board', type=>"Entry", default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef}, - { label=>"Set board repo:", param_name=>'fpga_board_repo', type=>"DIR_path", default_val=>"$repo", content=>undef, info=>$help7, param_parent=>'compile',ref_delay=>undef}, - { label=>"FPGA board part name:", param_name=>'fpga_board_part', type=>"EntryCombo",default_val=>undef, content=>undef, info =>$help4, param_parent=>'compile', ref_delay=> undef}, - { label=>"FPGA part name:", param_name=>'fpga_part', type=>"Entry", default_val=>undef, content=>undef, info=>$help5, param_parent=>'compile', ref_delay=> undef}, + my ($self,$name,$top,$target_dir,$end_func,$vendor,$tview)=@_; + my $table = def_table(2, 2, FALSE); + my $col=0; + my $row=0; + my $help1="Your given FPGA Board name. Do not use any space in given name"; + my $help2="Path to FPGA board xdc file. In your Xilinx board installation CD or in the Internet, search for a xdc file containing your FPGA device pin assignment constrain)."; + my $help3="Path to FPGA_board_top.v file. A Verilog file containing all your FPGA device IO ports."; + my $help4="Your Board name (Board PART) e.g. digilentinc.com:arty-z7-20:part0:1.0"; + my $help5="Your FPGA device name (PART) e.g. xc7z020clg400-1 "; + my $help6="The order number of target device in jtag chain. Run jtag targets after \"connect\" command in xsct terminal to list all available targets."; + my $help7="Path to Vivado board files repository. E.g download the repo from https://github.com/Digilent/vivado-boards and save in \$ProNoC_work/toolchain/board_files folder."; + my $help8="Hardware device name e.g. xc7z020_1. To find it you can connect your FPGA board to your PC. In tcl terminal run + open_hw + connect_hw_server + open_hw_target + get_hw_devices +It supposed to show the list of your hardware devices in your FPGA. Select the name represent your FPGA device + "; + my $repo ="$ENV{PRONOC_WORK}/toolchain/board_files"; + $row++; + my @info = ( + { label=>"FPGA board display name:", param_name=>'fpga_board', type=>"Entry", default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef}, + { label=>"Set board repo:", param_name=>'fpga_board_repo', type=>"DIR_path", default_val=>"$repo", content=>undef, info=>$help7, param_parent=>'compile',ref_delay=>undef}, + { label=>"FPGA board part name:", param_name=>'fpga_board_part', type=>"EntryCombo",default_val=>undef, content=>undef, info =>$help4, param_parent=>'compile', ref_delay=> undef}, + { label=>"FPGA part name:", param_name=>'fpga_part', type=>"Entry", default_val=>undef, content=>undef, info=>$help5, param_parent=>'compile', ref_delay=> undef}, { label=>"FPGA Hardware device name:", param_name=>'fpga_hw_device', type=>"EntryCombo", default_val=>undef, content=>undef, info=>$help8, param_parent=>'compile', ref_delay=> undef}, - { label=>"Target device JTAG chain order number", param_name=>'fpga_board_order', type=>"Spin-button", default_val=>1, content=>"0,256,1", info=>$help6, param_parent=>'compile',ref_delay=>undef}, - { label=>'FPGA board xdc file:', param_name=>'board_confg_file', type=>"FILE_path", default_val=>undef, content=>"xdc", info=>$help2, param_parent=>'compile', ref_delay=>undef}, - { label=>"FPGA board golden top Verilog file", param_name=>'fpga_board_v', type=>"FILE_path", default_val=>undef, content=>"v", info=>$help3, param_parent=>'compile',ref_delay=>undef}, - ); - my %widgets; - my %rows; - foreach my $d (@info) { - $rows{$d->{param_name}} =$row; - ($row,$col,$widgets{$d->{param_name}})=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,'vertical'); - } - - my $icon = 'icons/advance.png'; - my $search=def_image_button($icon,undef); - my $search_board=def_image_button ($icon,undef); - my $search_dev=def_image_button ($icon,undef); - my $search_chain=def_image_button ($icon,undef); - - $table->attach($search,4,5,$rows{'fpga_board_part'},$rows{'fpga_board_part'}+1,'fill','shrink',2,2); - $table->attach($search_board,4,5,$rows{'fpga_part'},$rows{'fpga_part'}+1,'fill','shrink',2,2); - $table->attach($search_dev,4,5,$rows{'fpga_hw_device'},$rows{'fpga_hw_device'}+1,'fill','shrink',2,2); - $table->attach($search_chain,4,5,$rows{'fpga_board_order'},$rows{'fpga_board_order'}+1,'fill','shrink',2,2); - - - $search->signal_connect("clicked" => sub{ - my $load= show_gif("icons/load.gif"); - $table->attach ($load,5, 6, $rows{'fpga_board_part'},$rows{'fpga_board_part'}+ 1,'shrink','shrink',0,0); - $table->show_all; - my $result= set_xilinx_board_from_repo($self,$tview); - update_combo_entry_content($widgets{'fpga_board_part'}, $result); - $load->destroy; - $table->show_all; - }); - - - $search_board->signal_connect("clicked" => sub{ - my $load= show_gif("icons/load.gif"); - $table->attach ($load,5, 6, $rows{'fpga_part'},$rows{'fpga_part'}+1, 'shrink','shrink',0,0); - $table->show_all; - my $result= get_xilinx_board_part($self,$tview); - $widgets{'fpga_part'}->set_text($result); - #print "result = $result\n"; - $load->destroy; - $table->show_all; - }); - $search_dev->signal_connect("clicked" => sub{ - my $load= show_gif("icons/load.gif"); - $table->attach ($load,5, 6, $rows{'fpga_hw_device'},$rows{'fpga_hw_device'}+ 1,'shrink','shrink',0,0); - $table->show_all; - my $result= get_xilinx_device_names($self,$tview); - update_combo_entry_content($widgets{'fpga_hw_device'}, $result); - $load->destroy; - $table->show_all; - }); - $search_chain->signal_connect("clicked" => sub{ - my $targets = show_all_xilinx_targets($self,$tview); - if(!defined $targets){ - add_info($tview,"Unable to find the FPGA board target list. Make sure you have connected your FPGA board to your PC first and it is powered on.\n"); - return; - } - - my @lines=split(/\r?\n/,$targets); - my @list1; - my @list2; - foreach my $p (@lines){ - $p =~ s/^\s+//;#left trim - my @words=split(/\s+/,$p); - push (@list1,$words[0]); - push (@list2,$words[1]); - } - my $hw = $self->object_get_attribute('compile','fpga_hw_device'); - if( !defined $hw){ - add_colored_info($tview,"Please define the FPGA hardware device name first!\n",'red'); - return; - } - my $pos = find_the_most_similar_position ($hw ,@list2); - add_info($tview,"$hw matched with target $list1[$pos] $list2[$pos] "); - $widgets{'fpga_board_order'}->set_value($list1[$pos]); - }); - - return ($row, $col, $table); + { label=>"Target device JTAG chain order number", param_name=>'fpga_board_order', type=>"Spin-button", default_val=>1, content=>"0,256,1", info=>$help6, param_parent=>'compile',ref_delay=>undef}, + { label=>'FPGA board xdc file:', param_name=>'board_confg_file', type=>"FILE_path", default_val=>undef, content=>"xdc", info=>$help2, param_parent=>'compile', ref_delay=>undef}, + { label=>"FPGA board golden top Verilog file", param_name=>'fpga_board_v', type=>"FILE_path", default_val=>undef, content=>"v", info=>$help3, param_parent=>'compile',ref_delay=>undef}, + ); + my %widgets; + my %rows; + foreach my $d (@info) { + $rows{$d->{param_name}} =$row; + ($row,$col,$widgets{$d->{param_name}})=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,'vertical'); + } + my $icon = 'icons/advance.png'; + my $search=def_image_button($icon,undef); + my $search_board=def_image_button ($icon,undef); + my $search_dev=def_image_button ($icon,undef); + my $search_chain=def_image_button ($icon,undef); + + $table->attach($search,4,5,$rows{'fpga_board_part'},$rows{'fpga_board_part'}+1,'fill','shrink',2,2); + $table->attach($search_board,4,5,$rows{'fpga_part'},$rows{'fpga_part'}+1,'fill','shrink',2,2); + $table->attach($search_dev,4,5,$rows{'fpga_hw_device'},$rows{'fpga_hw_device'}+1,'fill','shrink',2,2); + $table->attach($search_chain,4,5,$rows{'fpga_board_order'},$rows{'fpga_board_order'}+1,'fill','shrink',2,2); + $search->signal_connect("clicked" => sub{ + my $load= show_gif("icons/load.gif"); + $table->attach ($load,5, 6, $rows{'fpga_board_part'},$rows{'fpga_board_part'}+ 1,'shrink','shrink',0,0); + $table->show_all; + my $result= set_xilinx_board_from_repo($self,$tview); + update_combo_entry_content($widgets{'fpga_board_part'}, $result); + $load->destroy; + $table->show_all; + }); + $search_board->signal_connect("clicked" => sub{ + my $load= show_gif("icons/load.gif"); + $table->attach ($load,5, 6, $rows{'fpga_part'},$rows{'fpga_part'}+1, 'shrink','shrink',0,0); + $table->show_all; + my $result= get_xilinx_board_part($self,$tview); + $widgets{'fpga_part'}->set_text($result); + #print "result = $result\n"; + $load->destroy; + $table->show_all; + }); + $search_dev->signal_connect("clicked" => sub{ + my $load= show_gif("icons/load.gif"); + $table->attach ($load,5, 6, $rows{'fpga_hw_device'},$rows{'fpga_hw_device'}+ 1,'shrink','shrink',0,0); + $table->show_all; + my $result= get_xilinx_device_names($self,$tview); + update_combo_entry_content($widgets{'fpga_hw_device'}, $result); + $load->destroy; + $table->show_all; + }); + $search_chain->signal_connect("clicked" => sub{ + my $targets = show_all_xilinx_targets($self,$tview); + if(!defined $targets){ + add_info($tview,"Unable to find the FPGA board target list. Make sure you have connected your FPGA board to your PC first and it is powered on.\n"); + return; + } + + my @lines=split(/\r?\n/,$targets); + my @list1; + my @list2; + foreach my $p (@lines){ + $p =~ s/^\s+//;#left trim + my @words=split(/\s+/,$p); + push (@list1,$words[0]); + push (@list2,$words[1]); + } + my $hw = $self->object_get_attribute('compile','fpga_hw_device'); + if( !defined $hw){ + add_colored_info($tview,"Please define the FPGA hardware device name first!\n",'red'); + return; + } + my $pos = find_the_most_similar_position ($hw ,@list2); + add_info($tview,"$hw matched with target $list1[$pos] $list2[$pos] "); + $widgets{'fpga_board_order'}->set_value($list1[$pos]); + }); + return ($row, $col, $table); } - - sub set_xilinx_board_from_repo{ - my ($self,$tview)=@_; - my $bin = $self->object_get_attribute('compile',"vivado bin"); - my $vivado =(defined $bin)? "${bin}/vivado" : "vivado"; - my $result; - my $repo= $self->object_get_attribute('compile','fpga_board_repo'); - my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_boards.tcl -tclargs $repo"; - my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl"; - - add_info($tview,"$command\n"); - my $stdout=run_cmd_textview_errors($command,$tview); - return if (!defined $stdout); - add_info($tview,"$stdout\n"); - my @boards=split(/\s+/,$stdout); - my $r=0; - foreach my $board (@boards){ - my @pp=split(':',$board); - if(scalar @pp == 4 && $pp[1] =~ /[a-zA-Z]+/) { - $r=1; - $result= (!defined $result)? "$board" : $result.",$board"; - } - } - add_colored_info($tview,"$stdout\n",'red') if($r==0); - return $result; -} - + my ($self,$tview)=@_; + my $bin = $self->object_get_attribute('compile',"vivado bin"); + my $vivado =(defined $bin)? "${bin}/vivado" : "vivado"; + my $result; + my $repo= $self->object_get_attribute('compile','fpga_board_repo'); + my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_boards.tcl -tclargs $repo"; + my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl"; + add_info($tview,"$command\n"); + my $stdout=run_cmd_textview_errors($command,$tview); + return if (!defined $stdout); + add_info($tview,"$stdout\n"); + my @boards=split(/\s+/,$stdout); + my $r=0; + foreach my $board (@boards){ + my @pp=split(':',$board); + if(scalar @pp == 4 && $pp[1] =~ /[a-zA-Z]+/) { + $r=1; + $result= (!defined $result)? "$board" : $result.",$board"; + } + } + add_colored_info($tview,"$stdout\n",'red') if($r==0); + return $result; +} sub get_xilinx_device_names{ - my ($self,$tview)=@_; - my $bin = $self->object_get_attribute('compile',"vivado bin"); - my $vivado =(defined $bin)? "${bin}/vivado" : "vivado"; - my $result; - my $repo= $self->object_get_attribute('compile','fpga_board_repo'); - my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_hw_device.tcl -tclargs"; - my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl"; - - add_info($tview,"$command\n"); - my $stdout=run_cmd_textview_errors($command,$tview); - if (!defined $stdout){ - add_info($tview,"Unable to find the FPGA board devices list. Make sure you have connected your FPGA board to your PC first and it is powered on.\n"); - return; - } - add_info($tview,"$stdout\n"); - my $devices = capture_string_between ('\n\*RESULT:',$stdout,"\n"); - my @D=split(/\s+/,$devices); - return join ',', @D; -} - - - + my ($self,$tview)=@_; + my $bin = $self->object_get_attribute('compile',"vivado bin"); + my $vivado =(defined $bin)? "${bin}/vivado" : "vivado"; + my $result; + my $repo= $self->object_get_attribute('compile','fpga_board_repo'); + my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_hw_device.tcl -tclargs"; + my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl"; + add_info($tview,"$command\n"); + my $stdout=run_cmd_textview_errors($command,$tview); + if (!defined $stdout){ + add_info($tview,"Unable to find the FPGA board devices list. Make sure you have connected your FPGA board to your PC first and it is powered on.\n"); + return; + } + add_info($tview,"$stdout\n"); + my $devices = capture_string_between ('\n\*RESULT:',$stdout,"\n"); + my @D=split(/\s+/,$devices); + return join ',', @D; +} +sub get_xilinx_board_part{ + my ($self,$tview)=@_; + my $bin = $self->object_get_attribute('compile',"vivado bin"); + my $vivado =(defined $bin)? "${bin}/vivado" : "vivado"; + my $result; + my $repo= $self->object_get_attribute('compile','fpga_board_repo'); + my $board_part= $self->object_get_attribute('compile' ,'fpga_board_part'); + if (!defined $board_part ){ + add_colored_info($tview,"Please define the FPGA board part name first!\n",'red'); + return; + } + my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_part.tcl -tclargs $board_part $repo "; + my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl"; + add_info($tview,"$command\n"); + my $stdout=run_cmd_textview_errors($command,$tview); + return if (!defined $stdout); + add_info($tview,"$stdout\n"); + return capture_string_between ('\n\*RESULT:',$stdout,"\n"); +} -sub get_xilinx_board_part{ - my ($self,$tview)=@_; - my $bin = $self->object_get_attribute('compile',"vivado bin"); - my $vivado =(defined $bin)? "${bin}/vivado" : "vivado"; - my $result; - my $repo= $self->object_get_attribute('compile','fpga_board_repo'); - my $board_part= $self->object_get_attribute('compile' ,'fpga_board_part'); - if (!defined $board_part ){ - add_colored_info($tview,"Please define the FPGA board part name first!\n",'red'); - return; - } - - my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_part.tcl -tclargs $board_part $repo "; - - - my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl"; - - add_info($tview,"$command\n"); - my $stdout=run_cmd_textview_errors($command,$tview); - return if (!defined $stdout); - add_info($tview,"$stdout\n"); - return capture_string_between ('\n\*RESULT:',$stdout,"\n"); -} - - - sub add_new_altera_fpga_board_widgets{ - my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_; - my $table = def_table(2, 2, FALSE); - - my $help1="FPGA Board name. Do not use any space in given name"; - my $help2="Path to FPGA board qsf file. In your Altra board installation CD or in the Internet search for a QSF file containing your FPGA device name with other necessary global project setting including the pin assignments (e.g DE10_Nano_golden_top.qsf)."; - my $help3="Path to FPGA_board_top.v file. In your Altra board installation CD or in the Internet search for a Verilog file containing all your FPGA device IO ports (e.g DE10_Nano_golden_top.v)."; - my $help4="FPGA Board USB-Blaster product ID (PID). Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find PID. Optionally you can run mpsoc/ + my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_; + my $table = def_table(2, 2, FALSE); + my $help1="FPGA Board name. Do not use any space in given name"; + my $help2="Path to FPGA board qsf file. In your Altra board installation CD or in the Internet search for a QSF file containing your FPGA device name with other necessary global project setting including the pin assignments (e.g DE10_Nano_golden_top.qsf)."; + my $help3="Path to FPGA_board_top.v file. In your Altra board installation CD or in the Internet search for a Verilog file containing all your FPGA device IO ports (e.g DE10_Nano_golden_top.v)."; + my $help4="FPGA Board USB-Blaster product ID (PID). Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find PID. Optionally you can run mpsoc/ src_c/jtag/jtag_libusb/list_usb_dev to find your USB-Blaster PID. Search for PID of a device having 9fb (altera) Vendor ID (VID)"; - my $help5="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your hardware name. Optionally you can run \$QUARTUS_BIN/jtagconfig to find your programming hardware name. + my $help5="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your hardware name. Optionally you can run \$QUARTUS_BIN/jtagconfig to find your programming hardware name. an example of output from the 'jtagconfig' command: \t 1) ByteBlasterMV on LPT1 \t 090010DD EPXA10 @@ -819,219 +647,173 @@ sub add_new_altera_fpga_board_widgets{ \t 48A00477 SOCVHP5 \t 02D020DC 5CS(EBA6ES|XFC6c6ES) ByteBlasterMV \& DE-SoC are the programming hardware name."; -my $help6="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your device location in jtag chain. Optionally you can run \$QUARTUS_BIN/jtagconfig to find your target device location in jtag chain."; - - - - - my @info = ( - { label=>"FPGA Board Name:", param_name=>'fpga_board', type=>"Entry", default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef}, - { label=>'FPGA Board Golden top QSF file:', param_name=>'board_confg_file', type=>"FILE_path", default_val=>undef, content=>"qsf", info=>$help2, param_parent=>'compile', ref_delay=>undef}, - { label=>"FPGA Board Golden top Verilog file", param_name=>'fpga_board_v', type=>"FILE_path", default_val=>undef, content=>"v", info=>$help3, param_parent=>'compile',ref_delay=>undef }, - ); - - my @usb = ( - { label=>"FPGA Board USB Blaster PID:", param_name=>'quartus_pid', type=>"Entry", default_val=>undef, content=>undef, info=>$help4, param_parent=>'compile', ref_delay=> undef}, - { label=>"FPGA Board Programming Hardware Name:", param_name=>'quartus_hardware', type=>"Entry", default_val=>undef, content=>undef, info=>$help5, param_parent=>'compile', ref_delay=> undef}, - { label=>"FPGA Board Device location in JTAG chain:", param_name=>'quartus_device', type=>"Spin-button", default_val=>0, content=>"0,100,1", info=>$help6, param_parent=>'compile', ref_delay=> undef}, - ); - - - my $col=0; - my $row=0; - foreach my $d (@info) { - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical"); - } - - my $labl=def_pack_vbox(FALSE, 0,(gen_Hsep(),gen_label_in_center("FPGA Board JTAG Configuration"),gen_Hsep())); - - $table->attach( $labl,0,3,$row,$row+1,'fill','shrink',2,2); $row++; $col=0; - - foreach my $d (@usb) { - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical"); - } - - - return ($row, $col, $table); + my $help6="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your device location in jtag chain. Optionally you can run \$QUARTUS_BIN/jtagconfig to find your target device location in jtag chain."; + my @info = ( + { label=>"FPGA Board Name:", param_name=>'fpga_board', type=>"Entry", default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef}, + { label=>'FPGA Board Golden top QSF file:', param_name=>'board_confg_file', type=>"FILE_path", default_val=>undef, content=>"qsf", info=>$help2, param_parent=>'compile', ref_delay=>undef}, + { label=>"FPGA Board Golden top Verilog file", param_name=>'fpga_board_v', type=>"FILE_path", default_val=>undef, content=>"v", info=>$help3, param_parent=>'compile',ref_delay=>undef }, + ); + my @usb = ( + { label=>"FPGA Board USB Blaster PID:", param_name=>'quartus_pid', type=>"Entry", default_val=>undef, content=>undef, info=>$help4, param_parent=>'compile', ref_delay=> undef}, + { label=>"FPGA Board Programming Hardware Name:", param_name=>'quartus_hardware', type=>"Entry", default_val=>undef, content=>undef, info=>$help5, param_parent=>'compile', ref_delay=> undef}, + { label=>"FPGA Board Device location in JTAG chain:", param_name=>'quartus_device', type=>"Spin-button", default_val=>0, content=>"0,100,1", info=>$help6, param_parent=>'compile', ref_delay=> undef}, + ); + my $col=0; + my $row=0; + foreach my $d (@info) { + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical"); + } + my $labl=def_pack_vbox(FALSE, 0,(gen_Hsep(),gen_label_in_center("FPGA Board JTAG Configuration"),gen_Hsep())); + $table->attach( $labl,0,3,$row,$row+1,'fill','shrink',2,2); $row++; $col=0; + foreach my $d (@usb) { + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical"); + } + return ($row, $col, $table); } - sub add_new_xilinx_fpga_board_files{ - my ($self,$vendor)=@_; - #check the board name - my $board_name=$self->object_get_attribute('compile','fpga_board'); - return "Please define the Board Name\n" if(! defined $board_name ); - return "Please define the Board Name\n" if(length($board_name) ==0 ); - my $r=check_verilog_identifier_syntax($board_name); - return "Error in given Board Name: $r\n" if(defined $r ); - - #check xdc file - my $xdc=$self->object_get_attribute('compile','board_confg_file'); - return "Please define the xdc file\n" if(!defined $xdc ); - $xdc=add_project_dir_to_addr($xdc); - - #check v file - my $top=$self->object_get_attribute('compile','fpga_board_v'); - return "Please define the verilog file file\n" if(!defined $top ); - $top=add_project_dir_to_addr($top); - - #check board part - my $part=$self->object_get_attribute('compile','fpga_part'); - my $board_part=$self->object_get_attribute('compile','fpga_board_part'); - return "Please define at least one of FPGA board part or FPGA part names"if(!defined $part && !defined $board_part ); - - #make board directory - my $project_dir = get_project_dir(); - my $path="$project_dir/mpsoc/boards/$vendor/$board_name"; - mkpath($path,1,01777); - return "Error cannot make $path path" if ((-d $path)==0); - copy( $xdc,"$path/$board_name.xdc"); - copy($top,"$path/$board_name.v"); - - - - my $a=$self->object_get_attribute('compile','fpga_board_order'); - my $jtag_intfc="#!/bin/bash + my ($self,$vendor)=@_; + #check the board name + my $board_name=$self->object_get_attribute('compile','fpga_board'); + return "Please define the Board Name\n" if(! defined $board_name ); + return "Please define the Board Name\n" if(length($board_name) ==0 ); + my $r=check_verilog_identifier_syntax($board_name); + return "Error in given Board Name: $r\n" if(defined $r ); + #check xdc file + my $xdc=$self->object_get_attribute('compile','board_confg_file'); + return "Please define the xdc file\n" if(!defined $xdc ); + $xdc=add_project_dir_to_addr($xdc); + #check v file + my $top=$self->object_get_attribute('compile','fpga_board_v'); + return "Please define the verilog file file\n" if(!defined $top ); + $top=add_project_dir_to_addr($top); + #check board part + my $part=$self->object_get_attribute('compile','fpga_part'); + my $board_part=$self->object_get_attribute('compile','fpga_board_part'); + return "Please define at least one of FPGA board part or FPGA part names"if(!defined $part && !defined $board_part ); + #make board directory + my $project_dir = get_project_dir(); + my $path="$project_dir/mpsoc/boards/$vendor/$board_name"; + mkpath($path,1,01777); + return "Error cannot make $path path" if ((-d $path)==0); + copy( $xdc,"$path/$board_name.xdc"); + copy($top,"$path/$board_name.v"); + my $a=$self->object_get_attribute('compile','fpga_board_order'); + my $jtag_intfc="#!/bin/bash JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_xilinx_xsct -a $a -b 36\" #it works only for 32-bit jtag data width for 64 pass -b 68 "; - save_file ("$path/jtag_intfc.sh",$jtag_intfc); - - - my $bin = $self->object_get_attribute('compile',"vivado bin"); + save_file ("$path/jtag_intfc.sh",$jtag_intfc); + my $bin = $self->object_get_attribute('compile',"vivado bin"); my $hw_dev=$self->object_get_attribute('compile',"fpga_hw_device"); my $repo= $self->object_get_attribute('compile','fpga_board_repo'); - - - my $tcl="proc set_project_properties { } {\n"; - if(-d $repo){ - $tcl=$tcl."\tset_property \"board_part_repo_paths\" [list \"$repo\"] [current_project]\n"; - }else { - $tcl=$tcl."\tset_property \"board_part_repo_paths\" [get_property LOCAL_ROOT_DIR [xhub::get_xstores xilinx_board_store]] [current_project]\n" if(defined $board_part); - } - $tcl=$tcl."\tset_property \"part\" \"$part\" [current_project]\n" if(defined $part); - $tcl=$tcl."\tset_property \"board_part\" \"$board_part\" [current_project]\n" if(defined $board_part); - $tcl=$tcl."\tset_property \"default_lib\" \"xil_defaultlib\" [current_project]\n}\n"; - - - - if (defined $hw_dev){ -$tcl=$tcl."\n + my $tcl="proc set_project_properties { } {\n"; + if(-d $repo){ + $tcl=$tcl."\tset_property \"board_part_repo_paths\" [list \"$repo\"] [current_project]\n"; + }else { + $tcl=$tcl."\tset_property \"board_part_repo_paths\" [get_property LOCAL_ROOT_DIR [xhub::get_xstores xilinx_board_store]] [current_project]\n" if(defined $board_part); + } + $tcl=$tcl."\tset_property \"part\" \"$part\" [current_project]\n" if(defined $part); + $tcl=$tcl."\tset_property \"board_part\" \"$board_part\" [current_project]\n" if(defined $board_part); + $tcl=$tcl."\tset_property \"default_lib\" \"xil_defaultlib\" [current_project]\n}\n"; + if (defined $hw_dev){ +$tcl=$tcl."\n proc program_board {bit_file} { - open_hw - connect_hw_server - open_hw_target - set_property PROGRAM.FILE \$bit_file [get_hw_devices $hw_dev] - program_hw_devices [get_hw_devices $hw_dev] - refresh_hw_device [get_hw_devices $hw_dev] + open_hw + connect_hw_server + open_hw_target + set_property PROGRAM.FILE \$bit_file [get_hw_devices $hw_dev] + program_hw_devices [get_hw_devices $hw_dev] + refresh_hw_device [get_hw_devices $hw_dev] } -"; - } - save_file ("$path/board_property.tcl",$tcl); - - - $self->object_add_attribute('compile','board',$board_name); - return undef; - - +"; + } + save_file ("$path/board_property.tcl",$tcl); + $self->object_add_attribute('compile','board',$board_name); + return undef; } - sub add_new_altera_fpga_board_files{ - my ($self,$vendor)=@_; - - #check the board name - my $board_name=$self->object_get_attribute('compile','fpga_board'); - return "Please define the Board Name\n" if(! defined $board_name ); - return "Please define the Board Name\n" if(length($board_name) ==0 ); - my $r=check_verilog_identifier_syntax($board_name); - return "Error in given Board Name: $r\n" if(defined $r ); - - #check qsf file - my $qsf=$self->object_get_attribute('compile','board_confg_file'); - return "Please define the QSF file\n" if(!defined $qsf ); - - #check v file - my $top=$self->object_get_attribute('compile','fpga_board_v'); - return "Please define the verilog file file\n" if(!defined $top ); - - #check PID - my $pid=$self->object_get_attribute('compile','quartus_pid'); - return "Please define the PID\n" if(! defined $pid ); - return "Please define the PID\n" if(length($pid) ==0 ); - - #check Hardware name - my $hw=$self->object_get_attribute('compile','quartus_hardware'); - return "Please define the Hardware Name\n" if(! defined $hw ); - return "Please define the Hardware Name\n" if(length($hw) ==0 ); - - - #check Device name name - my $dw=$self->object_get_attribute('compile','quartus_device'); - return "Please define targeted Device location in JTAG chain. The device location must be larger than zero.\n" if( $dw == 0 ); - - - - #make board directory - my $project_dir = get_project_dir(); - my $path="$project_dir/mpsoc/boards/$vendor/$board_name"; - mkpath($path,1,01777); - return "Error cannot make $path path" if ((-d $path)==0); - - #generate new qsf file - $qsf=add_project_dir_to_addr($qsf); - $top=add_project_dir_to_addr($top); - open my $file, "<", $qsf or return "Error Could not open $qsf file in read mode!"; - open my $newqsf, ">", "$path/$board_name.qsf" or return "Error Could not create $path/$board_name.qsf file in write mode!"; - - #remove the lines contain following strings - my @p=("TOP_LEVEL_ENTITY","VERILOG_FILE","SYSTEMVERILOG_FILE","VHDL_FILE","AHDL_FILE","PROJECT_OUTPUT_DIRECTORY" ); - while (my $line = <$file>){ - if ($line =~ /\Q$p[0]\E/ || $line =~ /\Q$p[1]\E/ || $line =~ /\Q$p[2]\E/ || $line =~ /\Q$p[3]\E/ || $line =~ /\Q$p[4]\E/){#dont copy the line contain TOP_LEVEL_ENTITY - - } - - else{ - print $newqsf $line; - } - - } - print $newqsf "\nset_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files\n"; - - close $newqsf; - close $file; - copy($top,"$path/$board_name.v"); - - #generate jtag_intfc.sh - open $file, ">", "$path/jtag_intfc.sh" or return "Error: Could not create $path/jtag_intfc.sh file in write mode!"; - my $jtag; - if($pid eq 6001 || $pid eq 6002 || $pid eq 6003){ - $jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_libusb -a \$PRODUCT_ID\""; - - }else{ - $jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_quartus_stp -a \$HARDWARE_NAME -b \$DEVICE_NAME\""; - - } - print $file "#!/bin/bash + my ($self,$vendor)=@_; + #check the board name + my $board_name=$self->object_get_attribute('compile','fpga_board'); + return "Please define the Board Name\n" if(! defined $board_name ); + return "Please define the Board Name\n" if(length($board_name) ==0 ); + my $r=check_verilog_identifier_syntax($board_name); + return "Error in given Board Name: $r\n" if(defined $r ); + #check qsf file + my $qsf=$self->object_get_attribute('compile','board_confg_file'); + return "Please define the QSF file\n" if(!defined $qsf ); + #check v file + my $top=$self->object_get_attribute('compile','fpga_board_v'); + return "Please define the verilog file file\n" if(!defined $top ); + #check PID + my $pid=$self->object_get_attribute('compile','quartus_pid'); + return "Please define the PID\n" if(! defined $pid ); + return "Please define the PID\n" if(length($pid) ==0 ); + #check Hardware name + my $hw=$self->object_get_attribute('compile','quartus_hardware'); + return "Please define the Hardware Name\n" if(! defined $hw ); + return "Please define the Hardware Name\n" if(length($hw) ==0 ); + #check Device name name + my $dw=$self->object_get_attribute('compile','quartus_device'); + return "Please define targeted Device location in JTAG chain. The device location must be larger than zero.\n" if( $dw == 0 ); + #make board directory + my $project_dir = get_project_dir(); + my $path="$project_dir/mpsoc/boards/$vendor/$board_name"; + mkpath($path,1,01777); + return "Error cannot make $path path" if ((-d $path)==0); + #generate new qsf file + $qsf=add_project_dir_to_addr($qsf); + $top=add_project_dir_to_addr($top); + open my $file, "<", $qsf or return "Error Could not open $qsf file in read mode!"; + open my $newqsf, ">", "$path/$board_name.qsf" or return "Error Could not create $path/$board_name.qsf file in write mode!"; + #remove the lines contain following strings + my @p=("TOP_LEVEL_ENTITY","VERILOG_FILE","SYSTEMVERILOG_FILE","VHDL_FILE","AHDL_FILE","PROJECT_OUTPUT_DIRECTORY" ); + while (my $line = <$file>){ + if ($line =~ /\Q$p[0]\E/ || $line =~ /\Q$p[1]\E/ || $line =~ /\Q$p[2]\E/ || $line =~ /\Q$p[3]\E/ || $line =~ /\Q$p[4]\E/){#dont copy the line contain TOP_LEVEL_ENTITY + + } + + else{ + print $newqsf $line; + } + + } + print $newqsf "\nset_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files\n"; + close $newqsf; + close $file; + copy($top,"$path/$board_name.v"); + #generate jtag_intfc.sh + open $file, ">", "$path/jtag_intfc.sh" or return "Error: Could not create $path/jtag_intfc.sh file in write mode!"; + my $jtag; + if($pid eq 6001 || $pid eq 6002 || $pid eq 6003){ + $jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_libusb -a \$PRODUCT_ID\""; + + }else{ + $jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_quartus_stp -a \$HARDWARE_NAME -b \$DEVICE_NAME\""; + + } + print $file "#!/bin/bash PRODUCT_ID=\"0x$pid\" HARDWARE_NAME=\'$hw *\' DEVICE_NAME=\"\@$dw*\" - + $jtag - - "; - close $file; - - - #generate program_device.sh - open $file, ">", "$path/program_device.sh" or return "Error: Could not create $path/program_device.sh file in write mode!"; - - -print $file "#!/bin/bash + + "; + close $file; + + + #generate program_device.sh + open $file, ">", "$path/program_device.sh" or return "Error: Could not create $path/program_device.sh file in write mode!"; + + + print $file "#!/bin/bash #usage: -# bash program_device.sh programming_file.sof +# bash program_device.sh programming_file.sof #programming file #given as an argument: \$1 @@ -1048,16 +830,15 @@ sub add_new_altera_fpga_board_files{ #programming command if [ -n "${QUARTUS_BIN+set}" ]; then - $QUARTUS_BIN/quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}" + $QUARTUS_BIN/quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}" else - quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}" + quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}" fi -'; - -close $file; -$self->object_add_attribute('compile','board',$board_name); - - return undef; +'; + + close $file; + $self->object_add_attribute('compile','board',$board_name); + return undef; } @@ -1065,271 +846,213 @@ sub add_new_altera_fpga_board_files{ sub get_pin_assignment{ - my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_; - my $window = def_popwin_size(80,80,"Step 2: Pin Assignment",'percent'); - - my $table = def_table(2, 2, FALSE); - my $scrolled_win = add_widget_to_scrolled_win($table); - - my $mtable = def_table(10, 10, FALSE); - my $next=def_image_button('icons/right.png','Next'); - my $back=def_image_button('icons/left.png','Previous'); - $mtable->attach_defaults($scrolled_win,0,10,0,9); - $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2); - $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2); - - my $board_name=$self->object_get_attribute('compile','board'); - - #copy board jtag_intfc.sh file - my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); - copy("../boards/$vendor/$board_name/jtag_intfc.sh","${fpath}../sw/jtag_intfc.sh"); - my $m= $self->object_get_attribute('mpsoc_name',undef); - if(defined $m){ # we are compiling a complete NoC-based mpsoc - my ($nr,$ne,$router_p,$ref_tops)= get_noc_verilator_top_modules_info($self); - for (my $tile_num=0;$tile_num<$ne;$tile_num++){ - #print "$tile_num\n"; - my ($soc_name,$num)= $self->mpsoc_get_tile_soc_name($tile_num); - next if(!defined $soc_name); - copy("../boards/$vendor/$board_name/jtag_intfc.sh","${fpath}../sw/tile$tile_num/jtag_intfc.sh"); - } - - } - - - - #copy board program_device.sh file - copy("../boards/$vendor/$board_name/program_device.sh","${fpath}../program_device.sh"); - - #get boards pin list - my $top_v= "../boards/$vendor/$board_name/$board_name.v"; - - if(!-f $top_v){ - message_dialog("Error: Could not load the board pin list. The $top_v does not exist!",'error'); - $window->destroy; - } - - my $board=read_top_v_file($top_v); - - # Write object file - #open(FILE, ">lib/soc/tttttttt") || die "Can not open: $!"; - #print FILE Data::Dumper->Dump([\%$board],['board']); - #close(FILE) || die "Error closing file: $!"; - - my @dirs = ('Input', 'Bidir', 'Output'); - my %models; - foreach my $p (@dirs){ - my %pins=$board->board_get_pin($p); - $models{$p}=gen_combo_model(\%pins); - - } - - my $row=0; - my $col=0; - my @labels= ('Port Direction','Port Range ','Port name ','Assignment Type','Board Port name ','Board Port Range'); - foreach my $p (@labels){ - my $l=gen_label_in_left($p); - $l->set_markup(" $p "); - $table->attach ($l, $col,$col+1, $row, $row+1,'fill','shrink',2,2); - $col++ - } - $row++; - - - #read port list - my $vdb=read_verilog_file($top); - my %port_type=get_ports_type($vdb,"${name}_top"); - my %port_range=get_ports_rang($vdb,"${name}_top"); - my %param = $vdb->get_modules_parameters("${name}_top"); - - foreach my $p (sort keys %port_type){ - my $porttype=$port_type{$p}; - my $portrange=$port_range{$p}; - - if (length($portrange)!=0){ - #replace parameter with their values - my @a= split (/\b/,$portrange); - - foreach my $l (@a){ - my $value=$param{$l}; - if(defined $value){ - chomp $value; - ($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l}); - # print"($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l})\n"; - } - } - - my($s1,$s2)=split (":",$portrange); - { - no warnings 'numeric'; - $s1 = eval $s1; - $s2 = eval $s2; - } - $portrange = "[ $portrange ]" ; - if(defined $s1 && defined $s2 ){ - $portrange = "" if($s1 eq 0 && $s2 eq 0); #the upper and lower range are equal zero so remove it - } - } - - my $label1= gen_label_in_left(" $porttype"); - my $label2= gen_label_in_left(" $portrange"); - my $label3= gen_label_in_left(" $p"); - - $table->attach($label1, 0,1, $row, $row+1,'fill','shrink',2,2); - $table->attach($label2, 1,2, $row, $row+1,'fill','shrink',2,2); - $table->attach($label3, 2,3, $row, $row+1,'fill','shrink',2,2); - - my $assign_type= "Direct,Negate(~)"; - if ($porttype eq 'input') { - my $assign_combo=gen_combobox_object($self,'compile_assign_type',$p,$assign_type,'Direct',undef,undef); - $table->attach( $assign_combo, 3,4, $row, $row+1,'fill','shrink',2,2); - } - - my $type= ($porttype eq 'input') ? 'Input' : - ($porttype eq 'output')? 'Output' : 'Bidir'; - - my $combo= gen_tree_combo($models{$type}); - my $saved=$self->object_get_attribute('compile_pin_pos',$p); - my $box; - my $loc=$row; - if(defined $saved) { - my @indices=@{$saved}; - my $path = TreePath_new_from_indices(@indices); - my $iter = $models{$type}->get_iter($path); - undef $path; - $combo->set_active_iter($iter); - $box->destroy if(defined $box); - my $text=$self->object_get_attribute('compile_pin',$p); - $box=get_range ($board,$self,$type,$text,$portrange,$p); - $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2); - } - - - $combo->signal_connect("changed" => sub{ - - #get and saved new value - my $treeiter= $combo->get_active_iter(); - my $text = $models{$type}->get_value($treeiter, 0); - $self->object_add_attribute('compile_pin',$p,$text); - #get and saved value position in model - my $treepath = $models{$type}->get_path ($treeiter); - my @indices= $treepath->get_indices(); - $self->object_add_attribute('compile_pin_pos',$p,\@indices); - #update borad port range - $box->destroy if(defined $box); - $box=get_range ($board,$self,$type,$text,$portrange,$p); - $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2); - $table->show_all; - - }); - - $table->attach($combo, 4,5, $row, $row+1,'fill','shrink',2,2); - - $row++; - - } - $next-> signal_connect("clicked" => sub{ - - $window->destroy; - fpga_compilation($self,$board,$name,$top,$target_dir,$end_func,$vendor); - - }); - $back-> signal_connect("clicked" => sub{ - - $window->destroy; - select_compiler($self,$name,$top,$target_dir,$end_func,$vendor); - - }); - - - $window->add ($mtable); - $window->show_all(); + my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_; + my $window = def_popwin_size(80,80,"Step 2: Pin Assignment",'percent'); + my $table = def_table(2, 2, FALSE); + my $scrolled_win = add_widget_to_scrolled_win($table); + my $mtable = def_table(10, 10, FALSE); + my $next=def_image_button('icons/right.png','Next'); + my $back=def_image_button('icons/left.png','Previous'); + $mtable->attach_defaults($scrolled_win,0,10,0,9); + $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2); + $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2); + my $board_name=$self->object_get_attribute('compile','board'); + #copy board jtag_intfc.sh file + my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); + copy("../boards/$vendor/$board_name/jtag_intfc.sh","${fpath}../sw/jtag_intfc.sh"); + my $m= $self->object_get_attribute('mpsoc_name',undef); + if(defined $m){ # we are compiling a complete NoC-based mpsoc + my ($nr,$ne,$router_p,$ref_tops)= get_noc_verilator_top_modules_info($self); + for (my $tile_num=0;$tile_num<$ne;$tile_num++){ + #print "$tile_num\n"; + my ($soc_name,$num)= $self->mpsoc_get_tile_soc_name($tile_num); + next if(!defined $soc_name); + copy("../boards/$vendor/$board_name/jtag_intfc.sh","${fpath}../sw/tile$tile_num/jtag_intfc.sh"); + } + } + #copy board program_device.sh file + copy("../boards/$vendor/$board_name/program_device.sh","${fpath}../program_device.sh"); + #get boards pin list + my $top_v= "../boards/$vendor/$board_name/$board_name.v"; + if(!-f $top_v){ + message_dialog("Error: Could not load the board pin list. The $top_v does not exist!",'error'); + $window->destroy; + } + my $board=read_top_v_file($top_v); + # Write object file + #open(FILE, ">lib/soc/tttttttt") || die "Can not open: $!"; + #print FILE Data::Dumper->Dump([\%$board],['board']); + #close(FILE) || die "Error closing file: $!"; + my @dirs = ('Input', 'Bidir', 'Output'); + my %models; + foreach my $p (@dirs){ + my %pins=$board->board_get_pin($p); + $models{$p}=gen_combo_model(\%pins); + + } + my $row=0; + my $col=0; + my @labels= ('Port Direction','Port Range ','Port name ','Assignment Type','Board Port name ','Board Port Range'); + foreach my $p (@labels){ + my $l=gen_label_in_left($p); + $l->set_markup(" $p "); + $table->attach ($l, $col,$col+1, $row, $row+1,'fill','shrink',2,2); + $col++ + } + $row++; + #read port list + my $vdb=read_verilog_file($top); + my %port_type=get_ports_type($vdb,"${name}_top"); + my %port_range=get_ports_rang($vdb,"${name}_top"); + my %param = $vdb->get_modules_parameters("${name}_top"); + foreach my $p (sort keys %port_type){ + my $porttype=$port_type{$p}; + my $portrange=$port_range{$p}; + if (length($portrange)!=0){ + #replace parameter with their values + my @a= split (/\b/,$portrange); + foreach my $l (@a){ + my $value=$param{$l}; + if(defined $value){ + chomp $value; + ($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l}); + # print"($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l})\n"; + } + } + my($s1,$s2)=split (":",$portrange); + { + no warnings 'numeric'; + $s1 = eval $s1; + $s2 = eval $s2; + } + $portrange = "[ $portrange ]" ; + if(defined $s1 && defined $s2 ){ + $portrange = "" if($s1 eq 0 && $s2 eq 0); #the upper and lower range are equal zero so remove it + } + } + my $label1= gen_label_in_left(" $porttype"); + my $label2= gen_label_in_left(" $portrange"); + my $label3= gen_label_in_left(" $p"); + $table->attach($label1, 0,1, $row, $row+1,'fill','shrink',2,2); + $table->attach($label2, 1,2, $row, $row+1,'fill','shrink',2,2); + $table->attach($label3, 2,3, $row, $row+1,'fill','shrink',2,2); + + my $assign_type= "Direct,Negate(~)"; + if ($porttype eq 'input') { + my $assign_combo=gen_combobox_object($self,'compile_assign_type',$p,$assign_type,'Direct',undef,undef); + $table->attach( $assign_combo, 3,4, $row, $row+1,'fill','shrink',2,2); + } + my $type= ($porttype eq 'input') ? 'Input' : + ($porttype eq 'output')? 'Output' : 'Bidir'; + my $combo= gen_tree_combo($models{$type}); + my $saved=$self->object_get_attribute('compile_pin_pos',$p); + my $box; + my $loc=$row; + if(defined $saved) { + my @indices=@{$saved}; + my $path = TreePath_new_from_indices(@indices); + my $iter = $models{$type}->get_iter($path); + undef $path; + $combo->set_active_iter($iter); + $box->destroy if(defined $box); + my $text=$self->object_get_attribute('compile_pin',$p); + $box=get_range ($board,$self,$type,$text,$portrange,$p); + $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2); + } + $combo->signal_connect("changed" => sub{ + #get and saved new value + my $treeiter= $combo->get_active_iter(); + my $text = $models{$type}->get_value($treeiter, 0); + $self->object_add_attribute('compile_pin',$p,$text); + #get and saved value position in model + my $treepath = $models{$type}->get_path ($treeiter); + my @indices= $treepath->get_indices(); + $self->object_add_attribute('compile_pin_pos',$p,\@indices); + #update borad port range + $box->destroy if(defined $box); + $box=get_range ($board,$self,$type,$text,$portrange,$p); + $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2); + $table->show_all; + }); + $table->attach($combo, 4,5, $row, $row+1,'fill','shrink',2,2); + $row++; + } + $next-> signal_connect("clicked" => sub{ + $window->destroy; + fpga_compilation($self,$board,$name,$top,$target_dir,$end_func,$vendor); + + }); + $back-> signal_connect("clicked" => sub{ + + $window->destroy; + select_compiler($self,$name,$top,$target_dir,$end_func,$vendor); + + }); + $window->add ($mtable); + $window->show_all(); } - - - - sub fpga_compilation{ - my ($self,$board,$name,$top,$target_dir,$end_func,$vendor)=@_; - - my $run=def_image_button('icons/gate.png','Compile'); - my $back=def_image_button('icons/left.png','Previous'); - my $regen=def_image_button('icons/refresh.png','Regenerate Top.v'); - my $prog=def_image_button('icons/write.png','Program the board'); - - - my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); - my $board_top_file ="${fpath}Top.v"; - unless (-e $board_top_file ){ - gen_top_v($self,$board,$name,$top) ; - } - - my ($app,$table,$tview,$window) = software_main($fpath,'Top.v'); - $table->attach($back,1,2,1,2,'shrink','shrink',2,2); - $table->attach($regen,4,5,1,2,'shrink','shrink',2,2); - $table->attach ($run,6, 7, 1,2,'shrink','shrink',2,2); - $table->attach($prog,9,10,1,2,'shrink','shrink',2,2); - - - - $regen-> signal_connect("clicked" => sub{ - - my $response = yes_no_dialog("Are you sure you want to regenerate the Top.v file? Note that any changes you have made will be lost"); - if ($response eq 'yes') { - gen_top_v($self,$board,$name,$top); - $app->refresh_source("$board_top_file"); - } - }); - - - - $back-> signal_connect("clicked" => sub{ - - $window->destroy; - get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor); - - }); - - - #compile - $run-> signal_connect("clicked" => sub{ - my $load= show_gif("icons/load.gif"); - $table->attach ($load,8, 9, 1,2,'shrink','shrink',2,2); - $load->show_all; - - set_gui_status($self,'save_project',1); - $app->ask_to_save_changes(); - - quartus_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Altera'); - xilinx_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Xilinx'); - - $load->destroy; - - }); - - - #Programe the board - $prog-> signal_connect("clicked" => sub{ - quartus_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Altera'); - vivado_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Xilinx'); - }); - + my ($self,$board,$name,$top,$target_dir,$end_func,$vendor)=@_; + my $run=def_image_button('icons/gate.png','Compile'); + my $back=def_image_button('icons/left.png','Previous'); + my $regen=def_image_button('icons/refresh.png','Regenerate Top.v'); + my $prog=def_image_button('icons/write.png','Program the board'); + my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$"); + my $board_top_file ="${fpath}Top.v"; + unless (-e $board_top_file ){ + gen_top_v($self,$board,$name,$top) ; + } + my ($app,$table,$tview,$window) = software_main($fpath,'Top.v'); + $table->attach($back,1,2,1,2,'shrink','shrink',2,2); + $table->attach($regen,4,5,1,2,'shrink','shrink',2,2); + $table->attach ($run,6, 7, 1,2,'shrink','shrink',2,2); + $table->attach($prog,9,10,1,2,'shrink','shrink',2,2); + $regen-> signal_connect("clicked" => sub{ + my $response = yes_no_dialog("Are you sure you want to regenerate the Top.v file? Note that any changes you have made will be lost"); + if ($response eq 'yes') { + gen_top_v($self,$board,$name,$top); + $app->refresh_source("$board_top_file"); + } + }); + + $back-> signal_connect("clicked" => sub{ + + $window->destroy; + get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor); + + }); + + #compile + $run-> signal_connect("clicked" => sub{ + my $load= show_gif("icons/load.gif"); + $table->attach ($load,8, 9, 1,2,'shrink','shrink',2,2); + $load->show_all; + set_gui_status($self,'save_project',1); + $app->ask_to_save_changes(); + quartus_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Altera'); + xilinx_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Xilinx'); + $load->destroy; + }); + + #Programe the board + $prog-> signal_connect("clicked" => sub{ + quartus_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Altera'); + vivado_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Xilinx'); + }); } sub vivado_program_the_board { - my ($self,$tview,$target_dir,$name,$vendor) =@_; - - my $bit_file="$target_dir/Vivado/xilinx_compile/${name}.runs/impl_1/Top.bit"; - - - - unless (-f "$target_dir/Vivado/program_board.tcl"){ - #create tcl file - my $xpr = "\$tcl_path/xilinx_compile/${name}.xpr"; - my $tcl=" + my ($self,$tview,$target_dir,$name,$vendor) =@_; + my $bit_file="$target_dir/Vivado/xilinx_compile/${name}.runs/impl_1/Top.bit"; + + unless (-f "$target_dir/Vivado/program_board.tcl"){ + #create tcl file + my $xpr = "\$tcl_path/xilinx_compile/${name}.xpr"; + my $tcl=" #Get tcl shell path relative to current script -set tcl_path [file dirname [info script]] - +set tcl_path [file dirname [info script]] + set projectName $name source \"\$tcl_path/board_property.tcl\" @@ -1340,278 +1063,222 @@ sub vivado_program_the_board { close_project exit - "; - save_file ("$target_dir/Vivado/program_board.tcl",$tcl); - add_info($tview,"File $target_dir/Vivado/program_board.tcl is created\n"); - } - - #check bit file existance - unless (-f $bit_file){ - add_colored_info($tview,"Could not find $bit_file. Click on project Compile button first and make sure it runs successfully.",'red'); - return - } - - - #run vivado using program_board.tcl - my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/program_board.tcl"); - add_colored_info($tview,"Board is programmed successfully!\n",'blue') if($error==0); - - -} - - - + "; + save_file ("$target_dir/Vivado/program_board.tcl",$tcl); + add_info($tview,"File $target_dir/Vivado/program_board.tcl is created\n"); + } + + #check bit file existance + unless (-f $bit_file){ + add_colored_info($tview,"Could not find $bit_file. Click on project Compile button first and make sure it runs successfully.",'red'); + return + } + #run vivado using program_board.tcl + my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/program_board.tcl"); + add_colored_info($tview,"Board is programmed successfully!\n",'blue') if($error==0); +} sub quartus_program_the_board{ - my ($self,$tview,$target_dir,$name,$vendor)=@_; - my $error = 0; - my $sof_file="$target_dir/Quartus/output_files/${name}.sof"; - my $bash_file="$target_dir/program_device.sh"; - - add_info($tview,"Program the board using Quartus_pgm and $sof_file file\n"); - #check if the programming file exists - unless (-f $sof_file) { - add_colored_info($tview,"\tThe $sof_file does not exists! Make sure you have compiled the code successfully.\n", 'red'); - $error=1; - } - #check if the program_device.sh file exists - unless (-f $bash_file) { - add_colored_info($tview,"\tThe $bash_file does not exist! This file varies depending on your target board and must be available inside mpsoc/boards/$vendor/[board_name].\n", 'red'); - $error=1; - } - return if($error); - my $command = "bash $bash_file $sof_file"; - add_info($tview,"$command\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); - if(length $stderr>1){ - add_colored_info($tview,"$stderr\n",'red'); - add_colored_info($tview,"Board was not programmed successfully!\n",'red'); - }else { - if($exit){ - add_colored_info($tview,"$stdout\n",'red'); - add_colored_info($tview,"Board was not programmed successfully!\n",'red'); - }else{ - add_info($tview,"$stdout\n"); - add_colored_info($tview,"Board is programmed successfully!\n",'blue'); - } - - } + my ($self,$tview,$target_dir,$name,$vendor)=@_; + my $error = 0; + my $sof_file="$target_dir/Quartus/output_files/${name}.sof"; + my $bash_file="$target_dir/program_device.sh"; + add_info($tview,"Program the board using Quartus_pgm and $sof_file file\n"); + #check if the programming file exists + unless (-f $sof_file) { + add_colored_info($tview,"\tThe $sof_file does not exists! Make sure you have compiled the code successfully.\n", 'red'); + $error=1; + } + #check if the program_device.sh file exists + unless (-f $bash_file) { + add_colored_info($tview,"\tThe $bash_file does not exist! This file varies depending on your target board and must be available inside mpsoc/boards/$vendor/[board_name].\n", 'red'); + $error=1; + } + return if($error); + my $command = "bash $bash_file $sof_file"; + add_info($tview,"$command\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); + if(length $stderr>1){ + add_colored_info($tview,"$stderr\n",'red'); + add_colored_info($tview,"Board was not programmed successfully!\n",'red'); + }else { + if($exit){ + add_colored_info($tview,"$stdout\n",'red'); + add_colored_info($tview,"Board was not programmed successfully!\n",'red'); + }else{ + add_info($tview,"$stdout\n"); + add_colored_info($tview,"Board is programmed successfully!\n",'blue'); + } + } } - sub quartus_run_compile{ - my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_; - - my $error = 0; - add_info($tview,"CREATE: start creating Quartus project in $target_dir/Quartus folder\n"); - - mkpath("$target_dir/Quartus",1,01777); - - #get list of source file - add_info($tview," Read the list of all source files $target_dir/src_verilog\n"); - my @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$target_dir/src_verilog" ); - - #make sure source files have key word 'module' - my @sources; - foreach my $p (@files){ - push (@sources,$p) if(check_file_has_string($p,'endpackage')); - } - foreach my $p (@files){ - push (@sources,$p) if(check_file_has_string($p,'module')); - } - my $files = join ("\n",@sources); - add_info($tview,"$files\n"); - - #creat project qsf file - my $qsf_file="$target_dir/Quartus/${name}.qsf"; - save_file ($qsf_file,"# Generated using ProNoC\n"); - - #append global assignets to qsf file - my $board_name=$self->object_get_attribute('compile','board'); - my @qsfs = glob("../boards/$vendor/$board_name/*.qsf"); - if(!defined $qsfs[0]){ - message_dialog("Error: ../boards/$vendor/$board_name folder does not contain the qsf file.!",'error'); - $window->destroy; - } - - my $assignment_file = $qsfs[0]; - - if(-f $assignment_file){ - merg_files ($assignment_file,$qsf_file); - } - - my %paths; - - #add the list of source fils to qsf file - my $s="\n\n\n set_global_assignment -name TOP_LEVEL_ENTITY Top\n"; - foreach my $p (@sources){ - my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$"); - $s="$s set_global_assignment -name VERILOG_FILE $p\n" if ($suffix eq ".v"); - $s="$s set_global_assignment -name SYSTEMVERILOG_FILE $p\n" if ($suffix eq ".sv"); - $paths{$path}=1; - } - - - - - - - foreach my $p (sort keys %paths){ - $s="$s set_global_assignment -name SEARCH_PATH $p\n"; - } - - append_text_to_file($qsf_file,$s); - add_info($tview,"\n Qsf file has been created\n"); - - - - - #start compilation - my $Quartus_bin= $self->object_get_attribute('compile','quartus bin'); - my @qfiles = ("quartus_map","quartus_fit","quartus_asm","quartus_sta"); - foreach my $f (@qfiles){ - unless(-f "$Quartus_bin/$f" ){ - $error=1; - add_colored_info($tview, "$Quartus_bin/$f No such file or directory\n",'red'); - last; - } - - } - - my $run_sh = "#!/bin/bash + my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_; + my $error = 0; + add_info($tview,"CREATE: start creating Quartus project in $target_dir/Quartus folder\n"); + mkpath("$target_dir/Quartus",1,01777); + #get list of source file + add_info($tview," Read the list of all source files $target_dir/src_verilog\n"); + my @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$target_dir/src_verilog" ); + #make sure source files have key word 'module' + my @sources; + foreach my $p (@files){ + push (@sources,$p) if(check_file_has_string($p,'endpackage')); + } + foreach my $p (@files){ + push (@sources,$p) if(check_file_has_string($p,'module')); + } + my $files = join ("\n",@sources); + add_info($tview,"$files\n"); + #creat project qsf file + my $qsf_file="$target_dir/Quartus/${name}.qsf"; + save_file ($qsf_file,"# Generated using ProNoC\n"); + #append global assignets to qsf file + my $board_name=$self->object_get_attribute('compile','board'); + my @qsfs = glob("../boards/$vendor/$board_name/*.qsf"); + if(!defined $qsfs[0]){ + message_dialog("Error: ../boards/$vendor/$board_name folder does not contain the qsf file.!",'error'); + $window->destroy; + } + my $assignment_file = $qsfs[0]; + if(-f $assignment_file){ + merg_files ($assignment_file,$qsf_file); + } + my %paths; + #add the list of source fils to qsf file + my $s="\n\n\n set_global_assignment -name TOP_LEVEL_ENTITY Top\n"; + foreach my $p (@sources){ + my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$"); + $s="$s set_global_assignment -name VERILOG_FILE $p\n" if ($suffix eq ".v"); + $s="$s set_global_assignment -name SYSTEMVERILOG_FILE $p\n" if ($suffix eq ".sv"); + $paths{$path}=1; + } + foreach my $p (sort keys %paths){ + $s="$s set_global_assignment -name SEARCH_PATH $p\n"; + } + append_text_to_file($qsf_file,$s); + add_info($tview,"\n Qsf file has been created\n"); + #start compilation + my $Quartus_bin= $self->object_get_attribute('compile','quartus bin'); + my @qfiles = ("quartus_map","quartus_fit","quartus_asm","quartus_sta"); + foreach my $f (@qfiles){ + unless(-f "$Quartus_bin/$f" ){ + $error=1; + add_colored_info($tview, "$Quartus_bin/$f No such file or directory\n",'red'); + last; + } + } + my $run_sh = "#!/bin/bash $Quartus_bin/quartus_map --64bit $name --read_settings_files=on $Quartus_bin/quartus_fit --64bit $name --read_settings_files=on $Quartus_bin/quartus_asm --64bit $name --read_settings_files=on -$Quartus_bin/quartus_sta --64bit $name - "; - - save_file("$target_dir/Quartus/run.sh", $run_sh); - - add_info($tview, "Start Quartus compilation.....\n"); - my @compilation_command =( - "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_map --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ", - "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ", - "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ", - "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_sta --64bit $name; echo \$? > status; sleep 1 ' "); - - foreach my $cmd (@compilation_command){ - last if($error); - add_info($tview,"$cmd\n"); - unlink "$target_dir/Quartus/status"; - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); - if($exit){ - add_colored_info($tview, "$stdout\n",'red') if(defined $stdout); - add_colored_info($tview, "$stderr\n",'red') if(defined $stderr); - $error=1; - last; - } - - open(my $fh, "<$target_dir/Quartus/status") || die "Can not open: $!"; - read($fh,my $status,1); - close($fh); - if("$status" != "0"){ - ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("cd \"$target_dir/Quartus/output_files/\" \n grep -h \"Error (\" *"); - add_colored_info($tview,"$stderr\n",'red') if(defined $stderr); - add_colored_info($tview,"$stdout\n",'red'); - $error=1; - last; - } - } - add_colored_info($tview,"Quartus compilation failed !\n",'red') if($error==1); - add_colored_info($tview,"Quartus compilation is done successfully in $target_dir/Quartus!\n", 'blue') if($error==0); - if (defined $end_func){ - if ($error==0){ - $end_func->($self); - $window->destroy; - }else { - message_dialog("Error in Quartus compilation!",'error'); - } - } - - - +$Quartus_bin/quartus_sta --64bit $name + "; + save_file("$target_dir/Quartus/run.sh", $run_sh); + add_info($tview, "Start Quartus compilation.....\n"); + my @compilation_command =( + "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_map --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ", + "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ", + "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ", + "cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_sta --64bit $name; echo \$? > status; sleep 1 ' "); + foreach my $cmd (@compilation_command){ + last if($error); + add_info($tview,"$cmd\n"); + unlink "$target_dir/Quartus/status"; + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); + if($exit){ + add_colored_info($tview, "$stdout\n",'red') if(defined $stdout); + add_colored_info($tview, "$stderr\n",'red') if(defined $stderr); + $error=1; + last; + } + open(my $fh, "<$target_dir/Quartus/status") || die "Can not open: $!"; + read($fh,my $status,1); + close($fh); + if("$status" != "0"){ + ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("cd \"$target_dir/Quartus/output_files/\" \n grep -h \"Error (\" *"); + add_colored_info($tview,"$stderr\n",'red') if(defined $stderr); + add_colored_info($tview,"$stdout\n",'red'); + $error=1; + last; + } + } + add_colored_info($tview,"Quartus compilation failed !\n",'red') if($error==1); + add_colored_info($tview,"Quartus compilation is done successfully in $target_dir/Quartus!\n", 'blue') if($error==0); + if (defined $end_func){ + if ($error==0){ + $end_func->($self); + $window->destroy; + }else { + message_dialog("Error in Quartus compilation!",'error'); + } + } } - - - - - sub xilinx_run_compile{ - my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_; - - add_info($tview,"CREATE: start creating Vivado project in $target_dir/Vivado\n"); - #get list of source file - add_info($tview," Read the list of all source files $target_dir/src_verilog\n"); - my @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$target_dir/src_verilog" ); - - #make sure source files have key word 'module' - my @sources; - foreach my $p (@files){ - push (@sources,$p) if(check_file_has_string($p,'endpackage')); - } - foreach my $p (@files){ - push (@sources,$p) if(check_file_has_string($p,'module')); - } - - my %paths; - foreach my $p (@files){ - my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$"); - #print "$path\n"; - my $remove="$target_dir/"; - $path =~ s/$remove//; - $paths{$path}=1; - } - - - - - my $incdir="set include_dir_list [list"; - foreach my $p (sort keys %paths){ - $incdir.=" \$Dir/$p"; - } - $incdir.="]"; - - my $files = join ("\n",@sources); - - - - #add mem initial file to sources - my $mem_files=""; - my @initial_files = File::Find::Rule->file() - ->name( '*.mem') - ->in( "$target_dir/sw" ); - mkpath("$target_dir/Vivado/xilinx_mem",1,01777) unless -f "$target_dir/Vivado/xilinx_mem"; - foreach my $f (@initial_files){ - # /home/alireza/work/hca_git/mpsoc_work/SOC/mor1k_soc/sw/RAM/ram0.mif fpr soc - # /home/alireza/work/hca_git/mpsoc_work/MPSOC/newAdder/sw/tile0/RAM/ram0.mif fpr mpsoc - my @m = split('\/sw\/',$f ); - my $d = $m[-1];#take the last file path name after /sw/ - $d=~ s/RAM//g; #remove RAM - $d=~ s/\///g; #remove / - $d = "tile0".$d unless($m[-1]=~/^tile/); #add tile0 to soc - copy($f,"$target_dir/Vivado/xilinx_mem/$d"); - $mem_files="$mem_files \$tcl_path/xilinx_mem/$d"; - } - add_info($tview,"HDL sources:\n$files\nMem sources:\n$mem_files\n"); - #make tcl file - my $tcl=" + my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_; + add_info($tview,"CREATE: start creating Vivado project in $target_dir/Vivado\n"); + #get list of source file + add_info($tview," Read the list of all source files $target_dir/src_verilog\n"); + my @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$target_dir/src_verilog" ); + #make sure source files have key word 'module' + my @sources; + foreach my $p (@files){ + push (@sources,$p) if(check_file_has_string($p,'endpackage')); + } + foreach my $p (@files){ + push (@sources,$p) if(check_file_has_string($p,'module')); + } + my %paths; + foreach my $p (@files){ + my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$"); + #print "$path\n"; + my $remove="$target_dir/"; + $path =~ s/$remove//; + $paths{$path}=1; + } + my $incdir="set include_dir_list [list"; + foreach my $p (sort keys %paths){ + $incdir.=" \$Dir/$p"; + } + $incdir.="]"; + my $files = join ("\n",@sources); + #add mem initial file to sources + my $mem_files=""; + my @initial_files = File::Find::Rule->file() + ->name( '*.mem') + ->in( "$target_dir/sw" ); + mkpath("$target_dir/Vivado/xilinx_mem",1,01777) unless -f "$target_dir/Vivado/xilinx_mem"; + foreach my $f (@initial_files){ + # /home/alireza/work/hca_git/mpsoc_work/SOC/mor1k_soc/sw/RAM/ram0.mif fpr soc + # /home/alireza/work/hca_git/mpsoc_work/MPSOC/newAdder/sw/tile0/RAM/ram0.mif fpr mpsoc + my @m = split('\/sw\/',$f ); + my $d = $m[-1];#take the last file path name after /sw/ + $d=~ s/RAM//g; #remove RAM + $d=~ s/\///g; #remove / + $d = "tile0".$d unless($m[-1]=~/^tile/); #add tile0 to soc + copy($f,"$target_dir/Vivado/xilinx_mem/$d"); + $mem_files="$mem_files \$tcl_path/xilinx_mem/$d"; + } + add_info($tview,"HDL sources:\n$files\nMem sources:\n$mem_files\n"); + #make tcl file + my $tcl=" #Get tcl shell path relative to current script -set tcl_path [file dirname [info script]] +set tcl_path [file dirname [info script]] set Dir \"\$tcl_path/..\" "; - - $tcl=$tcl."set projectName $name"; - - $tcl =$tcl." + + $tcl=$tcl."set projectName $name"; + + $tcl =$tcl." source \"\$tcl_path/board_property.tcl\" #Create output directory and clear contents set outputdir \"\$tcl_path/xilinx_compile\""; - $tcl =$tcl.' + $tcl =$tcl.' file mkdir $outputdir set files [glob -nocomplain "$outputdir/*"] if {[llength $files] != 0} { @@ -1626,267 +1293,217 @@ sub xilinx_run_compile{ set_project_properties -#add source files to Vivado project +#add source files to Vivado project '; - #get top level port names - #get boards pin list - my $top_v= "$target_dir/src_verilog/Top.v"; - if(!-f $top_v){ - message_dialog("Error: Could not load the board pin list. The Top.v does not exist!",'error'); - $window->destroy; - } - - - my @ports=verilog_file_get_ports_list(read_verilog_file($top_v),"Top"); - - #get board tcl - my $board_name=$self->object_get_attribute('compile','board'); - my @tcls= glob("../boards/$vendor/$board_name/*.tcl"); - foreach my $f (@tcls){ - copy($f,"$target_dir/Vivado"); - } - - #get board xdc - my @xdcs= glob("../boards/$vendor/$board_name/*.xdc"); - my $i=1; - - foreach my $f (@xdcs){ - my $out=""; - #capture file content - my $string= load_file($f); - my @lines=split('\n',$string); - #make sure lines describing the port name are not comment - foreach my $l (@lines){ - foreach my $p (@ports){ - - $l=~ s/^\s*#/ /g if($l =~ /^\s*#/ && $l =~ /\[\s*get_ports\s*[{\s]\s*$p[\s\[\]\}]/ );# /\[get_ports\s*{\s*$p[\s\}\[]/); - - } - $out=$out."$l\n"; - } - my ($fname,$fpath,$fsuffix) = fileparse("$f",qr"\..[^.]*$"); - my $xdc_file = "$target_dir/Vivado/$fname.xdc"; - #save new xdc file - save_file($xdc_file,$out); - #add xdc to tcl file - $tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/$fname.xdc\n"; - $i++; - } - - #internal clock constrain - my $clk_xdc=get_clk_constrain_file($self); - #save_file ("$target_dir/clk.xdc",$clk_xdc); - #$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/clk.xdc\n"; - - - - $tcl =$tcl."add_files "; - #add hdl sources - foreach my $f (@sources){ - my $p =cut_dir_path($f,'src_verilog'); - $tcl =$tcl." \$Dir/src_verilog/$p "; - } - $tcl =$tcl."\n"; - - $tcl =$tcl."#add memory initial files to Vivado project - add_files -norecurse $mem_files" if(length($mem_files)>3); - - - $tcl =$tcl."\n set_property \"top\" \"Top\" [current_fileset]\n"; - $tcl =$tcl." - update_compile_order -fileset sources_1 - #launch synthesis - - # Make all reset syncron - set_property verilog_define {{SYNC_RESET_MODE}} [current_fileset] - - # include source dirs - $incdir - set_property include_dirs \$include_dir_list [current_fileset] - - launch_runs synth_1 - wait_on_run synth_1 - #Run implementation and generate bitstream - set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] - launch_runs impl_1 -to_step write_bitstream - wait_on_run impl_1 - puts \"Implementation done!\" - "; - - - $tcl =$tcl."\nexit"; - #creat make_project tcl file - save_file ("$target_dir/Vivado/make_project.tcl",$tcl); - - my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/make_project.tcl"); - add_colored_info($tview,"Vivado compilation is done successfully in $target_dir/Vivado!\n", 'blue') if($error==0); - if (defined $end_func){ - if ($error==0){ - $end_func->($self); - $window->destroy; - }else { - message_dialog("Error in Vivado compilation!",'error'); - } - } - - -} - + #get top level port names + #get boards pin list + my $top_v= "$target_dir/src_verilog/Top.v"; + if(!-f $top_v){ + message_dialog("Error: Could not load the board pin list. The Top.v does not exist!",'error'); + $window->destroy; + } + my @ports=verilog_file_get_ports_list(read_verilog_file($top_v),"Top"); + #get board tcl + my $board_name=$self->object_get_attribute('compile','board'); + my @tcls= glob("../boards/$vendor/$board_name/*.tcl"); + foreach my $f (@tcls){ + copy($f,"$target_dir/Vivado"); + } + #get board xdc + my @xdcs= glob("../boards/$vendor/$board_name/*.xdc"); + my $i=1; + + foreach my $f (@xdcs){ + my $out=""; + #capture file content + my $string= load_file($f); + my @lines=split('\n',$string); + #make sure lines describing the port name are not comment + foreach my $l (@lines){ + foreach my $p (@ports){ + + $l=~ s/^\s*#/ /g if($l =~ /^\s*#/ && $l =~ /\[\s*get_ports\s*[{\s]\s*$p[\s\[\]\}]/ );# /\[get_ports\s*{\s*$p[\s\}\[]/); + + } + $out=$out."$l\n"; + } + my ($fname,$fpath,$fsuffix) = fileparse("$f",qr"\..[^.]*$"); + my $xdc_file = "$target_dir/Vivado/$fname.xdc"; + #save new xdc file + save_file($xdc_file,$out); + #add xdc to tcl file + $tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/$fname.xdc\n"; + $i++; + } + #internal clock constrain + my $clk_xdc=get_clk_constrain_file($self); + #save_file ("$target_dir/clk.xdc",$clk_xdc); + #$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/clk.xdc\n"; + $tcl =$tcl."add_files "; + #add hdl sources + foreach my $f (@sources){ + my $p =cut_dir_path($f,'src_verilog'); + $tcl =$tcl." \$Dir/src_verilog/$p "; + } + $tcl =$tcl."\n"; + $tcl =$tcl."#add memory initial files to Vivado project + add_files -norecurse $mem_files" if(length($mem_files)>3); + $tcl =$tcl."\n set_property \"top\" \"Top\" [current_fileset]\n"; + $tcl =$tcl." + update_compile_order -fileset sources_1 + #launch synthesis + + # Make all reset syncron + set_property verilog_define {{SYNC_RESET_MODE}} [current_fileset] + + # include source dirs + $incdir + set_property include_dirs \$include_dir_list [current_fileset] + + launch_runs synth_1 + wait_on_run synth_1 + #Run implementation and generate bitstream + set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] + launch_runs impl_1 -to_step write_bitstream + wait_on_run impl_1 + puts \"Implementation done!\" + "; + $tcl =$tcl."\nexit"; + #creat make_project tcl file + save_file ("$target_dir/Vivado/make_project.tcl",$tcl); + my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/make_project.tcl"); + add_colored_info($tview,"Vivado compilation is done successfully in $target_dir/Vivado!\n", 'blue') if($error==0); + if (defined $end_func){ + if ($error==0){ + $end_func->($self); + $window->destroy; + }else { + message_dialog("Error in Vivado compilation!",'error'); + } + } +} sub run_vivado { - my ($self,$target_dir,$tview,$tcl)=@_; - my $error=0; - #start compilation - my $vivado_bin= $self->object_get_attribute('compile','vivado bin'); - add_info($tview, "Start compilation using vivado.....\n"); - my @compilation_command =( - "cd \"$target_dir/Vivado/\" \n xterm -e bash -c '$vivado_bin/vivado -mode tcl -source $tcl'" - ); - - save_file("$target_dir/Vivado/run.sh", "#!/bin/bash \n $vivado_bin/vivado -mode tcl -source $tcl"); - - - my $log="$target_dir/Vivado/vivado.log"; - #unlink $log; - - foreach my $cmd (@compilation_command){ - add_info($tview,"$cmd\n"); - - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); - if($exit){ - $error=1; - add_colored_info($tview, "$stdout\n",'red') if(defined $stdout); - add_colored_info($tview, "$stderr\n",'red') if(defined $stderr); - } - - } - - #check vivado.log for error - my $r; - open my $fd, "<" , $log or $r=$!; - if(defined $r ) { - add_colored_info($tview, "could not open $log to check errors: $r\n",'red'); - $error=1; - } - else{ - - #check error - while (my $line = <$fd>) { - chomp $line; - if( $line =~ /ERROR:/){ - add_colored_info($tview, "$line\n",'red'); - $error=1; - } - } - - #check warning - close($fd); - open $fd, "<" , $log; - #print "$log\n"; - if($error==0){ - while (my $line = <$fd>) { - chomp $line; - if( $line =~ /^\s*WARNING:/){ - add_info($tview, "$line\n"); - - } - } - } - - #check critical warning - close($fd); - open $fd, "<" , $log; - #print "$log\n"; - if($error==0){ - while (my $line = <$fd>) { - chomp $line; - if( $line =~ /^\s*CRITICAL WARNING:/){ - add_colored_info($tview, "$line\n",'green'); - } - } - } - close($fd); - } - return $error; + my ($self,$target_dir,$tview,$tcl)=@_; + my $error=0; + #start compilation + my $vivado_bin= $self->object_get_attribute('compile','vivado bin'); + add_info($tview, "Start compilation using vivado.....\n"); + my @compilation_command =( + "cd \"$target_dir/Vivado/\" \n xterm -e bash -c '$vivado_bin/vivado -mode tcl -source $tcl'" + ); + save_file("$target_dir/Vivado/run.sh", "#!/bin/bash \n $vivado_bin/vivado -mode tcl -source $tcl"); + my $log="$target_dir/Vivado/vivado.log"; + #unlink $log; + foreach my $cmd (@compilation_command){ + add_info($tview,"$cmd\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); + if($exit){ + $error=1; + add_colored_info($tview, "$stdout\n",'red') if(defined $stdout); + add_colored_info($tview, "$stderr\n",'red') if(defined $stderr); + } + } + #check vivado.log for error + my $r; + open my $fd, "<" , $log or $r=$!; + if(defined $r ) { + add_colored_info($tview, "could not open $log to check errors: $r\n",'red'); + $error=1; + } + else{ + #check error + while (my $line = <$fd>) { + chomp $line; + if( $line =~ /ERROR:/){ + add_colored_info($tview, "$line\n",'red'); + $error=1; + } + } + #check warning + close($fd); + open $fd, "<" , $log; + #print "$log\n"; + if($error==0){ + while (my $line = <$fd>) { + chomp $line; + if( $line =~ /^\s*WARNING:/){ + add_info($tview, "$line\n"); + } + } + } + #check critical warning + close($fd); + open $fd, "<" , $log; + #print "$log\n"; + if($error==0){ + while (my $line = <$fd>) { + chomp $line; + if( $line =~ /^\s*CRITICAL WARNING:/){ + add_colored_info($tview, "$line\n",'green'); + } + } + } + close($fd); + } + return $error; } - - - - sub modelsim_compilation{ - my ($self,$name,$top,$target_dir,$vendor)=@_; - #my $window = def_popwin_size(80,80,"Step 2: Compile",'percent'); - - - my $run=def_image_button('icons/run.png','_run',FALSE,1); - my $back=def_image_button('icons/left.png','Previous'); - my $regen=def_image_button('icons/refresh.png','Regenerate testbench.v'); - - - #creat modelsim dir - - my $model="$target_dir/Modelsim"; - unlink("$model/model.tcl"); - rmtree("$target_dir/rtl_work"); - mkpath("$model/rtl_work",1,01777); - - my ($app,$table,$tview,$window) = software_main("$target_dir/Modelsim",undef); - #create testbench.v - gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview) unless (-f "$target_dir/Modelsim/testbench.v"); - $app->refresh_source("$target_dir/Modelsim/testbench.v"); - - - - add_info($tview,"create Modelsim dir in $target_dir\n"); - $table->attach($back,1,2,1,2,'shrink','shrink',2,2); - $table->attach($regen,4,5,1,2,'shrink','shrink',2,2); - $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0); - - - - $regen-> signal_connect("clicked" => sub{ - my $response = yes_no_dialog("Are you sure you want to regenerate the testbench.v file? Note that any changes you have made will be lost"); - if ($response eq 'yes') { - gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview); - $app->refresh_source("$target_dir/Modelsim/testbench.v"); - } - }); - - $back-> signal_connect("clicked" => sub{ - - $window->destroy; - select_compiler($self,$name,$top,$target_dir); - - }); - - #Get the list of all verilog files in src_verilog folder - add_info($tview,"Get the list of all Verilog files in src_verilog folder\n"); - my @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$target_dir/src_verilog" ); - - #get list of all verilog files in src_sim folder + my ($self,$name,$top,$target_dir,$vendor)=@_; + #my $window = def_popwin_size(80,80,"Step 2: Compile",'percent'); + my $run=def_image_button('icons/run.png','_run',FALSE,1); + my $back=def_image_button('icons/left.png','Previous'); + my $regen=def_image_button('icons/refresh.png','Regenerate testbench.v'); + #creat modelsim dir + my $model="$target_dir/Modelsim"; + unlink("$model/model.tcl"); + rmtree("$target_dir/rtl_work"); + mkpath("$model/rtl_work",1,01777); + my ($app,$table,$tview,$window) = software_main("$target_dir/Modelsim",undef); + #create testbench.v + gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview) unless (-f "$target_dir/Modelsim/testbench.v"); + $app->refresh_source("$target_dir/Modelsim/testbench.v"); + add_info($tview,"create Modelsim dir in $target_dir\n"); + $table->attach($back,1,2,1,2,'shrink','shrink',2,2); + $table->attach($regen,4,5,1,2,'shrink','shrink',2,2); + $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0); + $regen-> signal_connect("clicked" => sub{ + my $response = yes_no_dialog("Are you sure you want to regenerate the testbench.v file? Note that any changes you have made will be lost"); + if ($response eq 'yes') { + gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview); + $app->refresh_source("$target_dir/Modelsim/testbench.v"); + } + }); + $back-> signal_connect("clicked" => sub{ + $window->destroy; + select_compiler($self,$name,$top,$target_dir); + }); + + #Get the list of all verilog files in src_verilog folder + add_info($tview,"Get the list of all Verilog files in src_verilog folder\n"); + my @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$target_dir/src_verilog" ); + + #get list of all verilog files in src_sim folder my @sim_files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$target_dir/src_sim" ); - push (@files, @sim_files); - #add testnemch.v - push (@files, "$target_dir/Modelsim/testbench.v"); - - #create a file list - my $tt =create_file_list($target_dir,\@files,'modelsim'); - save_file("$target_dir/Modelsim/file_list.f", "$tt"); - - - #create modelsim.tcl file + ->name( '*.v','*.V','*.sv' ) + ->in( "$target_dir/src_sim" ); + push (@files, @sim_files); + #add testnemch.v + push (@files, "$target_dir/Modelsim/testbench.v"); + + #create a file list + my $tt =create_file_list($target_dir,\@files,'modelsim'); + save_file("$target_dir/Modelsim/file_list.f", "$tt"); + #create modelsim.tcl file my $tcl="#!/usr/bin/tclsh - transcript on if {[file exists rtl_work]} { - vdel -lib rtl_work -all + vdel -lib rtl_work -all } vlib rtl_work vmap work rtl_work @@ -1901,177 +1518,151 @@ sub modelsim_compilation{ view signals run -all "; - add_info($tview,"Create model.tcl, run.sh files\n"); - save_file ("$model/model.tcl",$tcl); - my $modelsim_bin= $self->object_get_attribute('compile','modelsim_bin'); - my $cmd="cd $target_dir/Modelsim; rm -Rf rtl_work; $modelsim_bin/vsim -do $model/model.tcl"; - save_file ("$model/run.sh",'#!/bin/bash'."\n".$cmd); - - $run -> signal_connect("clicked" => sub{ - set_gui_status($self,'save_project',1); - $app->ask_to_save_changes(); - - - add_info($tview,"$cmd\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - add_colored_info($tview,"$stderr\n","red"); - - }else { - add_info($tview,"$stdout\n"); - } - - }); - - #$window->show_all(); + add_info($tview,"Create model.tcl, run.sh files\n"); + save_file ("$model/model.tcl",$tcl); + my $modelsim_bin= $self->object_get_attribute('compile','modelsim_bin'); + my $cmd="cd $target_dir/Modelsim; rm -Rf rtl_work; $modelsim_bin/vsim -do $model/model.tcl"; + save_file ("$model/run.sh",'#!/bin/bash'."\n".$cmd); + $run -> signal_connect("clicked" => sub{ + set_gui_status($self,'save_project',1); + $app->ask_to_save_changes(); + add_info($tview,"$cmd\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + add_colored_info($tview,"$stderr\n","red"); + }else { + add_info($tview,"$stdout\n"); + } + }); + #$window->show_all(); } - # source files : $target_dir/src_verilog # work dir : $target_dir/src_verilog - - sub create_file_list { - my ($target_dir,$files_ref, $platform)=@_; - my @ff=@{$files_ref} if(defined $files_ref); - my $pakages=""; - my $file_list=""; - my $include=""; - - my %paths; - my @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv','*.vh') + my ($target_dir,$files_ref, $platform)=@_; + my @ff=@{$files_ref} if(defined $files_ref); + my $pakages=""; + my $file_list=""; + my $include=""; + my %paths; + my @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv','*.vh') ->in( @ff ); - @ff =uniq( @ff); - - foreach my $file (@files) { - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - #print "$path\n"; - my $remove="$target_dir/"; - $path =~ s/$remove//; - $paths{$path}=1; - - #put packages at the top of the list - if(check_file_has_string($file,'endpackage')){ - $pakages.="../${path}${name}$suffix\n" if($platform eq 'modelsim'); - $pakages.="./${name}$suffix\n" if($platform eq 'verilator'); - } else{ - $file_list.= "../${path}${name}$suffix\n"if($platform eq 'modelsim'); - $file_list.= "./${name}$suffix\n"if($platform eq 'verilator'); - } - } - foreach my $p (sort keys %paths){ - $include.="+incdir+../$p\n"; - } - - return "$include\n$pakages\n$file_list"; + foreach my $file (@files) { + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + #print "$path\n"; + my $remove="$target_dir/"; + $path =~ s/$remove//; + $paths{$path}=1; + #put packages at the top of the list + if(check_file_has_string($file,'endpackage')){ + $pakages.="../${path}${name}$suffix\n" if($platform eq 'modelsim'); + $pakages.="./${name}$suffix\n" if($platform eq 'verilator'); + } else{ + $file_list.= "../${path}${name}$suffix\n"if($platform eq 'modelsim'); + $file_list.= "./${name}$suffix\n"if($platform eq 'verilator'); + } + } + foreach my $p (sort keys %paths){ + $include.="+incdir+../$p\n"; + } + return "$include\n$pakages\n$file_list"; } - sub verilator_compilation { - my ($top_ref,$target_dir,$outtext,$cpu_num)=@_; - $cpu_num = 1 if (!defined $cpu_num); - my %tops = %{$top_ref}; - #creat verilator dir - add_info($outtext,"create verilator dir in $target_dir\n"); - my $verilator="$target_dir/verilator"; - - rmtree("$verilator"); - mkpath("$verilator",1,01777); - - my @ff = ("$target_dir/src_verilog"); - push (@ff,"$target_dir/src_verilator") if (-d "$target_dir/src_verilator"); - push (@ff,"$target_dir/src_sim") if (-d "$target_dir/src_sim"); - - #create a file list - add_info($outtext,"make a file list containig all RTL modules\n"); - my $tt =create_file_list($target_dir,\@ff,'verilator'); - save_file("$verilator/file_list.f", "$tt"); - - #check if -Wno-TIMESCALEMOD flag is supported" + my ($top_ref,$target_dir,$outtext,$cpu_num)=@_; + $cpu_num = 1 if (!defined $cpu_num); + my %tops = %{$top_ref}; + #creat verilator dir + add_info($outtext,"create verilator dir in $target_dir\n"); + my $verilator="$target_dir/verilator"; + rmtree("$verilator"); + mkpath("$verilator",1,01777); + my @ff = ("$target_dir/src_verilog"); + push (@ff,"$target_dir/src_verilator") if (-d "$target_dir/src_verilator"); + push (@ff,"$target_dir/src_sim") if (-d "$target_dir/src_sim"); + #create a file list + add_info($outtext,"make a file list containig all RTL modules\n"); + my $tt =create_file_list($target_dir,\@ff,'verilator'); + save_file("$verilator/file_list.f", "$tt"); + #check if -Wno-TIMESCALEMOD flag is supported" my $flag=""; - # my $cmd ="verilator --version | head -n1 | cut -d\" \" -f2"; - # my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - - # my $current_v=$stdout; - # $current_v =~ s/[^0-9.]//g; - # if (defined $current_v){ - # $cmd = "printf \'%s\n\' \"4.0.0\" \"$current_v\" | sort -V | head -n1"; - # my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - # $stdout =~ s/[^0-9.]//g; - # if ($stdout eq "4.0.0" ){ - # add_info($outtext, "Verilator vesrion $current_v is Greater than or equal to 4.0.0. So compile with -Wno-TIMESCALEMOD flag\n"); - # $flag.="-Wno-TIMESCALEMOD"; - # }else{ - # add_info($outtext, "Verilator vesrion is $current_v\n"); - # } - # } - my $pdir = get_project_dir(); - my $tmp = "$pdir/mpsoc/perl_gui/lib/verilog/tmp.v"; - my $cmd = "verilator --lint-only $tmp -Wno-TIMESCALEMOD"; - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - - if(length $stderr>1){ #-Wno-TIMESCALEMOD not supported - #add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error. - }else { - #add_info($outtext,"compile verilator with -Wno-TIMESCALEMOD\n"); - $flag.="-Wno-TIMESCALEMOD"; - } - - #run verilator - my $jobs=0; #a counter to limit the number of paralle process - my $make_lib=""; - $cmd="cd \"$verilator\"; "; - my $vrun="#!/bin/bash + # my $cmd ="verilator --version | head -n1 | cut -d\" \" -f2"; + # my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + # my $current_v=$stdout; + # $current_v =~ s/[^0-9.]//g; + # if (defined $current_v){ + # $cmd = "printf \'%s\n\' \"4.0.0\" \"$current_v\" | sort -V | head -n1"; + # my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + # $stdout =~ s/[^0-9.]//g; + # if ($stdout eq "4.0.0" ){ + # add_info($outtext, "Verilator vesrion $current_v is Greater than or equal to 4.0.0. So compile with -Wno-TIMESCALEMOD flag\n"); + # $flag.="-Wno-TIMESCALEMOD"; + # }else{ + # add_info($outtext, "Verilator vesrion is $current_v\n"); + # } + # } + my $pdir = get_project_dir(); + my $tmp = "$pdir/mpsoc/perl_gui/lib/verilog/tmp.v"; + my $cmd = "verilator --lint-only $tmp -Wno-TIMESCALEMOD"; + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + + if(length $stderr>1){ #-Wno-TIMESCALEMOD not supported + #add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error. + }else { + #add_info($outtext,"compile verilator with -Wno-TIMESCALEMOD\n"); + $flag.="-Wno-TIMESCALEMOD"; + } + + #run verilator + my $jobs=0; #a counter to limit the number of paralle process + my $make_lib=""; + $cmd="cd \"$verilator\"; "; + my $vrun="#!/bin/bash cd \"$verilator\" "; - #my $cmd= "cd \"$verilator/processed_rtl\" \n xterm -e bash -c ' verilator --cc $name.v --profile-cfuncs --prefix \"Vtop\" -O3 -CFLAGS -O3'"; - my $length = scalar (keys %tops); - foreach my $top (sort keys %tops) { - add_colored_info($outtext,"Generate $top Verilator model from $tops{$top} file\n",'green'); - $cmd.= "verilator -f ./file_list.f --cc $tops{$top} --prefix \"$top\" $flag -O3 -CFLAGS -O3 & "; - $vrun.="verilator -f ./file_list.f --cc $tops{$top} --prefix \"$top\" $flag -O3 -CFLAGS -O3 &\n"; - - $make_lib.="make lib$jobs &\n"; - $jobs++; - - if( $jobs % $cpu_num == 0 || $jobs == $length){ - $vrun.="wait\n"; $make_lib.="wait\n"; $cmd.="wait\n"; - add_info($outtext,"$cmd\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error. - }else { - add_info($outtext,"$stdout\n"); - } - $cmd="cd \"$verilator\"; "; - } - } - - - - #check if verilator model has been generated - foreach my $top (sort keys %tops) { - - $vrun.=" + #my $cmd= "cd \"$verilator/processed_rtl\" \n xterm -e bash -c ' verilator --cc $name.v --profile-cfuncs --prefix \"Vtop\" -O3 -CFLAGS -O3'"; + my $length = scalar (keys %tops); + foreach my $top (sort keys %tops) { + add_colored_info($outtext,"Generate $top Verilator model from $tops{$top} file\n",'green'); + $cmd.= "verilator -DNO_HETRO_IVC=1 -f ./file_list.f --cc $tops{$top} --prefix \"$top\" $flag -O3 -CFLAGS -O3 & "; + $vrun.="verilator -DNO_HETRO_IVC=1 -f ./file_list.f --cc $tops{$top} --prefix \"$top\" $flag -O3 -CFLAGS -O3 &\n"; + + $make_lib.="make lib$jobs &\n"; + $jobs++; + + if( $jobs % $cpu_num == 0 || $jobs == $length){ + $vrun.="wait\n"; $make_lib.="wait\n"; $cmd.="wait\n"; + add_info($outtext,"$cmd\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error. + }else { + add_info($outtext,"$stdout\n"); + } + $cmd="cd \"$verilator\"; "; + } + } + #check if verilator model has been generated + foreach my $top (sort keys %tops) { + + $vrun.=" if ! [ -f $verilator/obj_dir/$top.cpp ]; then - echo \"Failed to generate: $verilator/obj_dir/$top.cpp \" - exit 1 + echo \"Failed to generate: $verilator/obj_dir/$top.cpp \" + exit 1 fi "; - - if (-f "$verilator/obj_dir/$top.cpp"){#succsess - - - }else { - return 0; - } - } - #generate makefile - gen_verilator_makefile($top_ref,"$verilator/obj_dir/Makefile"); - -$vrun.=" echo \"Verilator modules are generated successfully\". + if (-f "$verilator/obj_dir/$top.cpp"){#succsess + }else { + return 0; + } + } + #generate makefile + gen_verilator_makefile($top_ref,"$verilator/obj_dir/Makefile"); + +$vrun.=" echo \"Verilator modules are generated successfully\". cd $verilator/obj_dir/ @@ -2081,285 +1672,212 @@ sub verilator_compilation { make sim #done "; - - - save_file ("$verilator/verilate.sh",$vrun); - #copy topology connection header files - my $project_dir = get_project_dir(); - $project_dir= "$project_dir/mpsoc"; - my $src_verilator_dir="$project_dir/src_verilator"; - my @files = File::Find::Rule->file() - ->name( '*.h') + save_file ("$verilator/verilate.sh",$vrun); + #copy topology connection header files + my $project_dir = get_project_dir(); + $project_dir= "$project_dir/mpsoc"; + my $src_verilator_dir="$project_dir/src_verilator"; + my @files = File::Find::Rule->file() + ->name( '*.h') ->in( "$src_verilator_dir" ); - copy_file_and_folders (\@files,$project_dir,"$verilator/obj_dir/"); - - return 1; + copy_file_and_folders (\@files,$project_dir,"$verilator/obj_dir/"); + + return 1; } - - - - sub verilator_compilation_win { - my ($self,$name,$top,$target_dir,$vendor)=@_; - my $window = def_popwin_size(80,80,"Step 2: Compile",'percent'); - my $mtable = def_table(10, 10, FALSE); - my ($outbox,$outtext)= create_txview(); - - - my $next=def_image_button('icons/run.png','Next'); - my $back=def_image_button('icons/left.png','Previous'); - my $load= show_gif("icons/load.gif"); - $mtable->attach($load,8,9,9,10,'shrink','shrink',2,2); - - $mtable->attach_defaults ($outbox ,0, 10, 4,9); - $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2); - - - - - $back-> signal_connect("clicked" => sub{ - - $window->destroy; - select_compiler($self,$name,$top,$target_dir); - - }); - $next-> signal_connect("clicked" => sub{ - - $window->destroy; - verilator_testbench($self,$name,$top,$target_dir,$vendor); - - }); - - $window->add ($mtable); - $window->show_all(); - - - my $result; - my $cpu_num = $self->object_get_attribute('compile', 'cpu_num'); - - my $n= $self->object_get_attribute('soc_name',undef); - if(defined $n){ #we are compiling a single tile as SoC - my $sw_path = "$target_dir/sw"; - my %params = soc_get_all_parameters($self); - my $verilator = soc_generate_verilator ($self,$sw_path,"verilator_$n",\%params); + my ($self,$name,$top,$target_dir,$vendor)=@_; + my $window = def_popwin_size(80,80,"Step 2: Compile",'percent'); + my $mtable = def_table(10, 10, FALSE); + my ($outbox,$outtext)= create_txview(); + + my $next=def_image_button('icons/run.png','Next'); + my $back=def_image_button('icons/left.png','Previous'); + my $load= show_gif("icons/load.gif"); + $mtable->attach($load,8,9,9,10,'shrink','shrink',2,2); + + $mtable->attach_defaults ($outbox ,0, 10, 4,9); + $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2); + $back-> signal_connect("clicked" => sub{ + $window->destroy; + select_compiler($self,$name,$top,$target_dir); + + }); + $next-> signal_connect("clicked" => sub{ + + $window->destroy; + verilator_testbench($self,$name,$top,$target_dir,$vendor); + + }); + + $window->add ($mtable); + $window->show_all(); + my $result; + my $cpu_num = $self->object_get_attribute('compile', 'cpu_num'); + my $n= $self->object_get_attribute('soc_name',undef); + if(defined $n){ #we are compiling a single tile as SoC + my $sw_path = "$target_dir/sw"; + my %params = soc_get_all_parameters($self); + my $verilator = soc_generate_verilator ($self,$sw_path,"verilator_$n",\%params); my %tops; - $tops{"Vtop"}= "--top-module verilator_$n"; - my $target_verilator_dr ="$target_dir/src_verilator"; - mkpath("$target_verilator_dr",1,01777); - save_file ("$target_verilator_dr/verilator_${n}.sv",$verilator); - - - - - - #$tops{"Vtop"}= "--top-module $name"; - $result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num); - $self->object_add_attribute('verilator','libs',\%tops); - } - else { # we are compiling a complete NoC-based mpsoc - $result = gen_mpsoc_verilator_model ($self,$name,$top,$target_dir,$outtext,$cpu_num); - - - } - - - #check if verilator model has been generated - if ($result){ - add_colored_info($outtext,"Veriator model has been generated successfully!",'blue'); - $load->destroy(); - $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2); - }else { - add_colored_info($outtext,"Verilator compilation failed!\n","red"); - $load->destroy(); - $next->destroy(); - } + $tops{"Vtop"}= "--top-module verilator_$n"; + my $target_verilator_dr ="$target_dir/src_verilator"; + mkpath("$target_verilator_dr",1,01777); + save_file ("$target_verilator_dr/verilator_${n}.sv",$verilator); + #$tops{"Vtop"}= "--top-module $name"; + $result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num); + $self->object_add_attribute('verilator','libs',\%tops); + } + else { # we are compiling a complete NoC-based mpsoc + $result = gen_mpsoc_verilator_model ($self,$name,$top,$target_dir,$outtext,$cpu_num); + } + #check if verilator model has been generated + if ($result){ + add_colored_info($outtext,"Veriator model has been generated successfully!",'blue'); + $load->destroy(); + $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2); + }else { + add_colored_info($outtext,"Verilator compilation failed!\n","red"); + $load->destroy(); + $next->destroy(); + } } - - - - sub gen_mpsoc_verilator_model{ - my ($self,$name,$top,$target_dir,$outtext,$cpu_num)=@_; - - my $project_dir = get_project_dir(); - $project_dir= "$project_dir/mpsoc"; - my $src_verilator_dir="$project_dir/src_verilator"; - my $target_verilog_dr ="$target_dir/src_verilog"; - my $target_verilator_dr ="$target_dir/src_verilator"; - - my $sw_dir = "$target_dir/sw"; - my $src_noc_dir="$project_dir/rtl/src_noc"; - mkpath("$target_verilator_dr",1,01777); - - #copy src_verilator files - my @files_list = File::Find::Rule->file() + my ($self,$name,$top,$target_dir,$outtext,$cpu_num)=@_; + my $project_dir = get_project_dir(); + $project_dir= "$project_dir/mpsoc"; + my $src_verilator_dir="$project_dir/src_verilator"; + my $target_verilog_dr ="$target_dir/src_verilog"; + my $target_verilator_dr ="$target_dir/src_verilator"; + + my $sw_dir = "$target_dir/sw"; + my $src_noc_dir="$project_dir/rtl/src_noc"; + mkpath("$target_verilator_dr",1,01777); + #copy src_verilator files + my @files_list = File::Find::Rule->file() ->name( '*.v','*.V','*.sv' ) ->in( "$src_verilator_dir" ); - #make sure source files have key word 'module' - my @files; - foreach my $p (@files_list){ - push (@files,$p) if(check_file_has_string($p,'module')); - } - copy_file_and_folders (\@files,$project_dir,$target_verilator_dr); - - - - #copy src_noc files - #my @files2; - #push (@files2,$src_noc_dir); - #copy_file_and_folders (\@files2,$project_dir,$target_verilog_dr); - - - #create each tile top module + #make sure source files have key word 'module' + my @files; + foreach my $p (@files_list){ + push (@files,$p) if(check_file_has_string($p,'module')); + } + copy_file_and_folders (\@files,$project_dir,$target_verilator_dr); + #copy src_noc files + #my @files2; + #push (@files2,$src_noc_dir); + #copy_file_and_folders (\@files2,$project_dir,$target_verilog_dr); + #create each tile top module my $processors_en=0; my $mpsoc=$self; my $lisence= get_license_header("verilator_tiles"); - my $warning=autogen_warning(); + my $warning=autogen_warning(); my $verilator=$lisence.$warning; + # generate NoC parameter file + my ($noc_param,$pass_param)=gen_noc_param_v($self); + my $noc_param_v= " \`ifdef INCLUDE_PARAM \n \n + $noc_param + //simulation parameter - # generate NoC parameter file - my ($noc_param,$pass_param)=gen_noc_param_v($self); - - my $noc_param_v= " \`ifdef INCLUDE_PARAM \n \n - $noc_param - - //simulation parameter - \n \n \`endif" ; - #save_file("$target_verilator_dr/parameter.v",$noc_param_v); - - - - + #save_file("$target_verilator_dr/parameter.v",$noc_param_v); my ($nr,$ne,$router_p,$ref_tops)= get_noc_verilator_top_modules_info($self); my %tops = %{$ref_tops}; - for (my $tile_num=0;$tile_num<$ne;$tile_num++){ - - #print "$tile_num\n"; - my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($tile_num); - - my $soc=eval_soc($mpsoc,$soc_name,$outtext); - - - my $top=$mpsoc->mpsoc_get_soc($soc_name); - my $soc_num= $tile_num; - - - #update core id - $soc->object_add_attribute('global_param','CORE_ID',$tile_num); - - #update NoC param - my $nocparam =$mpsoc->object_get_attribute('noc_param',undef); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); - my %y=%{$nocparam}; - $y{'EAw'} = $EAw; - $y{'RAw'} = $RAw; - $y{'Fw'} = $Fw; - my @nis=get_NI_instance_list($top); - $soc->soc_add_instance_param($nis[0] ,\%y ); - my %z; - - my %param_type= $soc->soc_get_module_param_type($nis[0]); - foreach my $p (sort keys %y){ - $z{$p}=$param_type{$p}; #"Parameter"; - } - - - - - $soc->soc_add_instance_param_type($nis[0] ,\%z ); - - - my $tile=$tile_num; - my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile); - my %params; - #if ($setting eq 'Custom'){ - %params= $top->top_get_custom_soc_param($tile); - #}else{ - # %params=$top->top_get_default_soc_param(); - #} - - - my $sw_path = "$sw_dir/tile$tile_num"; - $verilator = $verilator.soc_generate_verilator ($soc,$sw_path,"tile_$tile",\%params); - $tops{"Vtile$tile_num"}= "--top-module tile_$tile"; - - - } - - save_file ("$target_verilator_dr/verilator_tiles.sv",$verilator); - my $result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num); - $self->object_add_attribute('verilator','libs',\%tops); - return $result; - + #print "$tile_num\n"; + my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($tile_num); + my $soc=eval_soc($mpsoc,$soc_name,$outtext); + my $top=$mpsoc->mpsoc_get_soc($soc_name); + my $soc_num= $tile_num; + #update core id + $soc->object_add_attribute('global_param','CORE_ID',$tile_num); + #update NoC param + my $nocparam =$mpsoc->object_get_attribute('noc_param',undef); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); + my %y=%{$nocparam}; + $y{'EAw'} = $EAw; + $y{'RAw'} = $RAw; + $y{'Fw'} = $Fw; + my @nis=get_NI_instance_list($top); + $soc->soc_add_instance_param($nis[0] ,\%y ); + my %z; + my %param_type= $soc->soc_get_module_param_type($nis[0]); + foreach my $p (sort keys %y){ + $z{$p}=$param_type{$p}; #"Parameter"; + } + $soc->soc_add_instance_param_type($nis[0] ,\%z ); + my $tile=$tile_num; + my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile); + my %params; + #if ($setting eq 'Custom'){ + %params= $top->top_get_custom_soc_param($tile); + #}else{ + # %params=$top->top_get_default_soc_param(); + #} + my $sw_path = "$sw_dir/tile$tile_num"; + $verilator = $verilator.soc_generate_verilator ($soc,$sw_path,"tile_$tile",\%params); + $tops{"Vtile$tile_num"}= "--top-module tile_$tile"; + } + save_file ("$target_verilator_dr/verilator_tiles.sv",$verilator); + my $result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num); + $self->object_add_attribute('verilator','libs',\%tops); + return $result; } - sub gen_verilator_soc_testbench { - my ($self,$name,$top,$target_dir)=@_; - my $verilator="$target_dir/verilator"; - my $dir="$verilator/"; - my $soc_top= $self->soc_get_top (); - - my $include='#include + my ($self,$name,$top,$target_dir)=@_; + my $verilator="$target_dir/verilator"; + my $dir="$verilator/"; + my $soc_top= $self->soc_get_top (); + my $include='#include #include #include #include '; - my @intfcs=$soc_top->top_get_intfc_list(); - my %PP; - my %rxds; - my $top_port_info="IO type\t port_size\t port_name\n"; - foreach my $intfc (@intfcs){ - my $key= ( $intfc eq 'plug:clk[0]')? 'clk' : - ( $intfc eq 'plug:reset[0]')? 'reset': - ( $intfc eq 'plug:enable[0]')? 'en' : - ( $intfc eq 'socket:RxD_sim[0]')? 'rxd': - 'other'; - - - my $key1="${key}1"; - my $key0="${key}0"; - - my @ports=$soc_top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); - $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} top->$p=1;\n" : "top->$p=1;\n"; - $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} top->$p=0;\n" : "top->$p=0;\n"; - $top_port_info="$top_port_info $type $range top->$p \n"; - } - if($key eq 'rxd'){ - my @ports=$soc_top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); - my @q =split (/RxD_ready_si/,$p); - $rxds{$id}{p}=$q[0] if( defined $q[1]); - $rxds{$id}{top}='top' if( defined $q[1]); - } - } - - } - - - my ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir); - my $include2=""; + my @intfcs=$soc_top->top_get_intfc_list(); + my %PP; + my %rxds; + my $top_port_info="IO type\t port_size\t port_name\n"; + foreach my $intfc (@intfcs){ + my $key= ( $intfc eq 'plug:clk[0]')? 'clk' : + ( $intfc eq 'plug:reset[0]')? 'reset': + ( $intfc eq 'plug:enable[0]')? 'en' : + ( $intfc eq 'socket:RxD_sim[0]')? 'rxd': + 'other'; + my $key1="${key}1"; + my $key0="${key}0"; + my @ports=$soc_top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); + $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} top->$p=1;\n" : "top->$p=1;\n"; + $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} top->$p=0;\n" : "top->$p=0;\n"; + $top_port_info="$top_port_info $type $range top->$p \n"; + } + if($key eq 'rxd'){ + my @ports=$soc_top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); + my @q =split (/RxD_ready_si/,$p); + $rxds{$id}{p}=$q[0] if( defined $q[1]); + $rxds{$id}{top}='top' if( defined $q[1]); + } + } + } + my ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir); + my $include2=""; $include2 .= '#include "RxDsim.h" // Header file for sending charactor to UART from STDIN' if($rxd_num > 0); - + my $main_c=get_license_header("testbench.cpp"); - - $main_c="$main_c $include $include1 #include // Defines common routines #include \"Vtop.h\" // From Verilating \"$name.v\" file -Vtop *top; +Vtop *top; $include2 /* $top_port_info @@ -2371,74 +1889,71 @@ sub gen_verilator_soc_testbench { unsigned int main_time = 0; // Current simulation time int main(int argc, char** argv) { - $rxd_info - Verilated::commandArgs(argc, argv); // Remember args - top = new Vtop; - - /******************** - * initialize input - *********************/ - - $PP{reset1} - $PP{en1} - main_time=0; - printf(\"Start Simulation\\n\"); - while (!Verilated::gotFinish()) { - $rxd_cap_cal - if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle - if (main_time >= 10 ) { - $PP{reset0} - } - - - if ((main_time & 1) == 0) { - $PP{clk1} // Toggle clock - // you can change the inputs and read the outputs here in case they are captured at posedge of clock - $rxd_wr_cal - - - }//if - else - { - $PP{clk0} - - - - }//else - - - main_time ++; - top->eval(); - } - top->final(); + $rxd_info + Verilated::commandArgs(argc, argv); // Remember args + top = new Vtop; + + /******************** + * initialize input + *********************/ + + $PP{reset1} + $PP{en1} + main_time=0; + printf(\"Start Simulation\\n\"); + while (!Verilated::gotFinish()) { + $rxd_cap_cal + if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle + if (main_time >= 10 ) { + $PP{reset0} + } + + if ((main_time & 1) == 0) { + $PP{clk1} // Toggle clock + // you can change the inputs and read the outputs here in case they are captured at posedge of clock + $rxd_wr_cal + + + }//if + else + { + $PP{clk0} + + + + }//else + + + main_time ++; + top->eval(); + } + top->final(); } double sc_time_stamp () { // Called by \$time in Verilog - return main_time; + return main_time; } "; - save_file("$dir/testbench.cpp",$main_c); - - + save_file("$dir/testbench.cpp",$main_c); + } sub eval_soc{ - my ($mpsoc,$soc_name,$outtext)=@_; - my $path=$mpsoc->object_get_attribute('setting','soc_path'); - $path=~ s/ /\\ /g; - my $p = "$path/$soc_name.SOC"; - my ($soc,$r,$err) = regen_object($p); - if ($r){ - show_info($outtext,"**Error reading $p file: $err\n"); - next; - } - return $soc; + my ($mpsoc,$soc_name,$outtext)=@_; + my $path=$mpsoc->object_get_attribute('setting','soc_path'); + $path=~ s/ /\\ /g; + my $p = "$path/$soc_name.SOC"; + my ($soc,$r,$err) = regen_object($p); + if ($r){ + show_info($outtext,"**Error reading $p file: $err\n"); + next; + } + return $soc; } sub rxd_testbench_verilator_gen { -my ($rxds_ref,$dir)=@_; - +my ($rxds_ref,$dir)=@_; my $rxd_info=''; my $rxd_num=0; my $rxd_func=''; @@ -2447,237 +1962,214 @@ sub rxd_testbench_verilator_gen { my $include=''; my %rxds=%{$rxds_ref}; - foreach my $rxd (sort keys %rxds){ - my $n=$rxds{$rxd}{p}; - my $top=$rxds{$rxd}{top}; - $rxd_info.="\\t$rxd_num : ${top}_${n}RXD\\n"; - - $rxd_func.=" - // we have a character to send to interface $rxd_num - if (sent_table[$rxd_num]!=0 && $top->${n}RxD_ready_sim){ - $top->${n}RxD_din_sim=sent_table[$rxd_num]; + my $n=$rxds{$rxd}{p}; + my $top=$rxds{$rxd}{top}; + $rxd_info.="\\t$rxd_num : ${top}_${n}RXD\\n"; + $rxd_func.=" + // we have a character to send to interface $rxd_num + if (sent_table[$rxd_num]!=0 && $top->${n}RxD_ready_sim){ + $top->${n}RxD_din_sim=sent_table[$rxd_num]; $top->${n}RxD_wr_sim=1; sent_table[$rxd_num]=0; - }else { - $top->${n}RxD_wr_sim=0; - } + }else { + $top->${n}RxD_wr_sim=0; + } "; - $rxd_num++; + $rxd_num++; } -if($rxd_num>0){ +if($rxd_num>0){ $rxd_func=" #ifndef RXD_SIM_H #define RXD_SIM_H - #define RXD_NUM $rxd_num // number of rxd input interfaces - char sent_table[RXD_NUM]={0}; - unsigned char active_rxd_num=0; - void write_char_on_RXD( ) { - $rxd_func - } - - int kbhit(void) { - struct termios oldt, newt; - int ch; - int oldf; - - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &newt); - oldf = fcntl(STDIN_FILENO, F_GETFL, 0); - fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); - - ch = getchar(); - - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - fcntl(STDIN_FILENO, F_SETFL, oldf); - - if(ch != EOF) - { - ungetc(ch, stdin); - return 1; - } - return 0; - } - - void capture_char_on_RXD (){ - char c; - if(kbhit()){ - c=getchar(); - if(c=='+'){ - active_rxd_num++; - if(active_rxd_num>=$rxd_num) active_rxd_num=0; - printf(\"The active input interface num is \%u\\n\",active_rxd_num); - }else if(c=='-'){ - active_rxd_num--; - if(active_rxd_num>=$rxd_num) active_rxd_num=($rxd_num-1); - printf(\"The active input interface num is \%u\\n\",active_rxd_num); - }else{ - sent_table[active_rxd_num]=c; - } - - } - } -#endif - "; - - - $include .='#include + #define RXD_NUM $rxd_num // number of rxd input interfaces + char sent_table[RXD_NUM]={0}; + unsigned char active_rxd_num=0; + void write_char_on_RXD( ) { + $rxd_func + } + + int kbhit(void) { + struct termios oldt, newt; + int ch; + int oldf; + + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + oldf = fcntl(STDIN_FILENO, F_GETFL, 0); + fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); + + ch = getchar(); + + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + fcntl(STDIN_FILENO, F_SETFL, oldf); + + if(ch != EOF) + { + ungetc(ch, stdin); + return 1; + } + return 0; + } + + void capture_char_on_RXD (){ + char c; + if(kbhit()){ + c=getchar(); + if(c=='+'){ + active_rxd_num++; + if(active_rxd_num>=$rxd_num) active_rxd_num=0; + printf(\"The active input interface num is \%u\\n\",active_rxd_num); + }else if(c=='-'){ + active_rxd_num--; + if(active_rxd_num>=$rxd_num) active_rxd_num=($rxd_num-1); + printf(\"The active input interface num is \%u\\n\",active_rxd_num); + }else{ + sent_table[active_rxd_num]=c; + } + } + } +#endif + "; + + + $include .='#include #include '; - $rxd_wr_cal="write_char_on_RXD( );"; - $rxd_cap_cal="capture_char_on_RXD( );"; - $rxd_info="printf(\"There are total of $rxd_num RXD (UART) interface ports in the top module:\\n${rxd_info}The default interfce is 0. You can switch to different interfaces by pressing + or - key.\\n\");" + $rxd_wr_cal="write_char_on_RXD( );"; + $rxd_cap_cal="capture_char_on_RXD( );"; + $rxd_info="printf(\"There are total of $rxd_num RXD (UART) interface ports in the top module:\\n${rxd_info}The default interfce is 0. You can switch to different interfaces by pressing + or - key.\\n\");" } - my $rxsim_c=get_license_header("RxDsim.h"); - $rxsim_c.="$rxd_func"; - save_file("$dir/RxDsim.h",$rxsim_c) if($rxd_num > 0); - - return ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include); - + my $rxsim_c=get_license_header("RxDsim.h"); + $rxsim_c.="$rxd_func"; + save_file("$dir/RxDsim.h",$rxsim_c) if($rxd_num > 0); + return ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include); + } - - sub gen_verilator_mpsoc_testbench { - my ($mpsoc,$name,$top,$target_dir,$tview)=@_; - my $verilator="$target_dir/verilator"; - my $dir="$verilator/"; - my $parameter_h=gen_noc_param_h($mpsoc); - - - my ($nr,$ne,$router_p,$ref_tops,$includ_h)= get_noc_verilator_top_modules_info($mpsoc); - - $parameter_h.=" - #define NE $ne - #define NR $nr - "; - $parameter_h=$parameter_h.$includ_h; - + my ($mpsoc,$name,$top,$target_dir,$tview)=@_; + my $verilator="$target_dir/verilator"; + my $dir="$verilator/"; + my $parameter_h=gen_noc_param_h($mpsoc); + + + my ($nr,$ne,$router_p,$ref_tops,$includ_h)= get_noc_verilator_top_modules_info($mpsoc); + + $parameter_h.=" + #define NE $ne + #define NR $nr + "; + $parameter_h=$parameter_h.$includ_h; + - my $libh=""; - my $inst= ""; - my $newinst=""; - - my $tile_addr=""; - my $tile_flit_in=""; - my $tile_flit_in_l=""; - my $tile_credit=""; - my $noc_credit=""; - my $noc_flit_in=""; - my $noc_flit_in_l=""; - my $noc_flit_in_wr=""; - my $noc_flit_in_wr_l=""; - my $tile_flit_in_wr=""; - my $tile_flit_in_wr_l=""; - my $tile_eval=""; - my $tile_final=""; - my $tile_reset=""; - my $tile_clk=""; - my $tile_en=""; - my $top_port_info="IO type\t port_size\t port_name\n"; - my $no_connected=''; - my %rxds; - - my $tile_chans=""; - my $tmp_reg=''; - for (my $endp=0; $endp<$ne;$endp++){ - - - my $e_addr=endp_addr_encoder($mpsoc,$endp); - my $router_num = get_connected_router_id_to_endp($mpsoc,$endp); - my $r_addr=router_addr_encoder($mpsoc,$router_num); - - - my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($endp); - if(defined $soc_name) {#we have a conncted tile - - #get ni instance name - my $ni_name; - my $soc=eval_soc($mpsoc,$soc_name,$tview); - my $soc_top=$soc->object_get_attribute('top_ip',undef); - my @intfcs=$soc_top->top_get_intfc_list(); - my @instances=$soc->soc_get_all_instances(); - foreach my $id (@instances){ - my $category = $soc->soc_get_category($id); - if ($category eq 'NoC') { - $ni_name= $soc->soc_get_instance_name($id); - } - } - - $tile_chans.="\ttile_chan_out[$endp] = &tile$endp->ni_chan_out;\n\ttile_chan_in[$endp] = &tile$endp->ni_chan_in;\n"; - $libh=$libh."#include \"Vtile${endp}.h\"\n"; - $inst=$inst."Vtile${endp}\t*tile${endp};\t // Instantiation of tile${endp}\n"; - $newinst = $newinst."\ttile${endp}\t=\tnew Vtile${endp};\n"; - $tile_flit_in = $tile_flit_in . "\ttile${endp}->${ni_name}_flit_in = noc->ni_flit_out [${endp}];\n"; - $tile_flit_in_l = $tile_flit_in_l . "\t\ttile${endp}->${ni_name}_flit_in[j] = noc->ni_flit_out [${endp}][j];\n"; - $tile_credit= $tile_credit."\ttile${endp}->${ni_name}_credit_in= noc->ni_credit_out[${endp}];\n"; - $noc_credit= $noc_credit."\tnoc->ni_credit_in[${endp}] = tile${endp}->${ni_name}_credit_out;\n"; - $noc_flit_in=$noc_flit_in."\tnoc->ni_flit_in [${endp}] = tile${endp}->${ni_name}_flit_out;\n"; - $noc_flit_in_l=$noc_flit_in_l."\t\t\tnoc->ni_flit_in [${endp}][j] = tile${endp}->${ni_name}_flit_out[j];\n"; - $noc_flit_in_wr= $noc_flit_in_wr."\tif(tile${endp}->${ni_name}_flit_out_wr) noc->ni_flit_in_wr = noc->ni_flit_in_wr | ((vluint64_t)1<<${endp});\n"; - $tile_flit_in_wr=$tile_flit_in_wr."\ttile${endp}->${ni_name}_flit_in_wr= ((noc->ni_flit_out_wr >> ${endp}) & 0x01);\n"; - $noc_flit_in_wr_l= $noc_flit_in_wr_l."\tif(tile${endp}->${ni_name}_flit_out_wr) MY_VL_SETBIT_W(noc->ni_flit_in_wr ,${endp});\n"; - $tile_flit_in_wr_l=$tile_flit_in_wr_l."\ttile${endp}->${ni_name}_flit_in_wr= (VL_BITISSET_W(noc->ni_flit_out_wr,${endp})>0);\n"; - $tile_eval=$tile_eval."\ttile${endp}->eval();\n"; - $tile_final=$tile_final."\ttile${endp}->final();\n"; - - - foreach my $intfc (@intfcs){ - my $key=($intfc eq 'plug:clk[0]')? 'clk' : - ($intfc eq 'plug:reset[0]')? 'reset': - ($intfc eq 'plug:enable[0]')? 'en' : - ($intfc eq 'socket:RxD_sim[0]')? 'rxd': - 'other'; - - my @ports=$soc_top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); - $tile_reset=$tile_reset."\t\ttile${endp}->$p=reset;\n" if $key eq 'reset'; - $tile_clk=$tile_clk."\t\ttile${endp}->$p=clk;\n" if $key eq 'clk'; - $tile_en=$tile_en."\t\ttile${endp}->$p=enable;\n" if $key eq 'en'; ; - $top_port_info="$top_port_info $type $range tile${endp}->$p \n"; - }#ports - - if($key eq 'rxd'){ - my @ports=$soc_top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); - my @q =split (/RxD_ready_si/,$p); - $rxds{$endp.$id}{p}=$q[0] if( defined $q[1]); - $rxds{$endp.$id}{top}="tile$endp" if( defined $q[1]); - } - } - - - }#interface - - $tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_r_addr=$r_addr; // noc->er_addr[${endp}];\n"; - $tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_e_addr=$e_addr;\n"; - - }else{ - #this tile is not connected to any ip. the noc input ports will be connected to ground - $tmp_reg.="\tunsigned char tmp1 [1024]={0};\n \tunsigned char tmp2 [1024]={0};"; - $tile_chans.="\n // Tile:$endp ($e_addr) is not assigned to any ip. Connet coresponding chan to ground.\n"; - $tile_chans.="\ttile_chan_out[$endp] = tmp1;\n\ttile_chan_in[$endp] = tmp2;\n"; - - } - - - } - - my ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir); - my $include2=""; - $include2 .= '#include "RxDsim.h" // Header file for sending charactor to UART from STDIN' if($rxd_num > 0); - - my $main_c=get_license_header("testbench.cpp"); - + my $libh=""; + my $inst= ""; + my $newinst=""; + + my $tile_addr=""; + my $tile_flit_in=""; + my $tile_flit_in_l=""; + my $tile_credit=""; + my $noc_credit=""; + my $noc_flit_in=""; + my $noc_flit_in_l=""; + my $noc_flit_in_wr=""; + my $noc_flit_in_wr_l=""; + my $tile_flit_in_wr=""; + my $tile_flit_in_wr_l=""; + my $tile_eval=""; + my $tile_final=""; + my $tile_reset=""; + my $tile_clk=""; + my $tile_en=""; + my $top_port_info="IO type\t port_size\t port_name\n"; + my $no_connected=''; + my %rxds; + + my $tile_chans=""; + my $tmp_reg=''; + for (my $endp=0; $endp<$ne;$endp++){ + my $e_addr=endp_addr_encoder($mpsoc,$endp); + my $router_num = get_connected_router_id_to_endp($mpsoc,$endp); + my $r_addr=router_addr_encoder($mpsoc,$router_num); + my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($endp); + if(defined $soc_name) {#we have a conncted tile + + #get ni instance name + my $ni_name; + my $soc=eval_soc($mpsoc,$soc_name,$tview); + my $soc_top=$soc->object_get_attribute('top_ip',undef); + my @intfcs=$soc_top->top_get_intfc_list(); + my @instances=$soc->soc_get_all_instances(); + foreach my $id (@instances){ + my $category = $soc->soc_get_category($id); + if ($category eq 'NoC') { + $ni_name= $soc->soc_get_instance_name($id); + } + } + $tile_chans.="\ttile_chan_out[$endp] = &tile$endp->ni_chan_out;\n\ttile_chan_in[$endp] = &tile$endp->ni_chan_in;\n"; + $libh=$libh."#include \"Vtile${endp}.h\"\n"; + $inst=$inst."Vtile${endp}\t*tile${endp};\t // Instantiation of tile${endp}\n"; + $newinst = $newinst."\ttile${endp}\t=\tnew Vtile${endp};\n"; + $tile_flit_in = $tile_flit_in . "\ttile${endp}->${ni_name}_flit_in = noc->ni_flit_out [${endp}];\n"; + $tile_flit_in_l = $tile_flit_in_l . "\t\ttile${endp}->${ni_name}_flit_in[j] = noc->ni_flit_out [${endp}][j];\n"; + $tile_credit= $tile_credit."\ttile${endp}->${ni_name}_credit_in= noc->ni_credit_out[${endp}];\n"; + $noc_credit= $noc_credit."\tnoc->ni_credit_in[${endp}] = tile${endp}->${ni_name}_credit_out;\n"; + $noc_flit_in=$noc_flit_in."\tnoc->ni_flit_in [${endp}] = tile${endp}->${ni_name}_flit_out;\n"; + $noc_flit_in_l=$noc_flit_in_l."\t\t\tnoc->ni_flit_in [${endp}][j] = tile${endp}->${ni_name}_flit_out[j];\n"; + $noc_flit_in_wr= $noc_flit_in_wr."\tif(tile${endp}->${ni_name}_flit_out_wr) noc->ni_flit_in_wr = noc->ni_flit_in_wr | ((vluint64_t)1<<${endp});\n"; + $tile_flit_in_wr=$tile_flit_in_wr."\ttile${endp}->${ni_name}_flit_in_wr= ((noc->ni_flit_out_wr >> ${endp}) & 0x01);\n"; + $noc_flit_in_wr_l= $noc_flit_in_wr_l."\tif(tile${endp}->${ni_name}_flit_out_wr) MY_VL_SETBIT_W(noc->ni_flit_in_wr ,${endp});\n"; + $tile_flit_in_wr_l=$tile_flit_in_wr_l."\ttile${endp}->${ni_name}_flit_in_wr= (VL_BITISSET_W(noc->ni_flit_out_wr,${endp})>0);\n"; + $tile_eval=$tile_eval."\ttile${endp}->eval();\n"; + $tile_final=$tile_final."\ttile${endp}->final();\n"; + foreach my $intfc (@intfcs){ + my $key=($intfc eq 'plug:clk[0]')? 'clk' : + ($intfc eq 'plug:reset[0]')? 'reset': + ($intfc eq 'plug:enable[0]')? 'en' : + ($intfc eq 'socket:RxD_sim[0]')? 'rxd': + 'other'; + + my @ports=$soc_top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); + $tile_reset=$tile_reset."\t\ttile${endp}->$p=reset;\n" if $key eq 'reset'; + $tile_clk=$tile_clk."\t\ttile${endp}->$p=clk;\n" if $key eq 'clk'; + $tile_en=$tile_en."\t\ttile${endp}->$p=enable;\n" if $key eq 'en'; ; + $top_port_info="$top_port_info $type $range tile${endp}->$p \n"; + }#ports + + if($key eq 'rxd'){ + my @ports=$soc_top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); + my @q =split (/RxD_ready_si/,$p); + $rxds{$endp.$id}{p}=$q[0] if( defined $q[1]); + $rxds{$endp.$id}{top}="tile$endp" if( defined $q[1]); + } + } + }#interface + $tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_r_addr=$r_addr; // noc->er_addr[${endp}];\n"; + $tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_e_addr=$e_addr;\n"; + }else{ + #this tile is not connected to any ip. the noc input ports will be connected to ground + $tmp_reg.="\tunsigned char tmp1 [1024]={0};\n \tunsigned char tmp2 [1024]={0};"; + $tile_chans.="\n // Tile:$endp ($e_addr) is not assigned to any ip. Connet coresponding chan to ground.\n"; + $tile_chans.="\ttile_chan_out[$endp] = tmp1;\n\ttile_chan_in[$endp] = tmp2;\n"; + } + } + my ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir); + my $include2=""; + $include2 .= '#include "RxDsim.h" // Header file for sending charactor to UART from STDIN' if($rxd_num > 0); + my $main_c=get_license_header("testbench.cpp"); $main_c="$main_c #include #include @@ -2704,14 +2196,14 @@ sub gen_verilator_mpsoc_testbench { #define CHAN_SIZE sizeof(tile0->ni_chan_in) #define conect_r2r(T1,r1,p1,T2,r2,p2) \\ - memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE ) + memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE ) #define connect_r2gnd(T,r,p)\\ - memset(&router##T [r]->chan_in [p],0x00,CHAN_SIZE) + memset(&router##T [r]->chan_in [p],0x00,CHAN_SIZE) #define connect_r2e(T,r,p,e) \\ - memcpy(&router##T [r]->chan_in[p], tile_chan_out[e], CHAN_SIZE );\\ - memcpy(tile_chan_in[e], &router##T [r]->chan_out[p], CHAN_SIZE ) + memcpy(&router##T [r]->chan_in[p], tile_chan_out[e], CHAN_SIZE );\\ + memcpy(tile_chan_in[e], &router##T [r]->chan_out[p], CHAN_SIZE ) @@ -2728,291 +2220,253 @@ sub gen_verilator_mpsoc_testbench { void connect_clk_reset_en_all(void){ - //clk,reset,enable + //clk,reset,enable $tile_reset -$tile_clk +$tile_clk $tile_en - connect_routers_reset_clk(); + connect_routers_reset_clk(); } void sim_eval_all(void){ - routers_eval(); + routers_eval(); $tile_eval } void sim_final_all(void ){ - routers_final(); -$tile_final -} + routers_final(); +$tile_final +} void clk_posedge_event(void) { - clk = 1; // Toggle clock - // you can change the inputs and read the outputs here in case they are captured at posedge of clock - $rxd_wr_cal - connect_clk_reset_en_all(); - sim_eval_all(); + clk = 1; // Toggle clock + // you can change the inputs and read the outputs here in case they are captured at posedge of clock + $rxd_wr_cal + connect_clk_reset_en_all(); + sim_eval_all(); } void clk_negedge_event(void){ - clk = 0; - topology_connect_all_nodes (); - connect_clk_reset_en_all(); - sim_eval_all(); -} + clk = 0; + topology_connect_all_nodes (); + connect_clk_reset_en_all(); + sim_eval_all(); +} int main(int argc, char** argv) { - int i,j,x,y; - $rxd_info - Verilated::commandArgs(argc, argv); // Remember args - Vrouter_new(); // Create instance - + int i,j,x,y; + $rxd_info + Verilated::commandArgs(argc, argv); // Remember args + Vrouter_new(); // Create instance + $newinst - - /******************** - * initialize input - *********************/ - $tile_chans - - reset=1; - enable=1; - topology_init(); - - $no_connected - + + /******************** + * initialize input + *********************/ + $tile_chans + + reset=1; + enable=1; + topology_init(); + + $no_connected + $tile_addr - main_time=0; - printf(\"Start Simulation\\n\"); - while (!Verilated::gotFinish()) { - $rxd_cap_cal - if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle - if (main_time >= 10 ) reset=0; - - clk_posedge_event( ); - //The valus of all registers and input ports valuse change @ posedge of the clock. Once clk is deasserted, as multiple modules are connected inside the testbench we need several eval for propogating combinational logic values - //between modules when the clock . - for (i=0;i<2*(SMART_MAX+1);i++) clk_negedge_event( ); - - main_time++; - }//while - - // Simulation is done - sim_final_all(); + main_time=0; + printf(\"Start Simulation\\n\"); + while (!Verilated::gotFinish()) { + $rxd_cap_cal + if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle + if (main_time >= 10 ) reset=0; + + clk_posedge_event( ); + //The valus of all registers and input ports valuse change @ posedge of the clock. Once clk is deasserted, as multiple modules are connected inside the testbench we need several eval for propogating combinational logic values + //between modules when the clock . + for (i=0;i<2*(SMART_MAX+1);i++) clk_negedge_event( ); + + main_time++; + }//while + + // Simulation is done + sim_final_all(); } double sc_time_stamp () { // Called by \$time in Verilog - return main_time; + return main_time; } - + "; - save_file("$dir/parameter.h",$parameter_h); - save_file("$dir/testbench.cpp",$main_c); + save_file("$dir/parameter.h",$parameter_h); + save_file("$dir/testbench.cpp",$main_c); } - - sub soc_get_all_parameters { - my $soc=shift; - my @instances=$soc->soc_get_all_instances(); - - my %all_param; - foreach my $id (@instances){ - - my $module =$soc->soc_get_module($id); - my $category =$soc->soc_get_category($id); - my $inst = $soc->soc_get_instance_name($id); - my %params = $soc->soc_get_module_param($id); - my %params_type = $soc->soc_get_module_param_type($id); - my $ip = ip->lib_new (); - my @param_order=$soc->soc_get_instance_param_order($id); - - foreach my $p (sort keys %params){ - my $inst_param= "$inst\_$p"; - #add instance name to parameter value - $params{$p}=add_instantc_name_to_parameters(\%params,$inst,$params{$p}); - my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p); - - $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); - if ($vfile_param_type eq "Localparam"){ - my $type = $params_type{$p}; - $type = "Localparam" if (! defined $type); - $vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam"; - } - - #$vfile_param_type= "Parameter" if ($vfile_param_type eq 1); - #$vfile_param_type= "Localparam" if ($vfile_param_type eq 0); - $all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" ); - #print"$all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq \"Parameter\" || $vfile_param_type eq \"Localparam\" ); \n"; - } - } - return %all_param; + my $soc=shift; + my @instances=$soc->soc_get_all_instances(); + my %all_param; + foreach my $id (@instances){ + + my $module =$soc->soc_get_module($id); + my $category =$soc->soc_get_category($id); + my $inst = $soc->soc_get_instance_name($id); + my %params = $soc->soc_get_module_param($id); + my %params_type = $soc->soc_get_module_param_type($id); + my $ip = ip->lib_new (); + my @param_order=$soc->soc_get_instance_param_order($id); + foreach my $p (sort keys %params){ + my $inst_param= "$inst\_$p"; + #add instance name to parameter value + $params{$p}=add_instantc_name_to_parameters(\%params,$inst,$params{$p}); + my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p); + + $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); + if ($vfile_param_type eq "Localparam"){ + my $type = $params_type{$p}; + $type = "Localparam" if (! defined $type); + $vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam"; + } + #$vfile_param_type= "Parameter" if ($vfile_param_type eq 1); + #$vfile_param_type= "Localparam" if ($vfile_param_type eq 0); + $all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" ); + #print"$all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq \"Parameter\" || $vfile_param_type eq \"Localparam\" ); \n"; + } + } + return %all_param; } sub soc_get_all_parameters_order { - my $soc=shift; - my @instances=$soc->soc_get_all_instances(); - my $ip = ip->lib_new (); - my @all_order; - foreach my $id (@instances){ - my $module =$soc->soc_get_module($id); - my $category =$soc->soc_get_category($id); - my $inst = $soc->soc_get_instance_name($id); - my @order = $soc->soc_get_instance_param_order($id); - my %params_type = $soc->soc_get_module_param_type($id); - foreach my $p ( @order){ - my $inst_param= "$inst\_$p"; - my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p); - $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); - if ($vfile_param_type eq "Localparam"){ - my $type = $params_type{$p}; - $type = "Localparam" if (! defined $type); - $vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam"; - } - #$vfile_param_type= "Parameter" if ($vfile_param_type eq 1); - #$vfile_param_type= "Localparam" if ($vfile_param_type eq 0); - push(@all_order, $inst_param) if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" ); - } - } - return @all_order; + my $soc=shift; + my @instances=$soc->soc_get_all_instances(); + my $ip = ip->lib_new (); + my @all_order; + foreach my $id (@instances){ + my $module =$soc->soc_get_module($id); + my $category =$soc->soc_get_category($id); + my $inst = $soc->soc_get_instance_name($id); + my @order = $soc->soc_get_instance_param_order($id); + my %params_type = $soc->soc_get_module_param_type($id); + foreach my $p ( @order){ + my $inst_param= "$inst\_$p"; + my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p); + $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); + if ($vfile_param_type eq "Localparam"){ + my $type = $params_type{$p}; + $type = "Localparam" if (! defined $type); + $vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam"; + } + #$vfile_param_type= "Parameter" if ($vfile_param_type eq 1); + #$vfile_param_type= "Localparam" if ($vfile_param_type eq 0); + push(@all_order, $inst_param) if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" ); + } + } + return @all_order; } - - sub gen_modelsim_soc_testbench { - my ($self,$name,$top,$target_dir,$tview)=@_; - my $dir="$target_dir/Modelsim"; - my $soc_top= $self->object_get_attribute('top_ip',undef); - - my @intfcs=$soc_top->top_get_intfc_list(); - my %PP; - my $top_port_def="// ${name}.v IO definition \n"; - my $pin_assign; - my $rst_inputs=''; - - - - - #add functions - my $project_dir = get_project_dir(); - open my $file1, "<", "$project_dir/mpsoc/perl_gui/lib/verilog/functions.v" or die; - my $functions_all=''; - while (my $f1 = readline ($file1)) { - $functions_all="$functions_all $f1 "; - } - close($file1); - - #get parameters - my $params_v=""; - my $n= $self->object_get_attribute('soc_name',undef); - - if(defined $n){ #we are compiling a single tile as SoC - my $core_id= $self->object_get_attribute('global_param','CORE_ID'); - my $sw_loc = $self->object_get_attribute('global_param','SW_LOC'); - - $params_v="\tlocalparam\tCORE_ID=$core_id; + my ($self,$name,$top,$target_dir,$tview)=@_; + my $dir="$target_dir/Modelsim"; + my $soc_top= $self->object_get_attribute('top_ip',undef); + my @intfcs=$soc_top->top_get_intfc_list(); + my %PP; + my $top_port_def="// ${name}.v IO definition \n"; + my $pin_assign; + my $rst_inputs=''; + #add functions + my $project_dir = get_project_dir(); + open my $file1, "<", "$project_dir/mpsoc/perl_gui/lib/verilog/functions.v" or die; + my $functions_all=''; + while (my $f1 = readline ($file1)) { + $functions_all="$functions_all $f1 "; + } + close($file1); + #get parameters + my $params_v=""; + my $n= $self->object_get_attribute('soc_name',undef); + if(defined $n){ #we are compiling a single tile as SoC + my $core_id= $self->object_get_attribute('global_param','CORE_ID'); + my $sw_loc = $self->object_get_attribute('global_param','SW_LOC'); + + $params_v="\tlocalparam\tCORE_ID=$core_id; \tlocalparam\tSW_LOC=\"$sw_loc\";\n"; - my %params=soc_get_all_parameters($self); - my @order= soc_get_all_parameters_order($self); - foreach my $p (@order){ - add_text_to_string(\$params_v,"\tlocalparam $p = $params{$p};\n") if(defined $params{$p} ); - } - }else{ # we are simulating a mpsoc - $params_v= gen_socs_param($self); - - - } - - foreach my $intfc (@intfcs){ - my $key= ( $intfc eq 'plug:clk[0]')? 'clk' : - ( $intfc eq 'plug:reset[0]')? 'reset': - ( $intfc eq 'plug:enable[0]')? 'en' : 'other'; - my $key1="${key}1"; - my $key0="${key}0"; - - my @ports=$soc_top->top_get_intfc_ports_list($intfc); - my $f=1; - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); - - $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} $p=1;\n" : "$p=1;\n"; - $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} $p=0;\n" : "$p=0;\n"; - - - if (length($range)!=0){ -# #replace parameter with their values # -# my @a= split (/\b/,$range); -# print "a=@a\n"; -# foreach my $l (@a){ -# my $value=$params{$l}; -# if(defined $value){ -# chomp $value; -# ($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l}); -# print "($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l}); \n"; -# } -# } - $range = "[ $range ]" ; - } - - - - - - if($type eq 'input'){ - $top_port_def="$top_port_def reg $range $p;\n" - }else{ - $top_port_def="$top_port_def wire $range $p;\n" - } - - - - - - - - - $pin_assign=(defined $pin_assign)? "$pin_assign,\n\t\t.$p($p)": "\t\t.$p($p)"; - $rst_inputs= "$rst_inputs $p=0;\n" if ($key eq 'other' && $type eq 'input' ); - } - - - } -my $global_localparam=get_golal_param_v(); + my %params=soc_get_all_parameters($self); + my @order= soc_get_all_parameters_order($self); + foreach my $p (@order){ + add_text_to_string(\$params_v,"\tlocalparam $p = $params{$p};\n") if(defined $params{$p} ); + } + }else{ # we are simulating a mpsoc + $params_v= gen_socs_param($self); + } + foreach my $intfc (@intfcs){ + my $key= ( $intfc eq 'plug:clk[0]')? 'clk' : + ( $intfc eq 'plug:reset[0]')? 'reset': + ( $intfc eq 'plug:enable[0]')? 'en' : 'other'; + my $key1="${key}1"; + my $key0="${key}0"; + my @ports=$soc_top->top_get_intfc_ports_list($intfc); + my $f=1; + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p); + + $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} $p=1;\n" : "$p=1;\n"; + $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} $p=0;\n" : "$p=0;\n"; + if (length($range)!=0){ +# #replace parameter with their values # +# my @a= split (/\b/,$range); +# print "a=@a\n"; +# foreach my $l (@a){ +# my $value=$params{$l}; +# if(defined $value){ +# chomp $value; +# ($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l}); +# print "($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l}); \n"; +# } +# } + $range = "[ $range ]" ; + } + if($type eq 'input'){ + $top_port_def="$top_port_def reg $range $p;\n" + }else{ + $top_port_def="$top_port_def wire $range $p;\n" + } + $pin_assign=(defined $pin_assign)? "$pin_assign,\n\t\t.$p($p)": "\t\t.$p($p)"; + $rst_inputs= "$rst_inputs $p=0;\n" if ($key eq 'other' && $type eq 'input' ); + } + } +my $global_localparam=get_golal_param_v(); my $test_v= get_license_header("testbench.v"); my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); #if(defined $mpsoc_name){ - if(0){ - - - my $top_ip=ip_gen->top_gen_new(); - my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + if(0){ + my $top_ip=ip_gen->top_gen_new(); + my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; my $hw_dir = "$target_dir/src_verilog"; my $sw_dir = "$target_dir/sw"; - my ($socs_v,$io_short,$io_full,$top_io_short,$top_io_full,$top_io_pass,$href)=gen_socs_v($self,$top_ip,$sw_dir,$tview); - my $socs_param= gen_socs_param($self); - my $global_localparam=get_golal_param_v(); - my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($self); - - + my ($socs_v,$io_short,$io_full,$top_io_short,$top_io_full,$top_io_pass,$href)=gen_socs_v($self,$top_ip,$sw_dir,$tview); + my $socs_param= gen_socs_param($self); + my $global_localparam=get_golal_param_v(); + my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($self); + $test_v.=" $clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port -`timescale 1ns/1ps +`timescale 1ns/1ps module testbench; $functions_all -$global_localparam +$global_localparam $socs_param @@ -3029,45 +2483,45 @@ sub gen_modelsim_soc_testbench { } -$test_v ="$test_v +$test_v ="$test_v -`timescale 1ns/1ps +`timescale 1ns/1ps module testbench; $functions_all $global_localparam - + $params_v $top_port_def - $name uut ( + $name uut ( $pin_assign - ); + ); //clock defination initial begin - forever begin - #5 $PP{clk0} - #5 $PP{clk1} - end + forever begin + #5 $PP{clk0} + #5 $PP{clk1} + end end initial begin - // reset $name module at the start up - $PP{reset1} - $PP{en1} - $rst_inputs - // deasert the reset after 200 ns - #200 - $PP{reset0} + // reset $name module at the start up + $PP{reset1} + $PP{en1} + $rst_inputs + // deasert the reset after 200 ns + #200 + $PP{reset0} - // write your testbench here + // write your testbench here @@ -3076,136 +2530,102 @@ sub gen_modelsim_soc_testbench { endmodule "; - save_file("$dir/testbench.v",$test_v); + save_file("$dir/testbench.v",$test_v); - + } sub verilator_testbench{ - my ($self,$name,$top,$target_dir,$vendor)=@_; - my $verilator="$target_dir/verilator"; - my $dir="$verilator"; - - my ($app,$table,$tview,$window) = software_main($dir,'testbench.cpp'); - - my $n= $self->object_get_attribute('soc_name',undef); - if(defined $n){ #we are compiling a single tile as SoC - gen_verilator_soc_testbench (@_) if((-f "$dir/testbench.cpp")==0); - } - else { # we are compiling a complete NoC-based mpsoc - gen_verilator_mpsoc_testbench (@_,$tview) if((-f "$dir/testbench.cpp")==0); - - } - - #copy makefile - #copy("../script/verilator_soc_make", "$verilator/obj_dir/Makefile"); - - - - - - my $make = def_image_button('icons/gen.png','Compile'); - my $regen=def_image_button('icons/refresh.png','Regenerate Testbench.cpp'); - my $run = def_image_button('icons/run.png','Run'); - my $back=def_image_button('icons/left.png','Previous'); - - - - $table->attach ($back,1,2,1,2,'shrink','shrink',0,0); - $table->attach ($regen,3,4,1,2,'shrink','shrink',0,0); - $table->attach ($make,6, 7, 1,2,'shrink','shrink',0,0); - $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0); - - $back-> signal_connect("clicked" => sub{ - - $window->destroy; - verilator_compilation_win($self,$name,$top,$target_dir,$vendor); - - }); - - $regen-> signal_connect("clicked" => sub{ - my $response = yes_no_dialog("Are you sure you want to regenerate the testbench.cpp file? Note that any changes you have made will be lost"); - if ($response eq 'yes') { - my $n= $self->object_get_attribute('soc_name',undef); - if(defined $n){ #we are compiling a single tile as SoC - gen_verilator_soc_testbench ($self,$name,$top,$target_dir); - } - else { # we are compiling a complete NoC-based mpsoc - gen_verilator_mpsoc_testbench ($self,$name,$top,$target_dir,$tview); - - } - - $app->refresh_source("$dir/testbench.cpp"); - } - }); - - - $make -> signal_connect("clicked" => sub{ - $make->hide; - my $load= show_gif("icons/load.gif"); - $table->attach ($load,8, 9, 1,2,'shrink','shrink',0,0); - $table->show_all; - $app->ask_to_save_changes(); - copy("$dir/testbench.cpp", "$verilator/obj_dir/testbench.cpp"); - copy("$dir/parameter.h", "$verilator/obj_dir/parameter.h") if(-f "$dir/parameter.h"); - copy("$dir/RxDsim.h", "$verilator/obj_dir/RxDsim.h") if(-f "$dir/RxDsim.h"); - - my $tops_ref=$self->object_get_attribute('verilator','libs'); - my %tops=%{$tops_ref}; - my $lib_num=0; - my $cpu_num = $self->object_get_attribute('compile', 'cpu_num'); - $cpu_num = 1 if (!defined $cpu_num); - add_colored_info($tview,"Makefie will use the maximum number of $cpu_num core(s) in parallel for compilation\n",'green'); - my $length=scalar (keys %tops); - my $cmd=""; - foreach my $top (sort keys %tops) { - $cmd.= "lib$lib_num & "; - $lib_num++; - if( $lib_num % $cpu_num == 0 || $lib_num == $length){ - $cmd.="wait\n"; - run_make_file("$verilator/obj_dir/",$tview,$cmd); - $cmd=""; - }else { - $cmd.=" make "; - } - } - - - #foreach my $top (sort keys %tops) { - # run_make_file("$verilator/obj_dir/",$tview,"lib$lib_num"); - # $lib_num++; - #} - - - - run_make_file("$verilator/obj_dir/",$tview,"sim"); - $load->destroy; - $make->show_all; - - }); - - $run -> signal_connect("clicked" => sub{ - my $bin="$verilator/obj_dir/testbench"; - if (-f $bin){ - my $cmd= "cd \"$verilator/obj_dir/\" \n xterm -e bash -c \"$bin; sleep 5\""; - add_info($tview,"$cmd\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - add_colored_info($tview,"$stderr\n",'red'); - }else { - add_info($tview,"$stdout\n"); - } - - }else{ - add_colored_info($tview,"Cannot find $bin executable binary file! make sure you have compiled the testbench successfully\n", 'red') - } - - }); - - + my ($self,$name,$top,$target_dir,$vendor)=@_; + my $verilator="$target_dir/verilator"; + my $dir="$verilator"; + + my ($app,$table,$tview,$window) = software_main($dir,'testbench.cpp'); + + my $n= $self->object_get_attribute('soc_name',undef); + if(defined $n){ #we are compiling a single tile as SoC + gen_verilator_soc_testbench (@_) if((-f "$dir/testbench.cpp")==0); + } + else { # we are compiling a complete NoC-based mpsoc + gen_verilator_mpsoc_testbench (@_,$tview) if((-f "$dir/testbench.cpp")==0); + } + #copy makefile + #copy("../script/verilator_soc_make", "$verilator/obj_dir/Makefile"); + my $make = def_image_button('icons/gen.png','Compile'); + my $regen=def_image_button('icons/refresh.png','Regenerate Testbench.cpp'); + my $run = def_image_button('icons/run.png','Run'); + my $back=def_image_button('icons/left.png','Previous'); + $table->attach ($back,1,2,1,2,'shrink','shrink',0,0); + $table->attach ($regen,3,4,1,2,'shrink','shrink',0,0); + $table->attach ($make,6, 7, 1,2,'shrink','shrink',0,0); + $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0); + $back-> signal_connect("clicked" => sub{ + $window->destroy; + verilator_compilation_win($self,$name,$top,$target_dir,$vendor); + }); + + $regen-> signal_connect("clicked" => sub{ + my $response = yes_no_dialog("Are you sure you want to regenerate the testbench.cpp file? Note that any changes you have made will be lost"); + if ($response eq 'yes') { + my $n= $self->object_get_attribute('soc_name',undef); + if(defined $n){ #we are compiling a single tile as SoC + gen_verilator_soc_testbench ($self,$name,$top,$target_dir); + } + else { # we are compiling a complete NoC-based mpsoc + gen_verilator_mpsoc_testbench ($self,$name,$top,$target_dir,$tview); + } + $app->refresh_source("$dir/testbench.cpp"); + } + }); + $make -> signal_connect("clicked" => sub{ + $make->hide; + my $load= show_gif("icons/load.gif"); + $table->attach ($load,8, 9, 1,2,'shrink','shrink',0,0); + $table->show_all; + $app->ask_to_save_changes(); + copy("$dir/testbench.cpp", "$verilator/obj_dir/testbench.cpp"); + copy("$dir/parameter.h", "$verilator/obj_dir/parameter.h") if(-f "$dir/parameter.h"); + copy("$dir/RxDsim.h", "$verilator/obj_dir/RxDsim.h") if(-f "$dir/RxDsim.h"); + my $tops_ref=$self->object_get_attribute('verilator','libs'); + my %tops=%{$tops_ref}; + my $lib_num=0; + my $cpu_num = $self->object_get_attribute('compile', 'cpu_num'); + $cpu_num = 1 if (!defined $cpu_num); + add_colored_info($tview,"Makefie will use the maximum number of $cpu_num core(s) in parallel for compilation\n",'green'); + my $length=scalar (keys %tops); + my $cmd=""; + foreach my $top (sort keys %tops) { + $cmd.= "lib$lib_num & "; + $lib_num++; + if( $lib_num % $cpu_num == 0 || $lib_num == $length){ + $cmd.="wait\n"; + run_make_file("$verilator/obj_dir/",$tview,$cmd); + $cmd=""; + }else { + $cmd.=" make "; + } + } + run_make_file("$verilator/obj_dir/",$tview,"sim"); + $load->destroy; + $make->show_all; + + }); + $run -> signal_connect("clicked" => sub{ + my $bin="$verilator/obj_dir/testbench"; + if (-f $bin){ + my $cmd= "cd \"$verilator/obj_dir/\" \n xterm -e bash -c \"$bin; sleep 5\""; + add_info($tview,"$cmd\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + add_colored_info($tview,"$stderr\n",'red'); + }else { + add_info($tview,"$stdout\n"); + } + }else{ + add_colored_info($tview,"Cannot find $bin executable binary file! make sure you have compiled the testbench successfully\n", 'red') + } + }); } - - -1; +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/simulator.pl b/mpsoc/perl_gui/lib/perl/simulator.pl index acf1de6..aab51aa 100755 --- a/mpsoc/perl_gui/lib/perl/simulator.pl +++ b/mpsoc/perl_gui/lib/perl/simulator.pl @@ -1246,7 +1246,6 @@ sub run_synthetic_simulation { extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); - } $cmds=""; @@ -1262,12 +1261,13 @@ sub run_synthetic_simulation { } - sub extract_st_by_name{ - my($st_name, $stdout)=@_; - + my($st_name, $stdout)=@_; my @results = split($st_name,$stdout); my %statistcs; + if (!defined $results[1]){ + print " Warning: was not able to capture $st_name results in simulation output\n"; + } my @lines = split("\n",$results[1]); my @names; my $i=0; @@ -1306,14 +1306,9 @@ sub extract_st_by_name{ sub extract_and_update_noc_sim_statistic { - my ($simulate,$sample,$ratio_in,$stdout)=@_; - - - + my ($simulate,$sample,$ratio_in,$stdout)=@_; my $total_time =capture_number_after("Simulation clock cycles:",$stdout); - my %statistcs = extract_st_by_name("Endpoints Statistics:",$stdout); - return if (!defined $statistcs{"total"}{'avg_latency_pck'}); update_result($simulate,$sample,"latency_result",$ratio_in,$statistcs{"total"}{'avg_latency_pck'}); update_result($simulate,$sample,"latency_flit_result",$ratio_in,$statistcs{"total"}{'avg_latency_flit'}); @@ -1341,7 +1336,7 @@ sub extract_and_update_noc_sim_statistic { my %st2 = extract_st_by_name("Endp_to_Endp pck_num:",$stdout); update_result($simulate,$sample,"endp-endp-pck_result",$ratio_in,\%st2); - my %st3 = extract_st_by_name("Routers' statistics:",$stdout); + my %st3 = extract_st_by_name("Routers Statistics:",$stdout); foreach my $p (sort keys %st3){ update_result($simulate,$sample,"flit_per_router_result",$ratio_in,$p,$st3{$p}{'flit_in'}); update_result($simulate,$sample,"packet_per_router_result",$ratio_in,$p,$st3{$p}{'pck_in'}); @@ -1354,10 +1349,9 @@ sub extract_and_update_noc_sim_statistic { } #my $p= $simulate->object_get_attribute ($sample,"noc_info"); - # my $TOPOLOGY=$p->{"TOPOLOGY"}; + # my $TOPOLOGY=$p->{"TOPOLOGY"}; #print "$TOPOLOGY\n"; - } @@ -1384,15 +1378,15 @@ sub run_task_simulation{ my $out_path ="$ENV{PRONOC_WORK}/simulate/"; for (my $i=0; $i<$num; $i++){ - my $f=$simulate->object_get_attribute($sample,"traffic_file$i"); - add_info($info, "Run $bin for $f file \n"); - my $cmd="$bin -c $SIM_CLOCK_LIMIT -f \"$f\" > $out_path/sim_out$i & "; - $cmds .=$cmd; - add_info($info, "$cmd \n"); - $jobs++; - push (@paralel_ratio,$i); - $c++; - if($jobs % $cpu_num ==0 || $jobs == $total){ + my $f=$simulate->object_get_attribute($sample,"traffic_file$i"); + add_info($info, "Run $bin for $f file \n"); + my $cmd="$bin -c $SIM_CLOCK_LIMIT -f \"$f\" > $out_path/sim_out$i & "; + $cmds .=$cmd; + add_info($info, "$cmd \n"); + $jobs++; + push (@paralel_ratio,$i); + $c++; + if($jobs % $cpu_num ==0 || $jobs == $total){ #run paralle simulation my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmds\n wait\n"); #print "($stdout,$exit,$stderr)\n"; @@ -1401,11 +1395,8 @@ sub run_task_simulation{ $simulate->object_add_attribute ($sample,"status","failed"); $simulate->object_add_attribute('status',undef,'ideal'); return; - } - + } - - #save results for (my $j=0; $j<$c; $j++){ my $r = $paralel_ratio[$j]; @@ -1426,7 +1417,7 @@ sub run_task_simulation{ $c=0; set_gui_status($simulate,"ref",2); } - + }#for i $simulate->object_add_attribute ($sample,"status","done"); @@ -1506,10 +1497,8 @@ sub run_trace_simulation{ $simulate->object_add_attribute ($sample,"status","failed"); $simulate->object_add_attribute('status',undef,'ideal'); return; - } - + } - $stdout = load_file("$out_path/sim_out"); my @errors = unix_grep("$out_path/sim_out","ERROR:"); if (scalar @errors ){ @@ -1518,12 +1507,12 @@ sub run_trace_simulation{ $simulate->object_add_attribute('status',undef,'ideal'); return; } - + extract_and_update_noc_sim_statistic ($simulate,$sample,0,$stdout); - + set_gui_status($simulate,"ref",2); - + $simulate->object_add_attribute ($sample,"status","done"); } @@ -1590,7 +1579,7 @@ sub check_sim_sample{ my $HW_PCK_TYPE=$p->{"PCK_TYPE"}; my $SIM_MIN_PCK_SIZE=$self->object_get_attribute ($sample,"MIN_PCK_SIZE"); my $SIM_MAX_PCK_SIZE=$self->object_get_attribute ($sample,"MAX_PCK_SIZE"); - if(!defined $HW_MIN_PCK_SIZE){ + if(!defined $HW_MIN_PCK_SIZE){ $HW_MIN_PCK_SIZE= 2; #print "undef\n"; } diff --git a/mpsoc/rtl/src_modelsim/noc_sim_statistic.sv b/mpsoc/rtl/src_modelsim/noc_sim_statistic.sv index ba2ede4..1ad946a 100755 --- a/mpsoc/rtl/src_modelsim/noc_sim_statistic.sv +++ b/mpsoc/rtl/src_modelsim/noc_sim_statistic.sv @@ -1,129 +1,116 @@ -// synthesis translate_off -`timescale 1ns/1ns `include "pronoc_def.v" +`ifdef SIMULATION + module routers_statistic_collector #( - parameter NOC_ID=0 + parameter NOC_ID=0 )( - reset, - clk, - router_event, - print + reset, + clk, + router_event, + print ); - - `NOC_CONF - - input clk,reset; - input router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - input print; - - typedef struct { - integer pck_num_in; - integer flit_num_in; - integer pck_num_out; - integer flit_num_out; - integer flit_num_in_bypassed; - integer flit_num_in_buffered; - integer bypass_counter [SMART_NUM : 0]; - } router_stat_t; - - - - task reset_router_stat; - output router_stat_t stat_in; - integer k; - begin - stat_in.pck_num_in=0; - stat_in.flit_num_in=0; - stat_in.pck_num_out=0; - stat_in.flit_num_out=0; - stat_in.flit_num_in_bypassed=0; - stat_in.flit_num_in_buffered=0; - for (k=0;k0) for (k=0;k0) for (k=0;k0) for (k=0;k0) for (k=0;k latency) begin + rsvd_stat.min_latency = latency; + end + `ifdef STND_DEV_EN + rsvd_stat.sum_clk_pow2 += real'(clk_num_h2h) * real'(clk_num_h2h); + `endif + end + endtask + + task print_endp_to_endp_st(string st); + $write("\n\tEndp_to_Endp %s:\n\t#EID,", st); + // Print header row + for (int src = 0; src < NE; src++) + $write("%0d,", src); + $display(""); + // Print data rows + for (int src = 0; src < NE; src++) begin + $write("\t%0d,", src); + for (int dst = 0; dst < NE; dst++) begin + if (st == "pck_num") + $write("%0d,", endp_to_endp[src][dst].pck_num); + else if (st == "flit_num") + $write("%0d,", endp_to_endp[src][dst].flit_num); + end + $display(""); + end + endtask + + task update_send_st ( + inout statistic_t sent_stat, + input int latency + ); + begin + sent_stat.worst_latency = (sent_stat.worst_latency < latency) ? latency : sent_stat.worst_latency; + if ((sent_stat.min_latency == 0) || (sent_stat.min_latency > latency)) begin + sent_stat.min_latency = latency; + end + end + endtask + + initial begin + reset_st (rsvd_stat_total); + reset_st (sent_stat_total); + for(m=0;m1) sent_stat [core_num][flit_out_class[core_num]].flit_num++; - else sent_stat [core_num][0].flit_num++; - if(chan_in_all[core_num].flit_chanel.flit[Fw-1])begin - total_sent_pck_num+=1; - if (C>1) sent_stat [core_num][flit_out_class[core_num]].pck_num++; - else sent_stat [core_num][0].pck_num++; - - end - end - - if(chan_out_all[core_num].flit_chanel.flit_wr)begin - total_rsv_flit_number+=1; - if (C>1) rsvd_stat [core_num][pck_class_out[core_num]].flit_num++; - else rsvd_stat [core_num][0].flit_num++; - end - - - if( update [core_num] ) begin - total_rsv_pck_num = total_rsv_pck_num+1; - - if (AVG_LATENCY_METRIC == "HEAD_2_TAIL") - update_statistic ( - core_num, - pck_class_out[core_num], - $itor(time_stamp_h2h[core_num]), - $itor(time_stamp_h2t[core_num]), - src_id[core_num], - time_stamp_h2t[core_num], - distance[core_num] - ); - else - update_statistic ( - core_num, - pck_class_out[core_num], - $itor(time_stamp_h2h[core_num]), - $itor(time_stamp_h2t[core_num]), - src_id[core_num], - time_stamp_h2h[core_num], - distance[core_num] - ); - - - if((total_rsv_pck_num & 'hffff )==0 ) $display(" packet received total=%0d",total_rsv_pck_num); - sum_clk_h2h += time_stamp_h2h[core_num]; - sum_clk_h2t += time_stamp_h2t[core_num]; - `ifdef STND_DEV_EN - sum_clk_pow2+=time_stamp_h2h[core_num] * time_stamp_h2h[core_num]; - sum_clk_pow2_per_class[pck_class_out[core_num]]+=time_stamp_h2h[core_num] * time_stamp_h2h[core_num]; - `endif - if(distance[core_num] > 0) sum_clk_per_hop+= $itor(time_stamp_h2h[core_num])/$itor(distance[core_num]); - total_rsv_pck_num_per_class[pck_class_out[core_num]]+=1; - sum_clk_h2h_per_class[pck_class_out[core_num]]+=time_stamp_h2h[core_num] ; - sum_clk_h2t_per_class[pck_class_out[core_num]]+=time_stamp_h2t[core_num] ; - if(distance[core_num]>0) sum_clk_per_hop_per_class[pck_class_out[core_num]]+= $itor(time_stamp_h2h[core_num])/$itor(distance[core_num]); - rsvd_core_total_rsv_pck_num[core_num]+=1; - if (rsvd_core_worst_delay[core_num] < time_stamp_h2t[core_num]) rsvd_core_worst_delay[core_num] = ( AVG_LATENCY_METRIC == "HEAD_2_TAIL")? time_stamp_h2t[core_num] : time_stamp_h2h[core_num]; - if (sent_core_worst_delay[src_id[core_num]] < time_stamp_h2t[core_num]) sent_core_worst_delay[src_id[core_num]] = (AVG_LATENCY_METRIC == "HEAD_2_TAIL")? time_stamp_h2t[core_num] : time_stamp_h2h[core_num]; - if (pck_size_o[core_num] >= MIN_PACKET_SIZE && pck_size_o[core_num] <=MAX_PACKET_SIZE) rsv_size_array[pck_size_o[core_num]-MIN_PACKET_SIZE] = rsv_size_array[pck_size_o[core_num]-MIN_PACKET_SIZE]+1; - - - end - end - end//always - - + end + end + + function integer addrencode; + input integer pos,k,n,kw; + integer pow,i,tmp;begin + addrencode=0; + pow=1; + for (i = 0; i 1)? pck_class_out[core_num] : 0; + if(chan_in_all[core_num].flit_chanel.flit_wr)begin + total_sent_flit_number+=1; + if (CAST_TYPE != "UNICAST") total_expect_rsv_flit_num+=mcast_dst_num[core_num]; + else total_expect_rsv_flit_num++; + if (C>1) sent_stat [core_num][flit_out_class[core_num]].flit_num++; + else sent_stat [core_num][0].flit_num++; + if(chan_in_all[core_num].flit_chanel.flit[Fw-1])begin + total_sent_pck_num+=1; + if (C>1) sent_stat [core_num][flit_out_class[core_num]].pck_num++; + else sent_stat [core_num][0].pck_num++; + end + end + if(chan_out_all[core_num].flit_chanel.flit_wr)begin + total_rsv_flit_number+=1; + endp_to_endp[src_tmp][core_num].flit_num++; + rsvd_stat [core_num][class_tmp].flit_num++; + end + if( update [core_num] ) begin + total_rsv_pck_num = total_rsv_pck_num+1; + latency_tmp =(AVG_LATENCY_METRIC == "HEAD_2_TAIL")? + time_stamp_h2t[core_num]:time_stamp_h2h[core_num]; + update_rsvd_st( + rsvd_stat[core_num][class_tmp], + $itor(time_stamp_h2h[core_num]),//clk_num_h2h, + $itor(time_stamp_h2t[core_num]),//clk_num_h2t, + latency_tmp, + distance[core_num] + ); + update_send_st( + sent_stat[src_tmp][class_tmp], + latency_tmp + ); + update_rsvd_st( + endp_to_endp[src_tmp][core_num], + $itor(time_stamp_h2h[core_num]),//clk_num_h2h, + $itor(time_stamp_h2t[core_num]),//clk_num_h2t, + latency_tmp, + distance[core_num] + ); + if((total_rsv_pck_num & 'hffff )==0 ) $display(" packet received total=%0d",total_rsv_pck_num); + sum_clk_h2h += time_stamp_h2h[core_num]; + sum_clk_h2t += time_stamp_h2t[core_num]; + `ifdef STND_DEV_EN + sum_clk_pow2+=time_stamp_h2h[core_num] * time_stamp_h2h[core_num]; + sum_clk_pow2_per_class[pck_class_out[core_num]]+=time_stamp_h2h[core_num] * time_stamp_h2h[core_num]; + `endif + if(distance[core_num] > 0) sum_clk_per_hop+= $itor(time_stamp_h2h[core_num])/$itor(distance[core_num]); + total_rsv_pck_num_per_class[pck_class_out[core_num]]+=1; + sum_clk_h2h_per_class[pck_class_out[core_num]]+=time_stamp_h2h[core_num] ; + sum_clk_h2t_per_class[pck_class_out[core_num]]+=time_stamp_h2t[core_num] ; + if(distance[core_num]>0) sum_clk_per_hop_per_class[pck_class_out[core_num]]+= $itor(time_stamp_h2h[core_num])/$itor(distance[core_num]); + rsvd_core_total_rsv_pck_num[core_num]+=1; + if (rsvd_core_worst_delay[core_num] < time_stamp_h2t[core_num]) rsvd_core_worst_delay[core_num] = ( AVG_LATENCY_METRIC == "HEAD_2_TAIL")? time_stamp_h2t[core_num] : time_stamp_h2h[core_num]; + if (sent_core_worst_delay[src_id[core_num]] < time_stamp_h2t[core_num]) sent_core_worst_delay[src_id[core_num]] = (AVG_LATENCY_METRIC == "HEAD_2_TAIL")? time_stamp_h2t[core_num] : time_stamp_h2h[core_num]; + if (pck_size_o[core_num] >= MIN_PACKET_SIZE && pck_size_o[core_num] <=MAX_PACKET_SIZE) rsv_size_array[pck_size_o[core_num]-MIN_PACKET_SIZE] = rsv_size_array[pck_size_o[core_num]-MIN_PACKET_SIZE]+1; + end + end + end//always - - - integer rsv_ideal_cnt,total_rsv_flit_number_old; - reg all_done_reg; - wire all_done_in; - assign all_done_in = (clk_counter > STOP_SIM_CLK) || ( total_sent_pck_num > STOP_PCK_NUM ); - assign sent_done = all_done_in & ~ all_done_reg; - - always @(`pronoc_clk_reset_edge)begin - if (`pronoc_reset) begin - all_done_reg <= 1'b0; - rsv_ideal_cnt<=0; - done<=1'b0; - total_rsv_flit_number_old<=0; - end else begin - all_done_reg <= all_done_in; - total_rsv_flit_number_old<=total_rsv_flit_number; - if(all_done_in) begin //All injectors stopped injecting packets - if(total_rsv_flit_number_old==total_rsv_flit_number) rsv_ideal_cnt<=rsv_ideal_cnt+1;//count the number of cycle when no flit is received by any injector - else rsv_ideal_cnt=0; - if(total_expect_rsv_flit_num == total_rsv_flit_number) begin // All injected packets are consumed - done<=1'b1; - end - if(rsv_ideal_cnt >= 100) begin // Injectors stopped sending packets, number of received and sent flits are not equal yet and for 100 cycles no flit is consumed. - done<=1'b1; - #100 $display ("ERROR: The number of expected (%d) & received flits (%d) were not equal at the end of simulation",total_expect_rsv_flit_num ,total_rsv_flit_number); - - $stop; - end - end - end - end - - initial total_active_endp=0; - - - real avg_throughput,avg_latency_flit,avg_latency_pck,std_dev,avg_latency_per_hop,min_avg_latency_per_class; - - - initial begin - for(m=0;m0) total_active_endp = total_active_endp +1; - end - - avg_throughput= ((total_sent_flit_number*100)/total_active_endp )/clk_counter; - avg_latency_flit =sum_clk_h2h/$itor(total_rsv_pck_num); - avg_latency_pck =sum_clk_h2t/$itor(total_rsv_pck_num); - avg_latency_per_hop = sum_clk_per_hop/$itor(total_rsv_pck_num); - $display("simulation results-------------------"); - $display("\tSimulation clock cycles:%0d",clk_counter); - - print_router_st=1'b1; - #1 - -/* - $display(" total sent/received packets:%d/%d",total_sent_pck_num,total_rsv_pck_num); - $display(" total sent/received flits:%d/%d",total_sent_flit_number,total_rsv_flit_number); - $display(" Total active Endpoint: %d \n",total_active_endp); - $display(" Avg throughput is: %f (flits/clk/Total active Endpoint %%)", avg_throughput); - - - - $display("\nall : "); - $display(" Total number of packet = %d \n average latency per hop = %f ",total_rsv_pck_num,avg_latency_per_hop); - $display(" average packet latency = %f \n average flit latency = %f ",avg_latency_pck, avg_latency_flit); -*/ - $display("\n\tTotal injected packet in different size:"); - $write("\tflit_size,"); - for (m=0;m<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);m++) begin - if(rsv_size_array[m]>0)$write("%0d,",m+ MIN_PACKET_SIZE); - end - $write("\n\t#pck,"); - for (m=0;m<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);m++) begin - if(rsv_size_array[m]>0)$write("%0d,",rsv_size_array[m]); - end - - // if(ratio==RATIO_INIT) first_avg_latency_flit=avg_latency_flit; - //`ifdef STND_DEV_EN - //std_dev= standard_dev( sum_clk_pow2,total_rsv_pck_num, avg_latency_flit); - //$display(" standard_dev = %f",std_dev); - //`endif - $display("\n\n\tEndpoints' statistics"); - $write("\t#node,sent_stat.pck_num,rsvd_stat.pck_num,sent_stat.flit_num,rsvd_stat.flit_num,sent_stat.worst_latency,rsvd_stat.worst_latency,sent_stat.min_latency,rsvd_stat.min_latency,avg_latency_per_hop,avg_latency_flit,avg_latency_pck,avg_throughput(%%),avg_pck_size,"); -`ifdef STND_DEV_EN - $write("avg.std_dev"); -`endif - $write("\n"); - - for (m=0; m1) begin - merge_statistic (rsvd_stat_per_class[c],rsvd_stat[m][c],rsvd_stat_per_class[c]); - merge_statistic (sent_stat_per_class[c],sent_stat[m][c],sent_stat_per_class[c]); - end - end - end - - - - for (m=0; m1)begin - for (c=0; c1) begin - print_st_single (clk_counter, rsvd_stat_class[m],sent_stat_class[m] ); - end else begin - print_st_single (clk_counter, rsvd_stat[m][0],sent_stat[m][0] ); - end + reg all_done_reg; + wire all_done_in; + assign all_done_in = (clk_counter > STOP_SIM_CLK) || ( total_sent_pck_num > STOP_PCK_NUM ); + assign sent_done = all_done_in & ~ all_done_reg; + + always @(`pronoc_clk_reset_edge)begin + if (`pronoc_reset) begin + all_done_reg <= 1'b0; + rsv_ideal_cnt<=0; + done<=1'b0; + total_rsv_flit_number_old<=0; + end else begin + all_done_reg <= all_done_in; + total_rsv_flit_number_old<=total_rsv_flit_number; + if(all_done_in) begin //All injectors stopped injecting packets + if(total_rsv_flit_number_old==total_rsv_flit_number) rsv_ideal_cnt<=rsv_ideal_cnt+1;//count the number of cycle when no flit is received by any injector + else rsv_ideal_cnt=0; + if(total_expect_rsv_flit_num == total_rsv_flit_number) begin // All injected packets are consumed + done<=1'b1; + end + if(rsv_ideal_cnt >= 100) begin // Injectors stopped sending packets, number of received and sent flits are not equal yet and for 100 cycles no flit is consumed. + done<=1'b1; + #100 $display ("ERROR: The number of expected (%d) & received flits (%d) were not equal at the end of simulation",total_expect_rsv_flit_num ,total_rsv_flit_number); + + $stop; + end + end + end + end + + initial total_active_endp=0; + real avg_throughput,avg_latency_flit,avg_latency_pck,std_dev,avg_latency_per_hop,min_avg_latency_per_class; + + initial begin + for(m=0;m0)? ((total_rsv_pck_num_per_class[m]*AVG_PCK_SIZ*100)/total_active_endp )/clk_counter:0; - avg_latency_flit = (total_rsv_pck_num_per_class[m]>0)? sum_clk_h2h_per_class[m]/total_rsv_pck_num_per_class[m]:0; - avg_latency_pck = (total_rsv_pck_num_per_class[m]>0)? sum_clk_h2t_per_class[m]/total_rsv_pck_num_per_class[m]:0; - avg_latency_per_hop = (total_rsv_pck_num_per_class[m]>0)? sum_clk_per_hop_per_class[m]/total_rsv_pck_num_per_class[m]:0; - if(AVG_LATENCY_METRIC == "HEAD_2_TAIL") begin - $display ("\nclass : %d ",m); - $display (" Total number of packet = %d \n avg_throughput = %f \n average latency per hop = %f \n average latency = %f",total_rsv_pck_num_per_class[m],avg_throughput,avg_latency_per_hop,avg_latency_pck); - - end else begin - - $display ("\nclass : %d ",m); - $display (" Total number of packet = %d \n avg_throughput = %f \n average latency per hop = %f \n average latency = %f",total_rsv_pck_num_per_class[m],avg_throughput,avg_latency_per_hop,avg_latency_flit); - end - if(min_avg_latency_per_class > avg_latency_flit) min_avg_latency_per_class=avg_latency_flit; - - //#if (STND_DEV_EN) - //std_dev= (total_rsv_pck_num_per_class[i]>0)? standard_dev( sum_clk_pow2_per_class[i],total_rsv_pck_num_per_class[i], avg_latency_flit):0; - // sprintf(file_name,"%s_std%u.txt",out_file_name,i); - // update_file( file_name,avg_throughput,std_dev); - - //#endif - end//for - - - - for (m=0;m0) $display ("\ttraffic percentage of class 0 is : %0d", C0_p); - if(C>1) $display ("\ttraffic percentage of class 1 is : %0d", C1_p); - if(C>2) $display ("\ttraffic percentage of class 2 is : %0d", C2_p); - if(C>3) $display ("\ttraffic percentage of class 3 is : %0d", C3_p); - if(TRAFFIC == "HOTSPOT")begin - //$display ("\tHot spot percentage: %u\n", HOTSPOT_PERCENTAGE); - $display ("\tNumber of hot spot cores: %0d", HOTSPOT_NODE_NUM); - end - if (CAST_TYPE != "UNICAST")begin - $display ("\tMULTICAST traffic ratio: %d(%%), min: %d, max: %d\n", MCAST_TRAFFIC_RATIO,MCAST_PCK_SIZ_MIN,MCAST_PCK_SIZ_MAX); - end - - - - //$display ("\tTotal packets sent by one router: %u\n", TOTAL_PKT_PER_ROUTER); - $display ("\tSimulation timeout =%0d", STOP_SIM_CLK); - $display ("\tSimulation ends on total packet num of =%0d", STOP_PCK_NUM); - $display ("\tPacket size (min,max,average) in flits: (%0d,%0d,%0d)",MIN_PACKET_SIZE,MAX_PACKET_SIZE,AVG_PCK_SIZ); - $display ("\tPacket injector FIFO width in flit:%0d\n\n",TIMSTMP_FIFO_NUM); - $display ("\tFlit injection ratio per router is =%f (flits/clk/Total Endpoint %%)",ratio); - - $display ("Simulation parameters-------------"); - - end//initial - - - - - - task update_statistic; - input integer core_num; - input [Cw-1 : 0] class_num; - input real clk_num_h2h; - input real clk_num_h2t; - input [NEw-1 : 0] src; - input real latency; - input [DISTw-1 :0] distance ; - begin - - - if(C>1) begin - - rsvd_stat[core_num][class_num].pck_num ++; - rsvd_stat[core_num][class_num].sum_clk_h2h +=clk_num_h2h; - rsvd_stat[core_num][class_num].sum_clk_h2t +=clk_num_h2t; - rsvd_stat[core_num][class_num].sum_clk_per_hop+= (clk_num_h2h/$itor(distance)); - if (rsvd_stat[core_num][class_num].worst_latency < latency ) rsvd_stat[core_num][class_num].worst_latency =latency; - if (rsvd_stat[core_num][class_num].min_latency==0 ) rsvd_stat[core_num][class_num].min_latency =latency; - if (rsvd_stat[core_num][class_num].min_latency > latency ) rsvd_stat[core_num][class_num].min_latency =latency; - if (sent_stat[src ][class_num].worst_latency < latency ) sent_stat[src ][class_num].worst_latency =latency; - if (sent_stat[src ][class_num].min_latency==0 ) sent_stat[src ][class_num].min_latency =latency; - if (sent_stat[src ][class_num].min_latency > latency ) sent_stat[src ][class_num].min_latency =latency; - - `ifdef STND_DEV_EN - rsvd_stat[core_num][class_num].sum_clk_pow2 += clk_num_h2h * clk_num_h2h; - `endif - end else begin - rsvd_stat[core_num][0].pck_num ++; - rsvd_stat[core_num][0].sum_clk_h2h +=clk_num_h2h; - rsvd_stat[core_num][0].sum_clk_h2t +=clk_num_h2t; - if(distance>0) rsvd_stat[core_num][0].sum_clk_per_hop+= (clk_num_h2h/$itor(distance)); - if (rsvd_stat[core_num][0].worst_latency < latency ) rsvd_stat[core_num][0].worst_latency=latency; - if (rsvd_stat[core_num][0].min_latency==0 ) rsvd_stat[core_num][0].min_latency =latency; - if (rsvd_stat[core_num][0].min_latency > latency ) rsvd_stat[core_num][0].min_latency =latency; - if (sent_stat[src ][0].worst_latency < latency ) sent_stat[src ][0].worst_latency=latency; - if (sent_stat[src ][0].min_latency==0 ) sent_stat[src ][0].min_latency =latency; - if (sent_stat[src ][0].min_latency > latency ) sent_stat[src ][0].min_latency =latency; - - `ifdef STND_DEV_EN - rsvd_stat[core_num][0].sum_clk_pow2 += clk_num_h2h * clk_num_h2h; - `endif - end - - end - endtask - - - - - task merge_statistic; - input statistic_t merge_stat; - input statistic_t stat_in; - output statistic_t stat_out; - begin - stat_out.pck_num = merge_stat.pck_num+stat_in.pck_num; - stat_out.flit_num = merge_stat.flit_num+stat_in.flit_num; - if(merge_stat.worst_latency < stat_in.worst_latency) stat_out.worst_latency= stat_in.worst_latency; - if(merge_stat.min_latency == 0 ) stat_out.min_latency = stat_in.min_latency; - if(merge_stat.min_latency > stat_in.min_latency && stat_in.min_latency!=0 ) stat_out.min_latency = stat_in.min_latency; - stat_out.sum_clk_h2h = merge_stat.sum_clk_h2h +stat_in.sum_clk_h2h ; - stat_out.sum_clk_h2t = merge_stat.sum_clk_h2t +stat_in.sum_clk_h2t ; - stat_out.sum_clk_per_hop = merge_stat.sum_clk_per_hop +stat_in.sum_clk_per_hop; - `ifdef STND_DEV_EN - stat_out.sum_clk_pow2 = merge_stat.sum_clk_pow2 +stat_in.sum_clk_pow2; - `endif - - end - endtask - - - - - - - task print_st_single; - input [CLK_CNTw-1 : 0]total_clk; - input statistic_t rsvd_stat; - input statistic_t sent_stat; - begin - - - - avg_st_t avg; - finilize_statistic (total_clk, rsvd_stat, avg); - - $write("%0d,",sent_stat.pck_num); - $write("%0d,",rsvd_stat.pck_num); - $write("%0d,",sent_stat.flit_num); - $write("%0d,",rsvd_stat.flit_num); - $write("%0d,",sent_stat.worst_latency); - $write("%0d,",rsvd_stat.worst_latency); - $write("%0d,",sent_stat.min_latency); - $write("%0d,",rsvd_stat.min_latency); - $write("%f,",avg.avg_latency_per_hop); - $write("%f,",avg.avg_latency_flit); - $write("%f,",avg.avg_latency_pck); - $write("%f,",avg.avg_throughput); - $write("%f,",avg.avg_pck_siz); - `ifdef STND_DEV_EN - $write("%f,",avg.std_dev); - `endif - $write("\n"); - // printf("\n"); - end - endtask - - - - task finilize_statistic; - input [CLK_CNTw-1 : 0]total_clk; - input statistic_t rsvd_stat; - output avg_st_t avg_statistic; - begin - - - avg_statistic.avg_throughput = ($itor(rsvd_stat.flit_num*100)/NE )/total_clk; - avg_statistic.avg_latency_flit =(rsvd_stat.pck_num>0)? rsvd_stat.sum_clk_h2h/rsvd_stat.pck_num : 0; - avg_statistic.avg_latency_pck = (rsvd_stat.pck_num>0)? rsvd_stat.sum_clk_h2t/rsvd_stat.pck_num :0; - avg_statistic.avg_latency_per_hop = ( rsvd_stat.pck_num==0)? 0 : rsvd_stat.sum_clk_per_hop/rsvd_stat.pck_num; - avg_statistic.avg_pck_siz = ( rsvd_stat.pck_num==0)? 0 : $itor(rsvd_stat.flit_num) / $itor(rsvd_stat.pck_num); - `ifdef STND_DEV_EN - standard_dev( rsvd_stat.sum_clk_pow2,rsvd_stat.pck_num, avg_statistic.avg_latency_flit,avg_statistic.std_dev); - `endif - end - endtask - - - - `ifdef STND_DEV_EN - /************************ - * std_dev = sqrt[(B-A^2/N)/N] = sqrt [(B/N)- (A/N)^2] = sqrt [B/N - mean^2] - * A = sum of the values - * B = sum of the squarded values - * *************/ - - task standard_dev; - input real sum_pow2; - input [PCK_CNTw-1 :0] total_num; - input real average; - output real std_dev; - begin - /* - double A, B, N; - N= total_num; - A= average * N; - B= sum_pow2; - - A=(A*A)/N; - std_dev = (B-A)/N; - std_dev = sqrt(std_dev); - */ - if(total_num==0) std_dev= 0; - else begin - std_dev = sum_pow2/$itor(total_num); //B/N - std_dev -= (average*average);// (B/N) - mean^2 - std_dev = $sqrt(std_dev);// sqrt [B/N - mean^2] - - end - end - endtask - - `endif - - - - /* - start_delay_gen #( - .NC(NE) - ) - delay_gen - ( - .clk(clk), - .reset(reset), - .start_i(start), - .start_o(start_o) - ); - */ - - - routers_statistic_collector #( - .NOC_ID(NOC_ID) - ) router_stat ( - .reset(reset), - .clk(clk), - .router_event(router_event), - .print(print_router_st) - ); - + + initial print_router_st=1'b0; + + //report + always @( posedge done) begin + for (core_num=0; core_num0) total_active_endp = total_active_endp +1; + end + avg_throughput= ((total_sent_flit_number*100)/total_active_endp )/clk_counter; + avg_latency_flit =sum_clk_h2h/$itor(total_rsv_pck_num); + avg_latency_pck =sum_clk_h2t/$itor(total_rsv_pck_num); + avg_latency_per_hop = sum_clk_per_hop/$itor(total_rsv_pck_num); + $display("\nsimulation results-------------------"); + $display("\tSimulation clock cycles:%0d",clk_counter); + $display("\n\tTotal received packet in different size:"); + $write("\tflit_size,"); + for (m=0;m<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);m++) begin + if(rsv_size_array[m]>0)$write("%0d,",m+ MIN_PACKET_SIZE); + end + $write("\n\t#pck,"); + for (m=0;m<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);m++) begin + if(rsv_size_array[m]>0)$write("%0d,",rsv_size_array[m]); + end + print_router_st=1'b1; + #1 + // if(ratio==RATIO_INIT) first_avg_latency_flit=avg_latency_flit; + //`ifdef STND_DEV_EN + //std_dev= standard_dev( sum_clk_pow2,total_rsv_pck_num, avg_latency_flit); + //$display(" standard_dev = %f",std_dev); + //`endif + print_endp_to_endp_st("pck_num"); + print_endp_to_endp_st("flit_num"); + $display("\n\n\tEndpoints Statistics:"); + $write("\t#EID,sent_stat.pck_num,rsvd_stat.pck_num,sent_stat.flit_num,rsvd_stat.flit_num,sent_stat.worst_latency,rsvd_stat.worst_latency,sent_stat.min_latency,rsvd_stat.min_latency,avg_latency_per_hop,avg_latency_flit,avg_latency_pck,avg_throughput(%%),avg_pck_size,"); + `ifdef STND_DEV_EN + $write("avg.std_dev"); + `endif + $write("\n"); + for (m=0; m1) begin + merge_statistic (rsvd_stat_per_class[c],rsvd_stat[m][c],rsvd_stat_per_class[c]); + merge_statistic (sent_stat_per_class[c],sent_stat[m][c],sent_stat_per_class[c]); + end + end + end + for (m=0; m1)begin + for (c=0; c1) begin + print_st_single (clk_counter, rsvd_stat_class[m],sent_stat_class[m] ); + end else begin + print_st_single (clk_counter, rsvd_stat[m][0],sent_stat[m][0] ); + end + end + end //always + + initial begin + display_noc_parameters(); + $display ("Simulation parameters-------------"); + if(DEBUG_EN) + $display ("\tDebuging is enabled"); + else + $display ("\tDebuging is disabled"); + //if( AVG_LATENCY_METRIC == "HEAD_2_TAIL") $display ("\tOutput is the average latency on sending the packet header until receiving tail"); + //else $display ("\tOutput is the average latency on sending the packet header until receiving header flit at destination node"); + $display ("\tTraffic pattern:%s",TRAFFIC); + if(C>0) $display ("\ttraffic percentage of class 0 is : %0d", C0_p); + if(C>1) $display ("\ttraffic percentage of class 1 is : %0d", C1_p); + if(C>2) $display ("\ttraffic percentage of class 2 is : %0d", C2_p); + if(C>3) $display ("\ttraffic percentage of class 3 is : %0d", C3_p); + if(TRAFFIC == "HOTSPOT")begin + //$display ("\tHot spot percentage: %u\n", HOTSPOT_PERCENTAGE); + $display ("\tNumber of hot spot cores: %0d", HOTSPOT_NODE_NUM); + end + if (CAST_TYPE != "UNICAST")begin + $display ("\tMULTICAST traffic ratio: %d(%%), min: %d, max: %d\n", MCAST_TRAFFIC_RATIO,MCAST_PCK_SIZ_MIN,MCAST_PCK_SIZ_MAX); + end + //$display ("\tTotal packets sent by one router: %u\n", TOTAL_PKT_PER_ROUTER); + $display ("\tSimulation timeout =%0d", STOP_SIM_CLK); + $display ("\tSimulation ends on total packet num of =%0d", STOP_PCK_NUM); + $display ("\tPacket size (min,max,average) in flits: (%0d,%0d,%0d)",MIN_PACKET_SIZE,MAX_PACKET_SIZE,AVG_PCK_SIZ); + $display ("\tPacket injector FIFO width in flit:%0d",TIMSTMP_FIFO_NUM); + $display ("\tFlit injection ratio per router is =%f (flits/clk/Total Endpoint %%)",ratio); + $display ("Simulation parameters-------------"); + end//initial + + task merge_statistic; + input statistic_t merge_stat; + input statistic_t stat_in; + output statistic_t stat_out; + begin + stat_out.pck_num = merge_stat.pck_num+stat_in.pck_num; + stat_out.flit_num = merge_stat.flit_num+stat_in.flit_num; + if(merge_stat.worst_latency < stat_in.worst_latency) stat_out.worst_latency= stat_in.worst_latency; + if(merge_stat.min_latency == 0 ) stat_out.min_latency = stat_in.min_latency; + if(merge_stat.min_latency > stat_in.min_latency && stat_in.min_latency!=0 ) stat_out.min_latency = stat_in.min_latency; + stat_out.sum_clk_h2h = merge_stat.sum_clk_h2h +stat_in.sum_clk_h2h ; + stat_out.sum_clk_h2t = merge_stat.sum_clk_h2t +stat_in.sum_clk_h2t ; + stat_out.sum_clk_per_hop = merge_stat.sum_clk_per_hop +stat_in.sum_clk_per_hop; + `ifdef STND_DEV_EN + stat_out.sum_clk_pow2 = merge_stat.sum_clk_pow2 +stat_in.sum_clk_pow2; + `endif + end + endtask + + task print_st_single; + input [CLK_CNTw-1 : 0]total_clk; + input statistic_t rsvd_stat; + input statistic_t sent_stat; + begin + avg_st_t avg; + finilize_statistic (total_clk, rsvd_stat, avg); + $write("%0d,",sent_stat.pck_num); + $write("%0d,",rsvd_stat.pck_num); + $write("%0d,",sent_stat.flit_num); + $write("%0d,",rsvd_stat.flit_num); + $write("%0d,",sent_stat.worst_latency); + $write("%0d,",rsvd_stat.worst_latency); + $write("%0d,",sent_stat.min_latency); + $write("%0d,",rsvd_stat.min_latency); + $write("%f,",avg.avg_latency_per_hop); + $write("%f,",avg.avg_latency_flit); + $write("%f,",avg.avg_latency_pck); + $write("%f,",avg.avg_throughput); + $write("%f,",avg.avg_pck_siz); + `ifdef STND_DEV_EN + $write("%f,",avg.std_dev); + `endif + $write("\n"); + end + endtask + + task finilize_statistic; + input [CLK_CNTw-1 : 0]total_clk; + input statistic_t rsvd_stat; + output avg_st_t avg_statistic; + begin + avg_statistic.avg_throughput = ($itor(rsvd_stat.flit_num*100)/NE )/total_clk; + avg_statistic.avg_latency_flit =(rsvd_stat.pck_num>0)? rsvd_stat.sum_clk_h2h/rsvd_stat.pck_num : 0; + avg_statistic.avg_latency_pck = (rsvd_stat.pck_num>0)? rsvd_stat.sum_clk_h2t/rsvd_stat.pck_num :0; + avg_statistic.avg_latency_per_hop = ( rsvd_stat.pck_num==0)? 0 : rsvd_stat.sum_clk_per_hop/rsvd_stat.pck_num; + avg_statistic.avg_pck_siz = ( rsvd_stat.pck_num==0)? 0 : $itor(rsvd_stat.flit_num) / $itor(rsvd_stat.pck_num); + `ifdef STND_DEV_EN + standard_dev( rsvd_stat.sum_clk_pow2,rsvd_stat.pck_num, avg_statistic.avg_latency_flit,avg_statistic.std_dev); + `endif + end + endtask + + `ifdef STND_DEV_EN + /************************ + * std_dev = sqrt[(B-A^2/N)/N] = sqrt [(B/N)- (A/N)^2] = sqrt [B/N - mean^2] + * A = sum of the values + * B = sum of the squarded values + * *************/ + task standard_dev; + input real sum_pow2; + input [PCK_CNTw-1 :0] total_num; + input real average; + output real std_dev; + begin + /* + double A, B, N; + N= total_num; + A= average * N; + B= sum_pow2; + A=(A*A)/N; + std_dev = (B-A)/N; + std_dev = sqrt(std_dev); + */ + if(total_num==0) std_dev= 0; + else begin + std_dev = sum_pow2/$itor(total_num); //B/N + std_dev -= (average*average);// (B/N) - mean^2 + std_dev = $sqrt(std_dev);// sqrt [B/N - mean^2] + end + end + endtask + `endif + + /* + start_delay_gen #( + .NC(NE) + ) + delay_gen + ( + .clk(clk), + .reset(reset), + .start_i(start), + .start_o(start_o) + ); + */ + + routers_statistic_collector #( + .NOC_ID(NOC_ID) + ) router_stat ( + .reset(reset), + .clk(clk), + .router_event(router_event), + .print(print_router_st) + ); + endmodule -// synthesis translate_on - +`endif \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 6a9421b..5d10393 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -225,7 +225,7 @@ module input_queue_per_port #( PORT_B = port_buffer_size(SW_LOC), PORT_Bw= log2(PORT_B), //PORT_IVC is equal to V if HETERO_VC=0 - PORT_IVC = port_hetero_vc_num(ROUTER_ID, SW_LOC); + PORT_IVC = hetero_ivc_decimal(ROUTER_ID, SW_LOC); localparam VV = V * V, diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index 094ccde..d9aafc0 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -252,22 +252,31 @@ package pronoc_pkg; } smartflit_chanel_t; localparam SMARTFLIT_CHANEL_w = $bits(smartflit_chanel_t); - function automatic integer port_hetero_vc_num; + function automatic integer hetero_ivc_decimal; input integer router_id; input integer router_port_num; //router port num begin - port_hetero_vc_num = + `ifdef NO_HETRO_IVC + // This macro (`NO_HETRO_IVC) generates identical router RTL code for a NoC. + // All input ports will have the maximum number of virtual channels (VCs), + // but the redundant VCs are not utilized. + // This is useful for simulations with long compilation times (e.g., using Verilator). + // Not recommended for synthesis; intended for simulation purposes only. + hetero_ivc_decimal = V; + `else + hetero_ivc_decimal = (HETERO_VC == 0) ? V : (HETERO_VC == 1) ? VC_CONFIG_TABLE [router_id][0] : - VC_CONFIG_TABLE [router_id][router_port_num]; + VC_CONFIG_TABLE [router_id][router_port_num]; + `endif end endfunction - function automatic logic [V-1 : 0] port_hetero_vc_presence; + function automatic logic [V-1 : 0] hetero_ovc_unary; input integer router_id; input integer router_port_num; //router port num begin - port_hetero_vc_presence = + hetero_ovc_unary = (HETERO_VC == 0) ? {V{1'b1}} : (HETERO_VC == 1) ? (1 << VC_CONFIG_TABLE [router_id][0]) - 1 : (1 << VC_CONFIG_TABLE [router_id][router_port_num]) -1; diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 30dd096..1e6a494 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -183,7 +183,7 @@ module router_two_stage #( assign ctrl_out[i].neighbors_r_addr = current_r_addr; assign ctrl_out[i].endp_port =1'b0; - assign ctrl_out[i].hetero_ovc_presence= port_hetero_vc_presence(current_r_id,i); + assign ctrl_out[i].hetero_ovc_presence= hetero_ovc_unary(current_r_id,i); assign chan_out[i].flit= flit_out_all [(i+1)*Fw-1: i*Fw]; assign chan_out[i].flit_wr= flit_out_wr_all [i]; diff --git a/mpsoc/src_verilator/simulator.cpp b/mpsoc/src_verilator/simulator.cpp index 2fd0c34..ef458e8 100755 --- a/mpsoc/src_verilator/simulator.cpp +++ b/mpsoc/src_verilator/simulator.cpp @@ -7,28 +7,19 @@ #include #include #include // Defines common routines - #include "Vtraffic.h" #include "Vpck_inj.h" #include #include #include - - #include #include #include - - #include "simulator.h" - - - int main(int argc, char** argv) { char change_injection_ratio=0; int i,j,x,y;//,report_delay_counter=0; - char deafult_out[] = {"result"}; NEw=Log2(NE); for(i=0;inum_nodes); @@ -72,19 +56,16 @@ int main(int argc, char** argv) { synful_init(synful_file,synful_SSExit,synful_random_seed,sim_end_clk_num,end_sim_pck_num); } else traffic_gen_init(); - - - + main_time=0; print_parameter(); if( thread_num>1) initial_threads(); - + while (!Verilated::gotFinish()) { if(main_time - saved_time < 50) {//set reset and start reset_active_high = ((router1[0]->router_event[0] & ACTIVE_HIGH_RST)!=0) ? 1 : 0; if (main_time-saved_time >= 10 ) reset = (reset_active_high)? 0 :1; else reset = reset_active_high; ;//keep system in reset - if(main_time == saved_time+21){ count_en=1; start_i=1;} if(main_time == saved_time+23) start_i=0; } @@ -92,8 +73,6 @@ int main(int argc, char** argv) { if(TRAFFIC_TYPE==NETRACE) netrace_posedge_event(); else if(TRAFFIC_TYPE ==SYNFUL) synful_posedge_event(); else traffic_clk_posedge_event(); - - //The valus of all registers and input ports valuse change @ posedge of the clock. Once clk is deasserted, as multiple modules are connected inside the testbench we need several eval for propogating combinational logic values //between modules when the clock . for (i=0;i [synthetic Traffic options]\n" " %s -f [Task options]\n" " %s -F [Netrace options] \n" @@ -196,79 +169,71 @@ bin_name,bin_name,bin_name,bin_name } - void netrace_processArgs (int argc, char **argv ) { - char c; - - /* don't want getopt to moan - I can do that just fine thanks! */ - opterr = 0; - if (argc < 2) usage(argv[0]); - while ((c = getopt (argc, argv, "F:dr:lv:T:n:s:")) != -1) - { - switch (c) - { - case 'F': - TRAFFIC_TYPE=NETRACE; - TRAFFIC=(char *) "NETRACE"; - ENDP_TYPE = PCK_INJECTOR; - netrace_file = optarg; - break; - case 'd': - ignore_dependencies=1; - break; - case 'r': + char c; + opterr = 0; + if (argc < 2) usage(argv[0]); + while ((c = getopt (argc, argv, "F:dr:lv:T:n:s:")) != -1) + { + switch (c) + { + case 'F': + TRAFFIC_TYPE=NETRACE; + TRAFFIC=(char *) "NETRACE"; + ENDP_TYPE = PCK_INJECTOR; + netrace_file = optarg; + break; + case 'd': + ignore_dependencies=1; + break; + case 'r': start_region=atoi(optarg); - break; - case 'l': - reader_throttling=1; - break; - case 'v': - verbosity= atoi(optarg); - break; - case 'T': + break; + case 'l': + reader_throttling=1; + break; + case 'v': + verbosity= atoi(optarg); + break; + case 'T': thread_num = atoi(optarg); break; - case 'n': - end_sim_pck_num=atoi(optarg); - break; - case 's': - netrace_speed_up=atoi(optarg); - - break; - case '?': - if (isprint (optopt)) - fprintf (stderr, "Unknown option `-%c'.\n", optopt); - else - fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); - default: - usage(argv[0]); - exit(1); - } + case 'n': + end_sim_pck_num=atoi(optarg); + break; + case 's': + netrace_speed_up=atoi(optarg); + break; + case '?': + if (isprint (optopt)) + fprintf (stderr, "Unknown option `-%c'.\n", optopt); + else + fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); + default: + usage(argv[0]); + exit(1); + } } } - - void synthetic_task_processArgs (int argc, char **argv ) { - char c; - int p; - int array[10]; - float f; - - /* don't want getopt to moan - I can do that just fine thanks! */ - opterr = 0; - if (argc < 2) usage(argv[0]); - while ((c = getopt (argc, argv, "t:m:n:c:i:p:h:H:f:T:u:Q")) != -1) - { - switch (c) + char c; + int p; + int array[10]; + float f; + opterr = 0; + if (argc < 2) usage(argv[0]); + while ((c = getopt (argc, argv, "t:m:n:c:i:p:h:H:f:T:u:Q")) != -1) + { + switch (c) { - case 'f': - TRAFFIC_TYPE=TASK; - TRAFFIC=(char *) "TASK"; - task_traffic_init(optarg); - break; + case 'f': + TRAFFIC_TYPE=TASK; + TRAFFIC=(char *) "TASK"; + task_traffic_init(optarg); + break; case 't': TRAFFIC=optarg; total_active_routers=-1; @@ -277,16 +242,16 @@ void synthetic_task_processArgs (int argc, char **argv ) MIN_PACKET_SIZE=atoi(optarg); break; case 'n': - end_sim_pck_num=atoi(optarg); - break; + end_sim_pck_num=atoi(optarg); + break; case 'c': - sim_end_clk_num=atoi(optarg); - break; + sim_end_clk_num=atoi(optarg); + break; case 'i': - f=atof(optarg); - f*=(MAX_RATIO/100); - ratio= (int) f; - break; + f=atof(optarg); + f*=(MAX_RATIO/100); + ratio= (int) f; + break; case 'p': p= parse_string (optarg, array); if (p==0) { @@ -303,7 +268,6 @@ void synthetic_task_processArgs (int argc, char **argv ) break; case 'm': update_pck_size(optarg); - break; case 'H': update_custom_traffic(optarg); @@ -324,69 +288,63 @@ void synthetic_task_processArgs (int argc, char **argv ) update_mcast_traffic(optarg); break; case '?': - if (isprint (optopt)) - fprintf (stderr, "Unknown option `-%c'.\n", optopt); - else - fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); + if (isprint (optopt)) + fprintf (stderr, "Unknown option `-%c'.\n", optopt); + else + fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); default: - usage(argv[0]); - exit(1); + usage(argv[0]); + exit(1); } - } + } } - - - void synful_processArgs (int argc, char **argv) { - char c; - /* don't want getopt to moan - I can do that just fine thanks! */ - opterr = 0; - if (argc < 2) usage(argv[0]); - while ((c = getopt (argc, argv, "S:c:sn:v:T:r:w:")) != -1) - { - switch (c) - { - case 'S': - TRAFFIC_TYPE=SYNFUL; - TRAFFIC=(char *) "SYNFUL"; - synful_file = optarg; - ENDP_TYPE =PCK_INJECTOR; - break; - case 'c': - sim_end_clk_num=atoi(optarg); - break; - case 's': - synful_SSExit =true; - break; - case 'n': - end_sim_pck_num=atoi(optarg); - break; - case 'v': - verbosity= atoi(optarg); - break; - case 'w': - synful_flitw= atoi(optarg); - break; - case 'T': - thread_num = atoi(optarg); - break; - case 'r': - synful_random_seed = atoi(optarg); - break; - case '?': - if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); - else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); - default: - usage(argv[0]); - exit(1); - }//switch - }//while + char c; + opterr = 0; + if (argc < 2) usage(argv[0]); + while ((c = getopt (argc, argv, "S:c:sn:v:T:r:w:")) != -1) + { + switch (c) + { + case 'S': + TRAFFIC_TYPE=SYNFUL; + TRAFFIC=(char *) "SYNFUL"; + synful_file = optarg; + ENDP_TYPE =PCK_INJECTOR; + break; + case 'c': + sim_end_clk_num=atoi(optarg); + break; + case 's': + synful_SSExit =true; + break; + case 'n': + end_sim_pck_num=atoi(optarg); + break; + case 'v': + verbosity= atoi(optarg); + break; + case 'w': + synful_flitw= atoi(optarg); + break; + case 'T': + thread_num = atoi(optarg); + break; + case 'r': + synful_random_seed = atoi(optarg); + break; + case '?': + if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); + else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); + default: + usage(argv[0]); + exit(1); + }//switch + }//while } - - int parse_string ( char * str, int * array) { int i=0; @@ -398,21 +356,15 @@ int parse_string ( char * str, int * array) i++; pt = strtok (NULL, ","); } - return i; + return i; } - - - - - unsigned int pck_dst_gen_unicast ( unsigned int core_num, unsigned char * inject_en) { if(TRAFFIC_TYPE==TASK) return pck_dst_gen_task_graph ( core_num, inject_en); if((strcmp (TOPOLOGY,"MESH")==0)||(strcmp (TOPOLOGY,"TORUS")==0)) return pck_dst_gen_2D (core_num, inject_en); return pck_dst_gen_1D (core_num, inject_en); } - void mcast_full_rnd (unsigned int core_num){ unsigned int rnd; int a; @@ -427,7 +379,6 @@ void mcast_full_rnd (unsigned int core_num){ } } - void mcast_partial_rnd (unsigned int core_num){ unsigned int rnd;int a; //printf("m[%d]=%d\n",core_num,mcast_list_array[core_num]); @@ -457,15 +408,11 @@ void mcast_partial_rnd (unsigned int core_num){ } } //this function should not come here - } - - - void pck_dst_gen ( unsigned int core_num, unsigned char * inject_en) { unsigned int dest = pck_dst_gen_unicast (core_num, inject_en); -// printf("inject_en=%u, core_num=%u, dest=%u\n",*inject_en, core_num,dest); + // printf("inject_en=%u, core_num=%u, dest=%u\n",*inject_en, core_num,dest); if(IS_UNICAST){ traffic[core_num]->dest_e_addr= dest; return; @@ -473,10 +420,8 @@ void pck_dst_gen ( unsigned int core_num, unsigned char * inject_en) { else if (*inject_en==0) return; //multicast DEST_ADDR_ASSIGN_ZERO(traffic[core_num]->dest_e_addr);//reset traffic[core_num]->dest_e_addr - unsigned int dest_id = endp_addr_decoder (dest); //*inject_en = dest_id !=core_num; - unsigned int rnd = rand() % 100; // 0~99 if(rnd >= mcast.ratio){ //send a unicast packet @@ -495,7 +440,6 @@ void pck_dst_gen ( unsigned int core_num, unsigned char * inject_en) { return; } traffic[core_num]->pck_size_in=rnd_between(mcast.min,mcast.max); - if (IS_MCAST_FULL) { mcast_full_rnd (core_num); return; @@ -504,43 +448,40 @@ void pck_dst_gen ( unsigned int core_num, unsigned char * inject_en) { mcast_partial_rnd(core_num); return; } - return; //IS_BCAST_FULL | IS_BCAST_PARTIAL traffic[core_num]->dest_e_addr=0; } - - void update_hotspot(char * str){ - int i; - int array[1000]; - int p; - int acuum=0; - hotspot_st * new_node; - p= parse_string (str, array); - if (p<4){ - fprintf(stderr,"ERROR: in hotspot traffic parameters. 4 value should be given as hotspot parameter\n"); - exit(1); - } - HOTSPOT_NUM=array[0]; - if (p<1+HOTSPOT_NUM*3){ - fprintf(stderr,"ERROR: in hotspot traffic parameters \n"); - exit(1); - } - new_node = (hotspot_st *) malloc( HOTSPOT_NUM * sizeof(hotspot_st)); - if( new_node == NULL){ - fprintf(stderr,"ERROR: cannot allocate memory for hotspot traffic\n"); - exit(1); - } - for (i=1;i<3*HOTSPOT_NUM; i+=3){ + int i; + int array[1000]; + int p; + int acuum=0; + hotspot_st * new_node; + p= parse_string (str, array); + if (p<4){ + fprintf(stderr,"ERROR: in hotspot traffic parameters. 4 value should be given as hotspot parameter\n"); + exit(1); + } + HOTSPOT_NUM=array[0]; + if (p<1+HOTSPOT_NUM*3){ + fprintf(stderr,"ERROR: in hotspot traffic parameters \n"); + exit(1); + } + new_node = (hotspot_st *) malloc( HOTSPOT_NUM * sizeof(hotspot_st)); + if( new_node == NULL){ + fprintf(stderr,"ERROR: cannot allocate memory for hotspot traffic\n"); + exit(1); + } + for (i=1;i<3*HOTSPOT_NUM; i+=3){ new_node[i/3]. ip_num = array[i]; new_node[i/3]. send_enable=array[i+1]; new_node[i/3]. percentage = acuum + array[i+2]; acuum= new_node[i/3]. percentage; - } - if(acuum> 1000){ - printf("Warning: The hotspot traffic summation %f exceed than 100 percent. \n", (float) acuum /10); - } - hotspots=new_node; + } + if(acuum> 1000){ + printf("Warning: The hotspot traffic summation %f exceed than 100 percent. \n", (float) acuum /10); + } + hotspots=new_node; } void update_mcast_traffic(char * str){ @@ -552,12 +493,9 @@ void update_mcast_traffic(char * str){ if(p>0) mcast.ratio =array[0]; if(p>1) mcast.min =array[1]; if(p>2) mcast.max =array[2]; - if (mcast.ratio > 100) { printf("ERROR: The given multicast traffic ratio (%d) is larger than 100\n",mcast.ratio); exit(1);} if (mcast.min < MIN_PCK_SIZE){ printf("ERROR: The given multicast minimum packet size (%d) is larger than %d minimum packet size supported by the NoC\n",mcast.min, MIN_PCK_SIZE); exit(1);} if (mcast.max > max_valid) { printf("ERROR: The given multicast maximum packet size (%d) is larger than %d maximum router buffer size\n",mcast.max, max_valid); exit(1);}; - - } void update_custom_traffic (char * str){ @@ -578,8 +516,6 @@ void update_pck_size(char *str){ char *pt,*pt2; MIN_PACKET_SIZE=100000; MAX_PACKET_SIZE=1; - - pt = strtok (str,","); if(*pt=='R'){//random range p= parse_string (str+2, array); @@ -587,7 +523,6 @@ void update_pck_size(char *str){ fprintf(stderr,"ERROR: Wrong Packet size format %s. It should be \"R,min,max\" : \n",str); exit(1); } - MIN_PACKET_SIZE=array[0]; MAX_PACKET_SIZE=array[1]; AVG_PACKET_SIZE=(MIN_PACKET_SIZE+MAX_PACKET_SIZE)/2;// average packet size @@ -613,52 +548,43 @@ void update_pck_size(char *str){ printf("ERROR: Memory not allocated.\n"); exit(1); } - for (i=0; i array[i]) MIN_PACKET_SIZE = array[i]; if(MAX_PACKET_SIZE < array[i]) MAX_PACKET_SIZE = array[i]; } - p= parse_string (pt2+1, array); int sum=0; AVG_PACKET_SIZE=0; for (i=0; i LB)? LB : B; - for( i = 1; i < argc; ++i ) { if( strcmp(argv[i], "-t") == 0 ) { synthetic_task_processArgs ( argc, argv ); @@ -693,7 +611,6 @@ void processArgs (int argc, char **argv ){ } else if( strcmp(argv[i], "-f") == 0 ) { synthetic_task_processArgs ( argc, argv ); return; - } else if( strcmp(argv[i], "-F") == 0 ) { netrace_processArgs (argc, argv ); return; @@ -707,23 +624,17 @@ void processArgs (int argc, char **argv ){ exit(1); } - int get_new_pck_size(){ - if(pck_size_sel == RANDOM_discrete){ - int rnd = rand() % 100; // 0~99 - int i=0; - while( rnd > discrete_prob[i] ) i++; - return discrete_size [i]; - } - //random range - return rnd_between(MIN_PACKET_SIZE,MAX_PACKET_SIZE); + if(pck_size_sel == RANDOM_discrete){ + int rnd = rand() % 100; // 0~99 + int i=0; + while( rnd > discrete_prob[i] ) i++; + return discrete_size [i]; + } + //random range + return rnd_between(MIN_PACKET_SIZE,MAX_PACKET_SIZE); } - - - - - void traffic_gen_final_report(){ int i; for (i=0;ipck_number>0) total_active_endp = total_active_endp +1; @@ -736,72 +647,67 @@ void traffic_gen_final_report(){ } printf("\n\t#pck,"); for (i=0;i<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);i++){ - if(rsv_size_array[i]>0) printf("%u,",rsv_size_array[i]); + if(rsv_size_array[i]>0) printf("%u,",rsv_size_array[i]); } printf("\n"); - // printf(" total received flits:%d\n",total_rsv_flit_number); // printf(" total sent flits:%d\n",total_sent_flit_number); print_statistic_new (clk_counter); - } - void traffic_gen_init( void ){ int i; unsigned int dest_e_addr; for (i=0;icurrent_e_addr = endp_addr_encoder(i); - traffic[i]->start=0; - traffic[i]->pck_class_in= pck_class_in_gen( i); - traffic[i]->pck_size_in=get_new_pck_size(); - pck_dst_gen (i, &inject_en); - //traffic[i]->dest_e_addr= dest_e_addr; - if(inject_en == 0) traffic[i]->stop=1; - //printf("src=%u, des_eaddr=%x, dest=%x\n", i,dest_e_addr, endp_addr_decoder(dest_e_addr)); - if(inject_done) traffic[i]->stop=1; - traffic[i]->start_delay=rnd_between(10,500); - if(TRAFFIC_TYPE==SYNTHETIC){ - //traffic[i]->avg_pck_size_in=AVG_PACKET_SIZE; - traffic[i]->ratio=ratio; - traffic[i]->init_weight=1; - } + unsigned char inject_en; + random_var[i] = 100; + traffic[i]->current_e_addr = endp_addr_encoder(i); + traffic[i]->start=0; + traffic[i]->pck_class_in= pck_class_in_gen( i); + traffic[i]->pck_size_in=get_new_pck_size(); + pck_dst_gen (i, &inject_en); + //traffic[i]->dest_e_addr= dest_e_addr; + if(inject_en == 0) traffic[i]->stop=1; + //printf("src=%u, des_eaddr=%x, dest=%x\n", i,dest_e_addr, endp_addr_decoder(dest_e_addr)); + if(inject_done) traffic[i]->stop=1; + traffic[i]->start_delay=rnd_between(10,500); + if(TRAFFIC_TYPE==SYNTHETIC){ + //traffic[i]->avg_pck_size_in=AVG_PACKET_SIZE; + traffic[i]->ratio=ratio; + traffic[i]->init_weight=1; + } } } void pck_inj_init (int model_node_num){ int i,tmp; for (i=0;icurrent_e_addr = endp_addr_encoder(i); - pck_inj[i]->pck_injct_in_ready= (0x1<pck_injct_in_pck_wr=0; + pck_inj[i]->current_e_addr = endp_addr_encoder(i); + pck_inj[i]->pck_injct_in_ready= (0x1<pck_injct_in_pck_wr=0; } std::cout << "Node mapping---------------------" << std::endl; std::cout << "\tMapping " << model_node_num << " " << TRAFFIC << " Nodes to " << NE << " ProNoC Nodes" << std::endl; std::cout << "\t" << TRAFFIC << "\tID \t<-> ProNoC ID "<< std::endl; traffic_model_mapping = (int *) malloc( model_node_num * sizeof(int)); for (i=0;i\t" << tmp << std::endl; - + //TODO mapping should be done according to number of NE and should be set by the user later + if(NE<=model_node_num){ + // we have less or equal number of injectors in traffic model thatn the number of modes in ProNoC + // So we need to map multiples injector nodes from the model to one packet injector + tmp = ((i* NE)/model_node_num); + traffic_model_mapping[i]=tmp; + } else { + // we have more endpoints that what is defined in the model + if(i\t" << tmp << std::endl; } std::cout << "Node mapping---------------------" << std::endl; } /************* * sc_time_stamp - * * **********/ double sc_time_stamp () { // Called by $time in Verilog return main_time; @@ -817,7 +723,6 @@ int pow2( int num){ volatile int * lock; unsigned int nr_per_thread=0; unsigned int ne_per_thread=0; - void thread_function (int n){ int i; unsigned int node=0; @@ -834,11 +739,9 @@ void thread_function (int n){ if( TRAFFIC_TYPE == NETRACE) pck_inj[node]->eval(); else traffic[node]->eval(); } - //router1[n]->eval(); //if( TRAFFIC_TYPE == NETRACE) pck_inj[n]->eval(); //else traffic[n]->eval(); - lock[n]=0; if(n==0) break;//first thread is the main process } @@ -858,8 +761,6 @@ class alignas(64) Vthread int ne_per_thread; // Member Functions() //Parameterized Constructor - - void function ( ){ int i; unsigned int node=0; @@ -886,7 +787,6 @@ class alignas(64) Vthread //if(router_is_active[node] | (Quick_sim_en==0)) single_router_reset_clk(node); } - //eval for(i=0;i= NE) break; @@ -921,7 +818,6 @@ class alignas(64) Vthread } copy=false; } - if(update){ for(i=0;ieval(); //if( TRAFFIC_TYPE == NETRACE) pck_inj[n]->eval(); //else traffic[n]->eval(); - - if(n==0) break;//first thread is the main process } } - Vthread(int x,int r,int e) { - n=x; nr_per_thread=r; ne_per_thread=e; - eval=false; - copy =false; - update=false; - if(n!=0) { - std::thread th {&Vthread::function,this}; - th.detach(); - } + n=x; nr_per_thread=r; ne_per_thread=e; + eval=false; + copy =false; + update=false; + if(n!=0) { + std::thread th {&Vthread::function,this}; + th.detach(); + } } - - }; Vthread ** thread; @@ -964,19 +854,15 @@ void initial_threads (void){ unsigned int ne_per_thread=0; nr_per_thread = (NR % thread_num)? (unsigned int)(NR/thread_num) + 1 : (unsigned int)(NR/thread_num); ne_per_thread = (NE % thread_num)? (unsigned int)(NE/thread_num) + 1 : (unsigned int)(NE/thread_num); - //std::vector threads(thread_num-1); //lock = new int[thread_num]; //for(i=0;i1) { @@ -997,9 +880,7 @@ void sim_eval_all (void){ thread[0]->function(); for(i=0;ieval); }else{// no thread - connect_clk_reset_start_all(); - //routers_eval(); for(i=0;i1) { for(i=0;icopy=true; @@ -1027,13 +905,11 @@ void topology_connect_all_nodes (void){ for (int n=0; nstop=1; } - sim_eval_all(); } @@ -1093,7 +966,6 @@ void update_traffic_injector_st (unsigned int i){ //printf("src=%u, dest=%x\n", i,endp_addr_decoder(dest_e_addr)); } } - if(traffic[i]->flit_out_wr==1){ total_sent_flit_number++; if (!IS_UNICAST){ @@ -1107,11 +979,9 @@ void update_traffic_injector_st (unsigned int i){ sent_stat [i].flit_num++; #endif } - if(traffic[i]->flit_in_wr==1){ total_rsv_flit_number++; } - if(traffic[i]->hdr_flit_sent==1){ total_sent_pck_num++; #if (C>1) @@ -1124,17 +994,13 @@ void update_traffic_injector_st (unsigned int i){ void update_all_traffic_injector_st(){ for (int i=0;i= end_sim_pck_num) || (clk_counter>= sim_end_clk_num) || total_active_routers == 0); @@ -1142,7 +1008,6 @@ void traffic_clk_posedge_event(void) { total_rsv_flit_number_old=total_rsv_flit_number; update_all_router_stat(); update_all_traffic_injector_st(); - if(inject_done){ if(total_rsv_flit_number_old == total_rsv_flit_number){ ideal_rsv_cnt++; @@ -1154,27 +1019,19 @@ void traffic_clk_posedge_event(void) { }else ideal_rsv_cnt=0; if(total_expect_rsv_flit_num == total_rsv_flit_number ) simulation_done=1; } - sim_eval_all(); - } - /********************************** - * * update_noc_statistic - * - * *********************************/ - void update_rsvd_st ( - statistic_t * rsvd_stat, - unsigned int clk_num_h2h, - unsigned int clk_num_h2t, - unsigned int latency, - unsigned int distance, - unsigned int pck_size - + statistic_t * rsvd_stat, + unsigned int clk_num_h2h, + unsigned int clk_num_h2t, + unsigned int latency, + unsigned int distance, + unsigned int pck_size ) { rsvd_stat->pck_num ++; rsvd_stat->flit_num+= pck_size; @@ -1193,32 +1050,26 @@ void update_sent_st ( statistic_t * sent_stat, unsigned int latency ) { - if (sent_stat->worst_latency < latency ) sent_stat->worst_latency=latency; if (sent_stat->min_latency==0 ) sent_stat->min_latency =latency; if (sent_stat->min_latency > latency ) sent_stat->min_latency =latency; - } void update_statistic_at_ejection ( - int core_num, - unsigned int clk_num_h2h, - unsigned int clk_num_h2t, - unsigned int distance, - unsigned int class_num, - unsigned int src, - unsigned int pck_size + int core_num, + unsigned int clk_num_h2h, + unsigned int clk_num_h2t, + unsigned int distance, + unsigned int class_num, + unsigned int src, + unsigned int pck_size ){ - - - if(ENDP_TYPE == TRFC_INJECTOR) { if( traffic[core_num]->pck_size_o >= MIN_PACKET_SIZE && traffic[core_num]->pck_size_o <=MAX_PACKET_SIZE){ - if(rsv_size_array!=NULL) rsv_size_array[traffic[core_num]->pck_size_o-MIN_PACKET_SIZE]++; + if(rsv_size_array!=NULL) rsv_size_array[traffic[core_num]->pck_size_o-MIN_PACKET_SIZE]++; } } - if(verbosity==0 && ( TRAFFIC_TYPE == NETRACE || TRAFFIC_TYPE ==SYNFUL)) if((total_rsv_pck_num & 0X1FFFF )==0 ) printf(" Packets recived total=%u\n",total_rsv_pck_num); unsigned int latency = (strcmp (AVG_LATENCY_METRIC,"HEAD_2_TAIL")==0)? clk_num_h2t : clk_num_h2h; #if(C>1) @@ -1228,84 +1079,70 @@ void update_statistic_at_ejection ( update_rsvd_st ( &rsvd_stat[core_num], clk_num_h2h, clk_num_h2t, latency, distance,pck_size); update_sent_st ( &sent_stat[src ], latency); #endif - update_rsvd_st ( &endp_to_endp[src][core_num], clk_num_h2h, clk_num_h2t, latency, distance, pck_size); - } - - - - void update_noc_statistic ( int core_num){ - unsigned int clk_num_h2h =traffic[core_num]->time_stamp_h2h; - unsigned int clk_num_h2t =traffic[core_num]->time_stamp_h2t; - unsigned int distance=traffic[core_num]->distance; - unsigned int class_num=traffic[core_num]->pck_class_out; - unsigned int src_e_addr=traffic[core_num]->src_e_addr; - unsigned int src = endp_addr_decoder (src_e_addr); - unsigned int pck_size = traffic[core_num]-> pck_size_o; + unsigned int clk_num_h2h =traffic[core_num]->time_stamp_h2h; + unsigned int clk_num_h2t =traffic[core_num]->time_stamp_h2t; + unsigned int distance=traffic[core_num]->distance; + unsigned int class_num=traffic[core_num]->pck_class_out; + unsigned int src_e_addr=traffic[core_num]->src_e_addr; + unsigned int src = endp_addr_decoder (src_e_addr); + unsigned int pck_size = traffic[core_num]-> pck_size_o; update_statistic_at_ejection ( core_num, clk_num_h2h, clk_num_h2t, distance, class_num, src,pck_size); - - } avg_st_t finilize_statistic (unsigned long int total_clk, statistic_t rsvd_stat){ - - avg_st_t avg_statistic; - avg_statistic.avg_throughput= ((double)(rsvd_stat.flit_num*100)/NE )/total_clk; - avg_statistic.avg_latency_flit = rsvd_stat.sum_clk_h2h/rsvd_stat.pck_num; - avg_statistic.avg_latency_pck = rsvd_stat.sum_clk_h2t/rsvd_stat.pck_num; - avg_statistic.avg_latency_per_hop = ( rsvd_stat.pck_num==0)? 0 : rsvd_stat.sum_clk_per_hop/rsvd_stat.pck_num; - avg_statistic.avg_pck_siz = ( rsvd_stat.pck_num==0)? 0 : (double)(rsvd_stat.flit_num / rsvd_stat.pck_num); - #if (STND_DEV_EN) - avg_statistic.std_dev =standard_dev( rsvd_stat.sum_clk_pow2,rsvd_stat.pck_num, avg_statistic.avg_latency_flit); - #endif - return avg_statistic; + avg_st_t avg_statistic; + avg_statistic.avg_throughput= ((double)(rsvd_stat.flit_num*100)/NE )/total_clk; + avg_statistic.avg_latency_flit = rsvd_stat.sum_clk_h2h/rsvd_stat.pck_num; + avg_statistic.avg_latency_pck = rsvd_stat.sum_clk_h2t/rsvd_stat.pck_num; + avg_statistic.avg_latency_per_hop = ( rsvd_stat.pck_num==0)? 0 : rsvd_stat.sum_clk_per_hop/rsvd_stat.pck_num; + avg_statistic.avg_pck_siz = ( rsvd_stat.pck_num==0)? 0 : (double)(rsvd_stat.flit_num / rsvd_stat.pck_num); + #if (STND_DEV_EN) + avg_statistic.std_dev =standard_dev( rsvd_stat.sum_clk_pow2,rsvd_stat.pck_num, avg_statistic.avg_latency_flit); + #endif + return avg_statistic; } template void myout(T value) { - std::cout << value << std::endl; + std::cout << value << std::endl; } + template void myout(First first, Rest ... rest) { - std::cout << first << ","; - myout(rest...); + std::cout << first << ","; + myout(rest...); } void print_st_single (unsigned long int total_clk, statistic_t rsvd_stat, statistic_t sent_stat){ - - - avg_st_t avg; avg=finilize_statistic (total_clk, rsvd_stat); - myout( - sent_stat.pck_num, - rsvd_stat.pck_num, - sent_stat.flit_num, - rsvd_stat.flit_num, - sent_stat.worst_latency, - rsvd_stat.worst_latency, - sent_stat.min_latency, - rsvd_stat.min_latency, - avg.avg_latency_per_hop, - avg.avg_latency_flit, - avg.avg_latency_pck, - avg.avg_throughput, - avg.avg_pck_siz, - #if (STND_DEV_EN) - avg.std_dev - #endif + sent_stat.pck_num, + rsvd_stat.pck_num, + sent_stat.flit_num, + rsvd_stat.flit_num, + sent_stat.worst_latency, + rsvd_stat.worst_latency, + sent_stat.min_latency, + rsvd_stat.min_latency, + avg.avg_latency_per_hop, + avg.avg_latency_flit, + avg.avg_latency_pck, + avg.avg_throughput, + avg.avg_pck_siz, + #if (STND_DEV_EN) + avg.std_dev + #endif ); -// printf("\n"); - + // printf("\n"); } - void merge_statistic (statistic_t * merge_stat, statistic_t stat_in){ merge_stat->pck_num+=stat_in.pck_num; merge_stat->flit_num+=stat_in.flit_num; @@ -1318,52 +1155,43 @@ void merge_statistic (statistic_t * merge_stat, statistic_t stat_in){ #if (STND_DEV_EN) merge_stat->sum_clk_pow2 +=stat_in.sum_clk_pow2; #endif - } void print_statistic_new (unsigned long int total_clk){ int i; - - print_router_st(); print_endp_to_endp_st("pck_num"); print_endp_to_endp_st("flit_num"); - - printf( "\n\tEndpoints Statistics:\n" - "\t#EID," - "sent_stat.pck_num," - "rsvd_stat.pck_num," - "sent_stat.flit_num," - "rsvd_stat.flit_num," - "sent_stat.worst_latency," - "rsvd_stat.worst_latency," - "sent_stat.min_latency," - "rsvd_stat.min_latency," - "avg_latency_per_hop," - "avg_latency_flit," - "avg_latency_pck," - "avg_throughput(%%)," - "avg_pck_size," - #if (STND_DEV_EN) - "avg.std_dev" - #endif - "\n"); - - - -#if(C>1) + printf( + "\n\tEndpoints Statistics:\n" + "\t#EID," + "sent_stat.pck_num," + "rsvd_stat.pck_num," + "sent_stat.flit_num," + "rsvd_stat.flit_num," + "sent_stat.worst_latency," + "rsvd_stat.worst_latency," + "sent_stat.min_latency," + "rsvd_stat.min_latency," + "avg_latency_per_hop," + "avg_latency_flit," + "avg_latency_pck," + "avg_throughput(%%)," + "avg_pck_size," + #if (STND_DEV_EN) + "avg.std_dev" + #endif + "\n"); + #if(C>1) int c; statistic_t sent_stat_class [NE]; statistic_t rsvd_stat_class [NE]; statistic_t sent_stat_per_class [C]; statistic_t rsvd_stat_per_class [C]; - memset (&rsvd_stat_class,0,sizeof(statistic_t)*NE); memset (&sent_stat_class,0,sizeof(statistic_t)*NE); memset (&rsvd_stat_per_class,0,sizeof(statistic_t)*C); memset (&sent_stat_per_class,0,sizeof(statistic_t)*C); - - for (i=0; i1) + #if(C>1) for (c=0; cratio=0; traffic[src]->stop=1; *inject_en=0; return INJECT_OFF; //disable sending } - if( read(task_graph_data[src],index,&task)==0){ traffic[src]->ratio=0; traffic[src]->stop=1; *inject_en=0; return INJECT_OFF; //disable sending - } - -#if (C>1) + #if (C>1) if(sent_stat[src][traffic[src]->flit_out_class].pck_num & 0xFF){//sent 255 packets -#else + #else if(sent_stat[src].pck_num & 0xFF){//sent 255 packets -#endif - - //printf("uu=%u\n",task.jnjct_var); - update_injct_var(src, task.jnjct_var); - - } - + #endif + //printf("uu=%u\n",task.jnjct_var); + update_injct_var(src, task.jnjct_var); + } task_graph_total_pck_num++; task.pck_sent = task.pck_sent +1; task.burst_sent= task.burst_sent+1; task.byte_sent = task.byte_sent + (task.avg_pck_size * (Fpay/8) ); - traffic[src]->pck_class_in= pck_class_in_gen(src); //traffic[src]->avg_pck_size_in=task.avg_pck_size; traffic[src]->pck_size_in=rnd_between(task.min_pck_size,task.max_pck_size); - f= task.injection_rate; v= random_var[src]; f*= (v /100); if(f>100) f= 100; f= f * MAX_RATIO / 100; - traffic[src]->ratio=(unsigned int)f; traffic[src]->init_weight=task.initial_weight; - if (task.burst_sent >= task.burst_size){ task.burst_sent=0; task_graph_abstract[src].active_index=task_graph_abstract[src].active_index+1; if(task_graph_abstract[src].active_index>=task_graph_abstract[src].total_index) task_graph_abstract[src].active_index=0; - } - update_by_index(task_graph_data[src],index,task); - if (task.byte_sent >= task.bytes){ // This task is done remove it from the queue remove_by_index(&task_graph_data[src],index); task_graph_abstract[src].total_index = task_graph_abstract[src].total_index-1; @@ -1690,11 +1440,9 @@ unsigned int pck_dst_gen_task_graph ( unsigned int src, unsigned char * inject_e } if(task_graph_abstract[src].active_index>=task_graph_abstract[src].total_index) task_graph_abstract[src].active_index=0; } - return endp_addr_encoder(task.dst); } - void update_all_router_stat(void){ if(thread_num>1) { int i; @@ -1709,13 +1457,12 @@ void update_all_router_stat(void){ } void update_router_st ( - unsigned int Pnum, - unsigned int rid, - void * event, - size_t size + unsigned int Pnum, + unsigned int rid, + void * event, + size_t size ){ unsigned int port_event; - for (int p=0;p0) for (int k=0;k0) for (int k=0;k0) for (int k=0;k0) for (int k=0;k0) for (int k=0;k Date: Wed, 5 Feb 2025 13:11:00 +0100 Subject: [PATCH 008/107] hetro_vc pass mesh 2x2 simulation --- mpsoc/rtl/src_noc/inout_ports.sv | 73 +++++---- mpsoc/rtl/src_noc/input_ports.sv | 213 +++++++++++++------------- mpsoc/rtl/src_noc/pronoc_pkg.sv | 21 ++- mpsoc/rtl/src_noc/router_two_stage.sv | 70 +++++---- mpsoc/rtl/src_noc/traffic_gen_top.sv | 46 +++--- 5 files changed, 215 insertions(+), 208 deletions(-) diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index ead16f6..2016fb7 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -30,10 +30,9 @@ module inout_ports #( parameter ROUTER_ID=0, parameter P=5 )( - current_r_addr, - neighbors_r_addr, clk, - reset, + reset, + router_info, // to/from neighboring router flit_in_all, @@ -76,7 +75,7 @@ module inout_ports #( iport_weight_all, oports_weight_all, refresh_w_counter, - crossbar_flit_out_wr_all, + crossbar_flit_out_wr_all, // status vsa_credit_decreased_all, @@ -103,10 +102,8 @@ module inout_ports #( WPP = WP * P, PVDSTPw= PV * DSTPw, PRAw= P * RAw; - - input [RAw-1 : 0] current_r_addr; - input [PRAw-1: 0] neighbors_r_addr; + input router_info_t router_info; input [PFw-1 : 0] flit_in_all; input [P-1 : 0] flit_in_wr_all; output[PV-1 : 0] credit_out_all; @@ -174,10 +171,9 @@ module inout_ports #( input_ports #( .NOC_ID(NOC_ID), .ROUTER_ID(ROUTER_ID), - .P(P) + .P(P) ) the_input_port ( - .current_r_addr (current_r_addr), - .neighbors_r_addr(neighbors_r_addr), + .router_info(router_info), .ivc_num_getting_sw_grant (ivc_num_getting_sw_grant ), .any_ivc_sw_request_granted_all (any_ivc_sw_request_granted_all), .flit_in_all (flit_in_all), @@ -194,7 +190,7 @@ module inout_ports #( .swap_port_presel(swap_port_presel), .credit_out_all(credit_out_all), // .lk_destination_encoded_all (lk_destination_encoded_all), - .nonspec_first_arbiter_granted_ivc_all(nonspec_first_arbiter_granted_ivc_all), + .nonspec_first_arbiter_granted_ivc_all(nonspec_first_arbiter_granted_ivc_all), .destport_clear (destport_clear), .vc_weight_is_consumed_all (vc_weight_is_consumed_all), .iport_weight_is_consumed_all (iport_weight_is_consumed_all), @@ -337,9 +333,11 @@ module output_vc_status #( parameter V = 4, parameter B = 16, parameter CAND_VC_SEL_MODE = 0, // 0: use arbiteration between not full vcs, 1: select the vc with most availble free space - parameter CRDTw = 4 + parameter CRDTw = 4, + parameter HETERO_VC=0 )( credit_init_val_in, + ovc_presence, wr_in, credit_in, nearly_full_vc, @@ -352,24 +350,24 @@ module output_vc_status #( ); input [V-1 : 0] [CRDTw-1 : 0 ] credit_init_val_in ; - input [V-1 :0] wr_in; - input [V-1 :0] credit_in; - output [V-1 :0] nearly_full_vc; + input [V-1 : 0] ovc_presence; + input [V-1 : 0] wr_in; + input [V-1 : 0] credit_in; + output [V-1 : 0] nearly_full_vc; output [V-1 : 0] full_vc; - output [V-1 :0] empty_vc; - output [V-1 :0] cand_vc; + output [V-1 : 0] empty_vc; + output [V-1 : 0] cand_vc; input cand_wr_vc_en; input clk; input reset; - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log20)? + ~ nearly_full_vc[i] & cand_wr_vc_en & ovc_presence[i]: + ~ nearly_full_vc[i] & cand_wr_vc_en; end//for - endgenerate arbiter #( - .ARBITER_WIDTH (V) + .ARBITER_WIDTH (V) ) the_nic_arbiter ( - .clk (clk), - .reset (reset), - .request (request), - .grant (cand_vc_next), - .any_grant () + .clk (clk), + .reset (reset), + .request (request), + .grant (cand_vc_next), + .any_grant() ); logic [V-1 : 0] cand_vc_ld_next; @@ -425,7 +423,6 @@ module output_vc_status #( cand_vc_ld_next = cand_vc; if(cand_wr_vc_en) cand_vc_ld_next = cand_vc_next; end - endmodule diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 5d10393..0032039 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -33,8 +33,7 @@ module input_ports #( parameter ROUTER_ID=0, parameter P=5 )( - current_r_addr, - neighbors_r_addr, + router_info, ivc_num_getting_sw_grant,// for non spec ivc_num_getting_first_sw_grant, any_ivc_sw_request_granted_all, flit_in_all, @@ -42,7 +41,7 @@ module input_ports #( reset_ivc_all, flit_is_tail_all, ivc_request_all, - dest_port_all, + dest_port_all, flit_out_all, assigned_ovc_not_full_all, @@ -87,8 +86,7 @@ module input_ports #( PRAw= P * RAw; input reset,clk; - input [RAw-1 : 0] current_r_addr; - input [PRAw-1: 0] neighbors_r_addr; + input router_info_t router_info; output [PV-1 : 0] ivc_num_getting_sw_grant; input [P-1 : 0] any_ivc_sw_request_granted_all; input [PFw-1 : 0] flit_in_all; @@ -126,7 +124,7 @@ module input_ports #( genvar i; generate - for(i=0;i1) && (CAST_TYPE== "UNICAST")) begin : multi_local /* verilator lint_on WIDTH */ - // the router has multiple local ports. Save the destination local port + // the router has multiple local ports. Save the destination local port fwft_fifo #( .DATA_WIDTH(ELw), @@ -781,10 +778,10 @@ module input_queue_per_port #( .recieve_more_than_1(), .reset(reset), .clk(clk) - ); - /* verilator lint_off WIDTH */ + ); + /* verilator lint_off WIDTH */ end else if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST") begin : fmesh - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ fwft_fifo #( .DATA_WIDTH(Pw), @@ -807,7 +804,7 @@ module input_queue_per_port #( assign endp_localp_num[(i+1)*PLw-1 : i*PLw] = {PLw{1'bx}}; end - /* verilator lint_off WIDTH */ + /* verilator lint_off WIDTH */ if(SWA_ARBITER_TYPE != "RRA")begin : wrra /* verilator lint_on WIDTH */ /* @@ -815,21 +812,21 @@ module input_queue_per_port #( .WEIGHTw(WEIGHTw) ) wctrl_per_vc ( .sw_is_granted(ivc_num_getting_sw_grant[i]), - .flit_is_tail(flit_is_tail[i]), - .weight_is_consumed_o(vc_weight_is_consumed[i]), - .iport_weight(1), //(iport_weight), + .flit_is_tail(flit_is_tail[i]), + .weight_is_consumed_o(vc_weight_is_consumed[i]), + .iport_weight(1), //(iport_weight), .clk(clk), - .reset(reset) + .reset(reset) ); - */ + */ assign vc_weight_is_consumed[i] = 1'b1; end else begin :no_wrra - assign vc_weight_is_consumed[i] = 1'bX; - end + assign vc_weight_is_consumed[i] = 1'bX; + end - end//for i + end//for i - /* verilator lint_off WIDTH */ + /* verilator lint_off WIDTH */ if(SWA_ARBITER_TYPE != "RRA")begin : wrra /* verilator lint_on WIDTH */ wire granted_flit_is_tail; @@ -850,22 +847,22 @@ module input_queue_per_port #( .WRRA_CONFIG_INDEX(WRRA_CONFIG_INDEX), .P(P), .SELF_LOOP_EN(SELF_LOOP_EN) - ) wctrl_iport ( + ) wctrl_iport ( .sw_is_granted(any_ivc_sw_request_granted), - .flit_is_tail(granted_flit_is_tail), - .weight_is_consumed_o(iport_weight_is_consumed), + .flit_is_tail(granted_flit_is_tail), + .weight_is_consumed_o(iport_weight_is_consumed), .iport_weight(iport_weight), .oports_weight(oports_weight), - .granted_dest_port(granted_dest_port), - .refresh_w_counter(refresh_w_counter), + .granted_dest_port(granted_dest_port), + .refresh_w_counter(refresh_w_counter), .clk(clk), - .reset(reset) + .reset(reset) ); end else begin :no_wrra assign iport_weight_is_consumed=1'bX; - assign oports_weight = {WP{1'bX}}; - end + assign oports_weight = {WP{1'bX}}; + end /* verilator lint_off WIDTH */ wire [V-1 : 0] flit_buffer_vc_num_rd = (COMBINATION_TYPE == "COMB_NONSPEC")? /* verilator lint_on WIDTH */ @@ -874,11 +871,11 @@ module input_queue_per_port #( flit_buffer #( .B(PORT_B), // buffer space :flit per VC, - .V(PORT_IVC) - ) the_flit_buffer ( + .V(PORT_IVC) + ) the_flit_buffer ( .din(flit_in), // Data in - .vc_num_wr(vc_num_in [PORT_IVC-1 : 0]),//write virtual channel - .vc_num_rd(flit_buffer_vc_num_rd [PORT_IVC-1 : 0]),//read virtual channel + .vc_num_wr(vc_num_in [PORT_IVC-1 : 0]),//write virtual channel + .vc_num_rd(flit_buffer_vc_num_rd [PORT_IVC-1 : 0]),//read virtual channel .wr_en(flit_in_wr), // Write enable .rd_en(any_ivc_sw_request_granted), // Read the next word .dout(buffer_out), // Data out @@ -889,14 +886,14 @@ module input_queue_per_port #( .multiple_dest( multiple_dest [PORT_IVC-1 : 0]), .sub_rd_ptr_ld(reset_ivc [PORT_IVC-1 : 0]) , .flit_is_tail(flit_is_tail [PORT_IVC-1 : 0]) - ); + ); if(PORT_IVC != V) begin : hetero assign ivc_not_empty [V-1 : PORT_IVC]={(V-PORT_IVC){1'b0}}; assign flit_is_tail [V-1 : PORT_IVC]={(V-PORT_IVC){1'b0}}; end - /* verilator lint_off WIDTH */ + /* verilator lint_off WIDTH */ if(CAST_TYPE== "UNICAST") begin : unicast /* verilator lint_on WIDTH */ look_ahead_routing #( @@ -904,10 +901,10 @@ module input_queue_per_port #( .T1(T1), .T2(T2), .T3(T3), - .T4(T4), - .P(P), - .RAw(RAw), - .EAw(EAw), + .T4(T4), + .P(P), + .RAw(RAw), + .EAw(EAw), .DAw(DAw), .DSTPw(DSTPw), .SW_LOC(SW_LOC), @@ -924,13 +921,11 @@ module input_queue_per_port #( .reset(reset), .clk(clk) ); - end // unicast - - endgenerate - + end // unicast + endgenerate header_flit_update_lk_route_ovc #( .NOC_ID(NOC_ID), - .P(P) + .P(P) ) the_flit_update ( .flit_in (buffer_out), .flit_out (flit_out), @@ -942,32 +937,32 @@ module input_queue_per_port #( .sel (sel), .reset (reset), .clk (clk) - ); + ); `ifdef SIMULATION - generate - if(DEBUG_EN) begin :debg + generate + if(DEBUG_EN) begin :debg - always @ (posedge clk) begin - if((|vsa_ctrl_in.ivc_num_getting_sw_grant) & (|ssa_ctrl_in.ivc_num_getting_sw_grant))begin + always @ (posedge clk) begin + if((|vsa_ctrl_in.ivc_num_getting_sw_grant) & (|ssa_ctrl_in.ivc_num_getting_sw_grant))begin $display("%t: ERROR: VSA/SSA conflict: an input port cannot get both sva and ssa grant at the same time %m",$time); $finish; - end + end end//always - for (i=0;i0 && vc_num_in[j] && t1[j]==0)begin + if(`pronoc_reset)begin + t1[j]<=1'b0; + end else begin + if(flit_in_wr >0 && vc_num_in[j] && t1[j]==0)begin $display("%t : Parser:current_r=%h, class_in=%h, destport_in=%h, dest_e_addr_in=%h, src_e_addr_in=%h, vc_num_in=%h,hdr_flit_wr=%h, hdr_flg_in=%h,tail_flg_in=%h ",$time,current_r_addr, class_in, destport_in, dest_e_addr_in, src_e_addr_in, vc_num_in,hdr_flit_wr, hdr_flg_in,tail_flg_in); t1[j]<=1; - end + end end end end `endif//MONITORE_PATH - endgenerate + endgenerate `endif// SIMULATION endmodule @@ -1056,8 +1051,8 @@ module destp_generator #( parameter CAST_TYPE = "UNICAST" )( destport_one_hot, - dest_port_encoded, - dest_port_out, + dest_port_encoded, + dest_port_out, endp_localp_num, swap_port_presel, port_pre_sel, @@ -1065,16 +1060,16 @@ module destp_generator #( ); localparam P_1= ( SELF_LOOP_EN=="NO")? P-1 : P; - input [DSTPw-1 : 0] dest_port_encoded; + input [DSTPw-1 : 0] dest_port_encoded; input [PLw-1 : 0] endp_localp_num; - output [P_1-1: 0] dest_port_out; + output [P_1-1: 0] dest_port_out; output [P-1 : 0] destport_one_hot; input swap_port_presel; input [PPSw-1 : 0] port_pre_sel; input odd_column; - generate - /* verilator lint_off WIDTH */ + generate + /* verilator lint_off WIDTH */ if(CAST_TYPE!= "UNICAST") begin : muticast /* verilator lint_on WIDTH */ // destination port is not coded for multicast/broadcast @@ -1086,7 +1081,7 @@ module destp_generator #( .destport_in(dest_port_encoded), .destport_out(dest_port_out) ); - end else begin : slp + end else begin : slp assign dest_port_out = dest_port_encoded; end /* verilator lint_off WIDTH */ @@ -1104,7 +1099,7 @@ module destp_generator #( .dest_port_in_encoded(dest_port_encoded), .dest_port_out(dest_port_out) ); - /* verilator lint_off WIDTH */ + /* verilator lint_off WIDTH */ end else if (TOPOLOGY == "TREE") begin :tree /* verilator lint_on WIDTH */ tree_destp_generator #( @@ -1116,7 +1111,7 @@ module destp_generator #( ) destp_generator ( .dest_port_in_encoded(dest_port_encoded), .dest_port_out(dest_port_out) - ); + ); /* verilator lint_off WIDTH */ end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh /* verilator lint_on WIDTH */ @@ -1171,22 +1166,22 @@ module destp_generator #( ) destp_generator ( .dest_port_in_encoded(dest_port_encoded), .dest_port_out(dest_port_out) - ); + ); end /* verilator lint_off WIDTH */ if(SELF_LOOP_EN=="NO") begin : nslp /* verilator lint_on WIDTH */ add_sw_loc_one_hot #( .P(P), - .SW_LOC(SW_LOC) + .SW_LOC(SW_LOC) )add ( .destport_in(dest_port_out), .destport_out(destport_one_hot) ); end else begin : slp - assign destport_one_hot = dest_port_out; - end + assign destport_one_hot = dest_port_out; + end endgenerate endmodule @@ -1233,16 +1228,16 @@ module custom_topology_destp_decoder #( .destport_in(dest_port_one_hot[P-1 : 0]), .destport_out(dest_port_out) ); - end else begin : slp + end else begin : slp assign dest_port_out = dest_port_one_hot; end endgenerate - `ifdef SIMULATION + `ifdef SIMULATION initial begin if( ROUTE_TYPE != "DETERMINISTIC") begin $display("%t: ERROR: Custom topologies can only support deterministic routing in the current version of ProNoC",$time); - $finish; + $finish; end end `endif diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index d9aafc0..00712f5 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -184,8 +184,18 @@ package pronoc_pkg; bit nearly_full; bit empty; }ovc_info_t; - localparam OVC_INFO_w = $bits( ovc_info_t); - + localparam OVC_INFO_w = $bits( ovc_info_t); + +/************** +* router id +**************/ + typedef struct packed { + logic [31:0] current_r_id; + logic [RAw-1 : 0] current_r_addr; + logic [MAX_P*RAw-1: 0] neighbors_r_addr; + } router_info_t; + localparam ROUTER_INFO_w = $bits(router_info_t); + /********************* * router_chanels *********************/ @@ -227,7 +237,7 @@ package pronoc_pkg; localparam BYPASSw = log2(SMART_NUM+1); typedef struct packed { logic [SMART_NUM-1: 0] requests; - logic [V-1 : 0] ovc; + logic [V-1 : 0] ovc; logic [EAw-1 : 0] dest_e_addr; bit hdr_flit; bit flit_in_bypassed; @@ -251,7 +261,10 @@ package pronoc_pkg; ctrl_chanel_t ctrl_chanel; } smartflit_chanel_t; localparam SMARTFLIT_CHANEL_w = $bits(smartflit_chanel_t); - + +/**************** +* functions +'***************/ function automatic integer hetero_ivc_decimal; input integer router_id; input integer router_port_num; //router port num diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 1e6a494..ac8f31e 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -38,7 +38,7 @@ module router_two_stage #( current_r_addr,// connected to constant parameter chan_in, - chan_out, + chan_out, ctrl_in, ctrl_out, @@ -55,7 +55,7 @@ module router_two_stage #( reset ); - `NOC_CONF + `NOC_CONF // The current/neighbor routers addresses/port. These values are fixed in each router and they are supposed to be given as parameter. // However, in order to give an identical RTL code to each router, they are given as input ports. The identical RTL code reduces the @@ -75,7 +75,7 @@ module router_two_stage #( output iport_info_t iport_info [P-1 : 0]; output oport_info_t oport_info [P-1 : 0]; - input smart_ctrl_t smart_ctrl_in [P-1 : 0]; + input smart_ctrl_t smart_ctrl_in [P-1 : 0]; vsa_ctrl_t vsa_ctrl [P-1 : 0]; @@ -85,7 +85,7 @@ module router_two_stage #( PVV = PV * V, P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, PP_1 = P_1 * P, - PVP_1 = PV * P_1, + PVP_1 = PV * P_1, PFw = P*Fw, CONG_ALw = CONGw* P, // congestion width per router W = WEIGHTw, @@ -131,7 +131,7 @@ module router_two_stage #( wire [PV-1 : 0] assigned_ovc_not_full_all; wire [PVV-1: 0] masked_ovc_request_all; wire [PV-1 : 0] vc_weight_is_consumed_all; - wire [P-1 : 0] iport_weight_is_consumed_all; + wire [P-1 : 0] iport_weight_is_consumed_all; wire [PV-1 : 0] vsa_ovc_released_all; wire [PV-1 : 0] vsa_credit_decreased_all; @@ -155,27 +155,32 @@ module router_two_stage #( wire [CRDTw-1 : 0 ] credit_init_val_in [P-1 : 0][V-1 : 0]; wire [CRDTw-1 : 0 ] credit_init_val_out [P-1 : 0][V-1 : 0]; + router_info_t router_info; + assign router_info.current_r_id=current_r_id; + assign router_info.current_r_addr=current_r_addr; + assign router_info.neighbors_r_addr[PRAw-1 : 0] = neighbors_r_addr; + genvar i,j; - generate + generate for (i=0; i0 )begin counter <=0; - flit_counter<=flit_counter+1'b1; + flit_counter<=flit_counter+1'b1; end else begin counter <= counter+1'b1; if( counter == 512 ) $display("%t : total flits received in (x=%d,Y=%d) is %d ",$time,current_r_addr,current_y,flit_counter); diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index e8f870c..1806b38 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -243,11 +243,13 @@ module traffic_gen_top #( output_vc_status #( .CRDTw(CRDTw), - .V (V), - .B (PORT_B) + .V(V), + .B(PORT_B), + .HETERO_VC(HETERO_VC) ) nic_ovc_status ( .credit_init_val_in( chan_in.ctrl_chanel.credit_init_val), - .wr_in(ovc_wr_in), + .ovc_presence(chan_in.ctrl_chanel.hetero_ovc_presence), + .wr_in(ovc_wr_in), .credit_in(credit_in), .nearly_full_vc(nearly_full_vc), .full_vc(full_vc), @@ -270,8 +272,8 @@ module traffic_gen_top #( .current_e_addr(current_e_addr), .clk_counter(clk_counter+1'b1),//in case of zero load latency, the flit will be injected in the next clock cycle .pck_number(pck_number), - .dest_e_addr_in(dest_e_addr), - .dest_e_addr_o(dest_e_addr_o), + .dest_e_addr_in(dest_e_addr), + .dest_e_addr_o(dest_e_addr_o), .pck_timestamp(pck_timestamp), .buffer_full(buffer_full), .pck_ready(pck_ready), @@ -298,7 +300,7 @@ module traffic_gen_top #( header_flit_generator #( .NOC_ID(NOC_ID), - .DATA_w(HDR_DATA_w) + .DATA_w(HDR_DATA_w) ) the_header_flit_generator ( .flit_out(hdr_flit_out), .vc_num_in(wr_vc), @@ -422,9 +424,9 @@ module traffic_gen_top #( hdr_flit_sent =1'b0; ns = ps; pck_rd =1'b0; - not_yet_sent_aflit_next =not_yet_sent_aflit; + not_yet_sent_aflit_next =not_yet_sent_aflit; case (ps) - IDEAL: begin + IDEAL: begin if(pck_ready ) begin if(wr_vc_avb && valid_dst)begin @@ -440,10 +442,10 @@ module traffic_gen_top #( sent_done =1'b1; cand_wr_vc_en =1'b1; if(cand_vc>0) begin - wr_vc_next = cand_vc; - end else ns = WAIT; - end //else - end//wr_vc + wr_vc_next = cand_vc; + end else ns = WAIT; + end //else + end//wr_vc end end //IDEAL @@ -469,18 +471,18 @@ module traffic_gen_top #( cand_wr_vc_en =1'b1; if(cand_vc>0) begin wr_vc_next = cand_vc; - ns =IDEAL; + ns = IDEAL; end end default: begin - ns =IDEAL; + ns = IDEAL; end endcase // packet sink if(flit_in_wr) begin credit_out_next = rd_vc; end else credit_out_next = {V{1'd0}}; - end //always + end //always always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin @@ -588,9 +590,9 @@ module traffic_gen_top #( endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod2 ( .id(dst_id), .code(rd_des_e_addr[EAw-1 : 0]));// only for unicast endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod3 ( .id(src_id), .code(rd_src_e_addr)); - wire [NE-1 :0] dest_mcast_all_endp2; + wire [NE-1 :0] dest_mcast_all_endp2; generate - if(CAST_TYPE != "UNICAST") begin :no_unicast + if(CAST_TYPE != "UNICAST") begin :no_unicast mcast_dest_list_decode #( .NOC_ID(NOC_ID) ) decode2 ( @@ -602,14 +604,14 @@ module traffic_gen_top #( end endgenerate - always @(posedge clk) begin + always @(posedge clk) begin /* verilator lint_off WIDTH */ if(CAST_TYPE == "UNICAST") begin - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ if(flit_out_wr && hdr_flit && dest_e_addr_o [EAw-1 : 0] == current_e_addr && SELF_LOOP_EN == "NO") begin $display("%t: ERROR: The self-loop is not enabled in the router while a packet is injected to the NoC with identical source and destination address in endpoint (%h).: %m",$time, dest_e_addr_o ); $finish; - end + end if(flit_in_wr && rd_hdr_flg && (rd_des_e_addr[EAw-1 : 0] != current_e_addr )) begin $display("%t: ERROR: packet with destination %d (code %h) which is sent by source %d (code %h) has been recieved in wrong destination %d (code %h). %m",$time,dst_id,rd_des_e_addr, src_id,rd_src_e_addr, current_id,current_e_addr); $finish; @@ -665,7 +667,7 @@ module traffic_gen_top #( assign {rsv_pck_number,rsv_flit_counter}=statistics; - integer ii; + integer ii; always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin for(ii=0;ii Date: Wed, 5 Feb 2025 15:50:17 +0100 Subject: [PATCH 009/107] remove extra ctrl fifos from input ports when hetero vc is selected --- mpsoc/rtl/src_noc/input_ports.sv | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 0032039..0cf9bba 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -450,7 +450,7 @@ module input_queue_per_port #( assign destport_in_encoded = destport_in; end - for (i=0;i Date: Wed, 5 Feb 2025 17:54:13 +0100 Subject: [PATCH 010/107] add hetro_vc test to intigration test --- .../configurations/vc_alloc/mesh_8x8_4vc | 7 ++ .../vc_alloc/mesh_8x8_4vc_hetero1 | 77 +++++++++++++++++++ .../vc_alloc/mesh_8x8_4vc_hetero2 | 77 +++++++++++++++++++ .../synthetic_sim/reports/vc_alloc_report | 18 +++++ .../synthetic_sim/reports/vc_alloc_report_old | 19 +++++ .../Integration_test/synthetic_sim/src/src.pl | 2 +- mpsoc/rtl/src_noc/input_ports.sv | 2 +- 7 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc new file mode 100644 index 0000000..248f91c --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "ESCAP_VC_MASK" => "4'd1", + "V" => 4, + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 new file mode 100644 index 0000000..5196912 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 @@ -0,0 +1,77 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "ESCAP_VC_MASK" => "4'd1", + "V" => 4, + "HETERO_VC"=> "1", + "MAX_ROUTER"=>"64", + "MAX_PORT"=>"1", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{ + //P0 P1 P2 P3 P4 + '{1}, // R0 + '{2}, // R1 + '{3}, // R2 + '{4}, // R3 + '{1}, // R4 + '{2}, // R5 + '{3}, // R6 + '{4}, // R7 + '{1}, // R8 + '{2}, // R9 + '{3}, // R10 + '{4}, // R11 + '{1}, // R12 + '{2}, // R13 + '{3}, // R14 + '{1}, // R15 + '{2}, // R16 + '{3}, // R17 + '{4}, // R18 + '{1}, // R19 + '{2}, // R20 + '{3}, // R21 + '{4}, // R22 + '{1}, // R23 + '{2}, // R24 + '{3}, // R25 + '{4}, // R26 + '{1}, // R27 + '{2}, // R28 + '{3}, // R29 + '{1}, // R30 + '{2}, // R31 + '{3}, // R32 + '{4}, // R33 + '{1}, // R34 + '{2}, // R35 + '{3}, // R36 + '{4}, // R37 + '{1}, // R38 + '{2}, // R39 + '{3}, // R40 + '{4}, // R41 + '{1}, // R42 + '{2}, // R43 + '{3}, // R44 + '{1}, // R45 + '{2}, // R46 + '{3}, // R47 + '{4}, // R48 + '{1}, // R49 + '{2}, // R50 + '{3}, // R51 + '{4}, // R52 + '{1}, // R53 + '{2}, // R54 + '{3}, // R55 + '{4}, // R56 + '{1}, // R57 + '{2}, // R58 + '{3}, // R59 + '{1}, // R60 + '{2}, // R61 + '{3}, // R62 + '{4} // R63 + }", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 new file mode 100644 index 0000000..38c6d2b --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 @@ -0,0 +1,77 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "V" => 4, + "ESCAP_VC_MASK" => "4'd1", + "HETERO_VC"=> "2", + "MAX_ROUTER"=>"64", + "MAX_PORT"=>"5", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{ + //P0 P1 P2 P3 P4 + '{1, 2, 3, 4, 1}, // R0 + '{2, 3, 4, 1, 2}, // R1 + '{3, 4, 1, 2, 3}, // R2 + '{4, 1, 2, 3, 4}, // R3 + '{1, 2, 3, 4, 1}, // R4 + '{2, 3, 4, 1, 2}, // R5 + '{3, 4, 1, 2, 3}, // R6 + '{4, 1, 2, 3, 4}, // R7 + '{1, 2, 3, 4, 1}, // R8 + '{2, 3, 4, 1, 2}, // R9 + '{3, 4, 1, 2, 3}, // R10 + '{4, 1, 2, 3, 4}, // R11 + '{1, 2, 3, 4, 1}, // R12 + '{2, 3, 4, 1, 2}, // R13 + '{3, 4, 1, 2, 3}, // R14 + '{1, 2, 3, 4, 1}, // R15 + '{2, 3, 4, 1, 2}, // R16 + '{3, 4, 1, 2, 3}, // R17 + '{4, 1, 2, 3, 4}, // R18 + '{1, 2, 3, 4, 1}, // R19 + '{2, 3, 4, 1, 2}, // R20 + '{3, 4, 1, 2, 3}, // R21 + '{4, 1, 2, 3, 4}, // R22 + '{1, 2, 3, 4, 1}, // R23 + '{2, 3, 4, 1, 2}, // R24 + '{3, 4, 1, 2, 3}, // R25 + '{4, 1, 2, 3, 4}, // R26 + '{1, 2, 3, 4, 1}, // R27 + '{2, 3, 4, 1, 2}, // R28 + '{3, 4, 1, 2, 3}, // R29 + '{1, 2, 3, 4, 1}, // R30 + '{2, 3, 4, 1, 2}, // R31 + '{3, 4, 1, 2, 3}, // R32 + '{4, 1, 2, 3, 4}, // R33 + '{1, 2, 3, 4, 1}, // R34 + '{2, 3, 4, 1, 2}, // R35 + '{3, 4, 1, 2, 3}, // R36 + '{4, 1, 2, 3, 4}, // R37 + '{1, 2, 3, 4, 1}, // R38 + '{2, 3, 4, 1, 2}, // R39 + '{3, 4, 1, 2, 3}, // R40 + '{4, 1, 2, 3, 4}, // R41 + '{1, 2, 3, 4, 1}, // R42 + '{2, 3, 4, 1, 2}, // R43 + '{3, 4, 1, 2, 3}, // R44 + '{1, 2, 3, 4, 1}, // R45 + '{2, 3, 4, 1, 2}, // R46 + '{3, 4, 1, 2, 3}, // R47 + '{4, 1, 2, 3, 4}, // R48 + '{1, 2, 3, 4, 1}, // R49 + '{2, 3, 4, 1, 2}, // R50 + '{3, 4, 1, 2, 3}, // R51 + '{4, 1, 2, 3, 4}, // R52 + '{1, 2, 3, 4, 1}, // R53 + '{2, 3, 4, 1, 2}, // R54 + '{3, 4, 1, 2, 3}, // R55 + '{4, 1, 2, 3, 4}, // R56 + '{1, 2, 3, 4, 1}, // R57 + '{2, 3, 4, 1, 2}, // R58 + '{3, 4, 1, 2, 3}, // R59 + '{1, 2, 3, 4, 1}, // R60 + '{2, 3, 4, 1, 2}, // R61 + '{3, 4, 1, 2, 3}, // R62 + '{4, 1, 2, 3, 4} // R63 + }", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report b/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report index 526faa5..0de61d5 100644 --- a/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report +++ b/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report @@ -5,15 +5,33 @@ Verification Results: model is generated successfully. ****************************mesh_4x4x3_vc_spec2 : Compile *******************************: model is generated successfully. +****************************mesh_8x8_4vc : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_4vc_hetero1 : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_4vc_hetero2 : Compile *******************************: + model is generated successfully. ****************************mesh_4x4x3_vc_nonspec : random traffic *******************************: Passed: zero load (2,12.7475) saturation (26,188.161) ****************************mesh_4x4x3_vc_spec1 : random traffic *******************************: Passed: zero load (2,12.53) saturation (22,78.2991) ****************************mesh_4x4x3_vc_spec2 : random traffic *******************************: Passed: zero load (2,12.53) saturation (22,80.5533) +****************************mesh_8x8_4vc : random traffic *******************************: + Passed: zero load (2,18.2409) saturation (38,114.247) +****************************mesh_8x8_4vc_hetero1 : random traffic *******************************: + Passed: zero load (2,18.273) saturation (30,162.17) +****************************mesh_8x8_4vc_hetero2 : random traffic *******************************: + Passed: zero load (2,18.257) saturation (30,175.259) ****************************mesh_4x4x3_vc_nonspec : transposed 1 traffic *******************************: Passed: zero load (2,13.0755) saturation (14,126.234) ****************************mesh_4x4x3_vc_spec1 : transposed 1 traffic *******************************: Passed: zero load (2,12.8699) saturation (14,134.914) ****************************mesh_4x4x3_vc_spec2 : transposed 1 traffic *******************************: Passed: zero load (2,12.8699) saturation (14,137.797) +****************************mesh_8x8_4vc : transposed 1 traffic *******************************: + Passed: zero load (2,19.3785) saturation (18,146.718) +****************************mesh_8x8_4vc_hetero1 : transposed 1 traffic *******************************: + Passed: zero load (2,19.449) saturation (18,150.624) +****************************mesh_8x8_4vc_hetero2 : transposed 1 traffic *******************************: + Passed: zero load (2,19.3972) saturation (18,141.983) diff --git a/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report_old b/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report_old index 526faa5..5fb8f91 100644 --- a/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report_old +++ b/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report_old @@ -5,15 +5,34 @@ Verification Results: model is generated successfully. ****************************mesh_4x4x3_vc_spec2 : Compile *******************************: model is generated successfully. +****************************mesh_8x8_4vc : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_4vc_hetero1 : Compile *******************************: + model is generated successfully. + +****************************mesh_8x8_4vc_hetero2 : Compile *******************************: + model is generated successfully. ****************************mesh_4x4x3_vc_nonspec : random traffic *******************************: Passed: zero load (2,12.7475) saturation (26,188.161) ****************************mesh_4x4x3_vc_spec1 : random traffic *******************************: Passed: zero load (2,12.53) saturation (22,78.2991) ****************************mesh_4x4x3_vc_spec2 : random traffic *******************************: Passed: zero load (2,12.53) saturation (22,80.5533) +****************************mesh_8x8_4vc : random traffic *******************************: + Passed: zero load (2,18.2409) saturation (38,114.247) +****************************mesh_8x8_4vc_hetero1 : random traffic *******************************: + Passed: zero load (2,18.273) saturation (30,162.17) +****************************mesh_8x8_4vc_hetero2 : random traffic *******************************: + Passed: zero load (2,18.257) saturation (30,175.259) ****************************mesh_4x4x3_vc_nonspec : transposed 1 traffic *******************************: Passed: zero load (2,13.0755) saturation (14,126.234) ****************************mesh_4x4x3_vc_spec1 : transposed 1 traffic *******************************: Passed: zero load (2,12.8699) saturation (14,134.914) ****************************mesh_4x4x3_vc_spec2 : transposed 1 traffic *******************************: Passed: zero load (2,12.8699) saturation (14,137.797) +****************************mesh_8x8_4vc : transposed 1 traffic *******************************: + Passed: zero load (2,19.3785) saturation (18,146.718) +****************************mesh_8x8_4vc_hetero1 : transposed 1 traffic *******************************: + Passed: zero load (2,19.449) saturation (18,150.624) +****************************mesh_8x8_4vc_hetero2 : transposed 1 traffic *******************************: + Passed: zero load (2,19.3972) saturation (18,141.983) diff --git a/mpsoc/Integration_test/synthetic_sim/src/src.pl b/mpsoc/Integration_test/synthetic_sim/src/src.pl index e0bda9e..f1b8ea1 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/src.pl +++ b/mpsoc/Integration_test/synthetic_sim/src/src.pl @@ -306,7 +306,7 @@ sub gen_verilator_sh{ '; foreach my $top (sort keys %tops) { - $cmd.= "verilator -f \$SCRPT_DIR_PATH/file_list.f --cc $tops{$top} --prefix \"$top\" \$cmn & \n"; + $cmd.= "verilator -DNO_HETRO_IVC=1 -f \$SCRPT_DIR_PATH/file_list.f --cc $tops{$top} --prefix \"$top\" \$cmn & \n"; } $cmd.="wait\n"; foreach my $top (sort keys %tops) { diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 0cf9bba..509d02f 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -899,7 +899,7 @@ module input_queue_per_port #( assign class_out[i]={Cw{1'b0}}; assign dest_port_multi[i]={DSTPw{1'b0}}; assign dest_port_encoded[i]={DSTPw{1'b0}}; - assign lk_destination_encoded[i]={DSTPw{1'b0}}; + assign lk_destination_encoded [(i+1)*DSTPw-1 : i*DSTPw]={DSTPw{1'b0}}; assign endp_localp_num[(i+1)*PLw-1 : i*PLw]={PLw{1'b0}}; assign vc_weight_is_consumed[i]=1'b0; end From 9aadc0df12c452cab7bafdefd08d8660e4afd0f3 Mon Sep 17 00:00:00 2001 From: amonemi Date: Sat, 8 Feb 2025 01:47:31 +0100 Subject: [PATCH 011/107] Replace synopsys_translate_off with ifdef SIMULATION --- mpsoc/rtl/src_noc/class_table.v | 89 +- mpsoc/rtl/src_noc/comb-spec1.v | 425 ++--- mpsoc/rtl/src_noc/comb_nonspec.sv | 629 +++---- mpsoc/rtl/src_noc/comb_spec2.v | 582 +++--- mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv | 169 +- mpsoc/rtl/src_noc/congestion_analyzer.v | 1966 ++++++++------------- mpsoc/rtl/src_noc/crossbar.v | 116 +- mpsoc/rtl/src_noc/debug.v | 620 +++---- mpsoc/rtl/src_noc/fattree_noc_top.sv | 6 +- mpsoc/rtl/src_noc/fattree_route.v | 734 +++----- mpsoc/rtl/src_noc/fmesh.sv | 825 ++++----- mpsoc/rtl/src_noc/header_flit.sv | 144 +- mpsoc/rtl/src_noc/mesh_torus.sv | 205 +-- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 1 - mpsoc/rtl/src_noc/mesh_torus_routting.v | 1442 ++++++--------- mpsoc/rtl/src_noc/multicast.sv | 6 +- mpsoc/rtl/src_noc/output_ports.sv | 847 +++++---- mpsoc/rtl/src_noc/route_mesh.v | 3 +- mpsoc/rtl/src_noc/route_torus.v | 2 +- mpsoc/rtl/src_noc/router_bypass.sv | 1609 +++++++++-------- mpsoc/rtl/src_noc/routing.v | 2 +- mpsoc/rtl/src_noc/ss_allocator.sv | 338 ++-- mpsoc/rtl/src_noc/topology_localparam.v | 456 +++-- mpsoc/rtl/src_noc/tree_noc_top.sv | 1 - mpsoc/rtl/src_noc/tree_route.v | 3 +- mpsoc/rtl/src_noc/wrra.v | 3 +- 26 files changed, 4657 insertions(+), 6566 deletions(-) diff --git a/mpsoc/rtl/src_noc/class_table.v b/mpsoc/rtl/src_noc/class_table.v index 70e5282..9bae283 100755 --- a/mpsoc/rtl/src_noc/class_table.v +++ b/mpsoc/rtl/src_noc/class_table.v @@ -1,5 +1,4 @@ -`timescale 1ns/1ps - +`include "pronoc_def.v" /********************************************************************** ** File: class_table.v ** @@ -26,27 +25,23 @@ *************************************/ - module class_ovc_table #( +module class_ovc_table #( parameter C= 4,//number of class parameter V= 4, //VC number per port parameter CVw=(C==0)? V : C * V, parameter [CVw-1: 0] CLASS_SETTING = {CVw{1'b1}} // shows how each class can use VCs - - - ) - ( + )( class_in, candidate_ovcs ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21)? log2(C): 1; @@ -56,40 +51,31 @@ genvar i; generate - if(C == 0 || C == 1) begin: no_class // - - assign candidate_ovcs={V{1'b1}}; - - end else begin: width_class - - wire [V-1 : 0] class_table [C-1 : 0]; - for(i=0;i V )begin :b2 - for (i=0;i V )begin :b2 + for (i=0;i. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** VC allocator combined with speculative switch allo- -** cator where free VC availability is checked at the end -** of switch allocation (comb-spec1). +** Description: +** VC allocator combined with speculative switch allo- +** cator where free VC availability is checked at the end +** of switch allocation (comb-spec1). ** ***********************************************************************/ @@ -36,28 +36,26 @@ module comb_spec1_allocator #( parameter MIN_PCK_SIZE=2, //minimum packet size in flits. The minimum value is 1. parameter SELF_LOOP_EN = "NO" )( - dest_port_all, - masked_ovc_request_all, - ovc_is_assigned_all, - ivc_request_all, - assigned_ovc_not_full_all, - ovc_allocated_all, - granted_ovc_num_all, - ivc_num_getting_ovc_grant, - ivc_num_getting_sw_grant, - spec_first_arbiter_granted_ivc_all, - nonspec_first_arbiter_granted_ivc_all, - granted_dest_port_all, - nonspec_granted_dest_port_all, - any_ivc_sw_request_granted_all, - vc_weight_is_consumed_all, - iport_weight_is_consumed_all, - pck_is_single_flit_all, - granted_dst_is_from_a_single_flit_pck, - clk,reset - + dest_port_all, + masked_ovc_request_all, + ovc_is_assigned_all, + ivc_request_all, + assigned_ovc_not_full_all, + ovc_allocated_all, + granted_ovc_num_all, + ivc_num_getting_ovc_grant, + ivc_num_getting_sw_grant, + spec_first_arbiter_granted_ivc_all, + nonspec_first_arbiter_granted_ivc_all, + granted_dest_port_all, + nonspec_granted_dest_port_all, + any_ivc_sw_request_granted_all, + vc_weight_is_consumed_all, + iport_weight_is_consumed_all, + pck_is_single_flit_all, + granted_dst_is_from_a_single_flit_pck, + clk,reset ); - localparam PV = V * P, VV = V * V, @@ -66,8 +64,7 @@ module comb_spec1_allocator #( VP_1 = V * P_1, PP_1 = P_1 * P, PVP_1 = PV * P_1; - - + input [PVP_1-1 : 0] dest_port_all; input [PVV-1 : 0] masked_ovc_request_all; input [PV-1 : 0] ovc_is_assigned_all; @@ -75,35 +72,24 @@ module comb_spec1_allocator #( input [PV-1 : 0] assigned_ovc_not_full_all; input [PV-1 : 0] vc_weight_is_consumed_all; input [P-1 : 0] iport_weight_is_consumed_all; - output [PV-1 : 0] ovc_allocated_all; output [PVV-1 : 0] granted_ovc_num_all; output [PV-1 : 0] ivc_num_getting_ovc_grant; output [PV-1 : 0] ivc_num_getting_sw_grant; output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; output [PV-1 : 0] spec_first_arbiter_granted_ivc_all; - output [PP_1-1 : 0] granted_dest_port_all; output [PP_1-1 : 0] nonspec_granted_dest_port_all; output [P-1 : 0] any_ivc_sw_request_granted_all; - input [PV-1 : 0] pck_is_single_flit_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - input clk,reset; - - - - //internal wires switch allocator - wire [PV-1 : 0] spec_first_arbiter_granted_ivc_all; wire [PP_1-1 : 0] spec_granted_dest_port_all; wire [P-1 : 0] spec_any_ivc_grant_valid; wire [P-1 : 0] valid_speculation; - - //speculative switch allocator spec_sw_alloc #( @@ -113,10 +99,7 @@ module comb_spec1_allocator #( .SWA_ARBITER_TYPE(SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE) - ) - speculative_sw_allocator - ( - + ) speculative_sw_allocator ( .ivc_granted_all(ivc_num_getting_sw_grant), .ivc_request_all(ivc_request_all), .ovc_is_assigned_all(ovc_is_assigned_all), @@ -134,12 +117,10 @@ module comb_spec1_allocator #( .iport_weight_is_consumed_all(iport_weight_is_consumed_all), .pck_is_single_flit_all(pck_is_single_flit_all), .granted_dst_is_from_a_single_flit_pck(granted_dst_is_from_a_single_flit_pck), - .clk(clk), .reset(reset) - ); - + wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; wire [VV-1 : 0] masked_candidate_ovc_per_port [P-1 : 0] ; wire [V-1 : 0] spec_first_arbiter_granted_ivc_per_port[P-1 : 0] ; @@ -150,68 +131,44 @@ module comb_spec1_allocator #( wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; wire [V-1 : 0] ivc_local_num_getting_ovc_grant [P-1 : 0]; - + genvar i,j; generate - - - // IVC loop - for(i=0;i< PV;i=i+1) begin :total_vc_loop - //seprate input/output - assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; - - end//for - - - for(i=0;i< P;i=i+1) begin :port_loop3 - for(j=0;j< V;j=j+1) begin :vc_loop - //merge masked_candidate_ovc in each port - assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; - end//for j - - assign spec_first_arbiter_granted_ivc_per_port[i] =spec_first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; - assign spec_granted_dest_port_per_port[i] =spec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - // multiplex candidate OVC of first level switch allocatore winner - + for(i=0;i< P;i=i+1) begin :P_ + for(j=0;j< V;j=j+1) begin : V_ + //merge masked_candidate_ovc in each port + assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; + end//for j + assign spec_first_arbiter_granted_ivc_per_port[i] =spec_first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; + assign spec_granted_dest_port_per_port[i] =spec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; + // multiplex candidate OVC of first level switch allocatore winner one_hot_mux #( - .IN_WIDTH (VV), - .SEL_WIDTH (V) - ) - multiplexer2 - ( - .mux_in (masked_candidate_ovc_per_port [i]), - .mux_out (spec_first_arbiter_ovc_request [i]), - .sel (spec_first_arbiter_granted_ivc_per_port [i]) - + .IN_WIDTH (VV), + .SEL_WIDTH (V) + ) mux2 ( + .mux_in (masked_candidate_ovc_per_port [i]), + .mux_out (spec_first_arbiter_ovc_request [i]), + .sel (spec_first_arbiter_granted_ivc_per_port [i]) ); - //first level arbiter to candidate only one OVC arbiter #( - .ARBITER_WIDTH (V) - ) - second_arbiter - ( - .clk (clk), - .reset (reset), - .request (spec_first_arbiter_ovc_request[i]), - .grant (spec_first_arbiter_ovc_granted[i]), - .any_grant (valid_speculation[i]) + .ARBITER_WIDTH (V) + ) second_arbiter ( + .clk (clk), + .reset (reset), + .request (spec_first_arbiter_ovc_request[i]), + .grant (spec_first_arbiter_ovc_granted[i]), + .any_grant(valid_speculation[i]) ); - - //demultiplexer - one_hot_demux #( - .IN_WIDTH (V), - .SEL_WIDTH (P_1) - )demux1 - ( - .demux_sel (spec_granted_dest_port_per_port [i]),//selectore - .demux_in (spec_first_arbiter_ovc_granted[i]),//repeated - .demux_out (cand_ovc_granted[i]) + .IN_WIDTH (V), + .SEL_WIDTH (P_1) + )demux1 ( + .demux_sel(spec_granted_dest_port_per_port [i]),//selectore + .demux_in (spec_first_arbiter_ovc_granted[i]),//repeated + .demux_out(cand_ovc_granted[i]) ); - - assign granted_ovc_local_num_per_port[i]=(spec_any_ivc_grant_valid[i])? spec_first_arbiter_ovc_granted[i] : {V{1'b0}}; assign ivc_local_num_getting_ovc_grant[i]= (spec_any_ivc_grant_valid[i] & valid_speculation[i])?spec_first_arbiter_granted_ivc_per_port [i] : {V{1'b0}}; assign ivc_num_getting_ovc_grant[(i+1)*V-1 : i*V] = ivc_local_num_getting_ovc_grant[i]; @@ -220,66 +177,49 @@ module comb_spec1_allocator #( end//j end//i - wire [PV-1 : 0] result; - for(i=0;i< PV;i=i+1) begin :total_vc_loop2 - for(j=0;jj) begin: hh + end else if((i/V)>j) begin assign ovc_allocated_all_gen[i][j] = cand_ovc_granted[j][i-V]; end end//j - assign ovc_allocated_all [i] = |ovc_allocated_all_gen[i]; - - //synthesis translate_off - //synopsys translate_off - if(DEBUG_EN)begin :dbg - - is_onehot0 #( - .IN_WIDTH(P_1) - ) - check_ovc_allocated - ( - .in(ovc_allocated_all_gen[i]), - .result(result[i]) - - ); - - always @(posedge clk ) begin - if(~result[i]) $display("%t,Error: An OVC is assigned to more than one IVC %m",$time); - end - end //DEBUG_EN - //synopsys translate_on - //synthesis translate_on - + `ifdef SIMULATION + if(DEBUG_EN) begin : dbg + is_onehot0 #( + .IN_WIDTH(P_1) + ) check_ovc_allocated ( + .in(ovc_allocated_all_gen[i]), + .result(result[i]) + ); + always @(posedge clk ) begin + if(~result[i]) $display("%t,Error: An OVC is assigned to more than one IVC %m",$time); + end + end //DEBUG_EN + `endif end//i - endgenerate - endmodule - /****************************** * * speculative switch allocator * ******************************/ - - - module spec_sw_alloc #( parameter V = 4, parameter P = 5, parameter DEBUG_EN = 1, parameter SWA_ARBITER_TYPE="RRA", parameter MIN_PCK_SIZE=2 //minimum packet size in flits. The minimum value is 1. - )( - ivc_granted_all, ivc_request_all, ovc_is_assigned_all, @@ -299,17 +239,14 @@ module spec_sw_alloc #( granted_dst_is_from_a_single_flit_pck, clk, reset - ); - - localparam P_1 = P-1,//assumed that no port request for itself! PV = V * P, VP_1 = V * P_1, PVP_1 = P * VP_1, PP_1 = P_1 * P; - + output [PV-1 : 0] ivc_granted_all; input [PV-1 : 0] ivc_request_all; input [PV-1 : 0] ovc_is_assigned_all; @@ -327,11 +264,8 @@ module spec_sw_alloc #( input [P-1 : 0] iport_weight_is_consumed_all; input [PV-1 : 0] pck_is_single_flit_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - input clk, reset; - - //internal wire wire [PV-1 : 0] spec_ivc_granted_all,nonspec_ivc_granted_all; wire [PV-1 : 0] spec_ivc_request_all,nonspec_ivc_request_all; @@ -340,7 +274,6 @@ module spec_sw_alloc #( wire [PP_1-1 : 0] spec_granted_dest_port_all,spec_granted_dest_port_all_accepted; wire [P-1 : 0] nonspec_inport_granted_all,nonspec_outport_granted_all; wire [PP_1-1 : 0] spec_granted_dest_port_all_pre; - wire [P_1-1 : 0] nonspec_portsel_granted [P-1 : 0]; wire [PP_1-1 : 0] spec_request_acceptable; wire [P_1-1 : 0] spec_request_accepted [P-1 : 0]; @@ -348,16 +281,12 @@ module spec_sw_alloc #( wire [PV-1 : 0] spec_ivc_granted_all_accepted; wire [P-1 : 0] spec_any_ivc_grant,nonspec_any_ivc_grant; - sw_alloc_sub#( .V(V), .P(P), .SWA_ARBITER_TYPE(SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE) - - ) - speculative_alloc - ( + ) speculative_alloc ( .ivc_granted_all(spec_ivc_granted_all), .ivc_request_all(spec_ivc_request_all), .assigned_ovc_not_full_all(spec_assigned_ovc_not_full_all), @@ -375,16 +304,13 @@ module spec_sw_alloc #( .clk (clk), .reset (reset) ); - - + sw_alloc_sub#( .V(V), .P(P), .SWA_ARBITER_TYPE(SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE) - ) - nonspeculative_alloc - ( + ) nonspeculative_alloc( .ivc_granted_all (nonspec_ivc_granted_all), .ivc_request_all (nonspec_ivc_request_all), .assigned_ovc_not_full_all (nonspec_assigned_ovc_not_full_all), @@ -403,23 +329,21 @@ module spec_sw_alloc #( .reset (reset) ); - assign nonspec_ivc_request_all = ivc_request_all & ovc_is_assigned_all; - assign spec_ivc_request_all = ivc_request_all & ~ovc_is_assigned_all; - assign spec_assigned_ovc_not_full_all = {PV{1'b1}}; - assign nonspec_assigned_ovc_not_full_all = assigned_ovc_not_full_all; - assign spec_dest_port_all = dest_port_all; - assign nonspec_dest_port_all = dest_port_all; - - + assign nonspec_ivc_request_all = ivc_request_all & ovc_is_assigned_all; + assign spec_ivc_request_all = ivc_request_all & ~ovc_is_assigned_all; + assign spec_assigned_ovc_not_full_all = {PV{1'b1}}; + assign nonspec_assigned_ovc_not_full_all = assigned_ovc_not_full_all; + assign spec_dest_port_all = dest_port_all; + assign nonspec_dest_port_all = dest_port_all; genvar i,j; generate - for(i=0;ij)begin: hh + end else if(i>j)begin assign nonspec_portsel_granted[i][j] = nonspec_outport_granted_all [j]; end //if(i==j) wires are left disconnected @@ -430,10 +354,9 @@ module spec_sw_alloc #( assign any_spec_request_accepted [i] = |spec_request_accepted [i]; assign spec_ivc_granted_all_accepted[(i+1)*V-1 : i*V] = (any_spec_request_accepted [i] & valid_speculation[i])? spec_ivc_granted_all[(i+1)*V-1 : i*V]: {V{1'b0}}; assign spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]=(valid_speculation[i])? spec_request_accepted [i]: {P_1{1'b0}}; - - //synthesis translate_off - //synopsys translate_off - if(DEBUG_EN)begin :dbg + + `ifdef SIMULATION + if(DEBUG_EN) begin : dbg wire [P_1-1 : 0] nonspec_check [P-1:0]; wire [P_1-1 : 0] spec_check [P-1:0]; assign nonspec_check[i] = nonspec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; @@ -443,21 +366,15 @@ module spec_sw_alloc #( if(nonspec_ivc_granted_all [(i+1)*V-1 : i*V] >0 && spec_ivc_granted_all_accepted[(i+1)*V-1 : i*V]>0 ) $display("%t: Error: Both speculative and nonspeculative is granted for one port",$time); end end //DEBUG - //synopsys translate_on - //synthesis translate_on - - - + `endif end//i endgenerate assign spec_any_ivc_grant_valid = any_spec_request_accepted & valid_speculation & spec_any_ivc_grant; assign any_ivc_sw_request_granted_all = nonspec_any_ivc_grant | spec_any_ivc_grant_valid; - assign granted_dest_port_all = nonspec_granted_dest_port_all | spec_granted_dest_port_all_accepted; assign ivc_granted_all = nonspec_ivc_granted_all | spec_ivc_granted_all_accepted; assign spec_granted_dest_port_all = spec_granted_dest_port_all_accepted; - endmodule /********************************** @@ -465,14 +382,11 @@ endmodule * canonical switch allocator * **********************************/ - - module sw_alloc_sub#( parameter V = 4, parameter P = 5, parameter SWA_ARBITER_TYPE="RRA", parameter MIN_PCK_SIZE=2 //minimum packet size in flits. The minimum value is 1. - )( ivc_granted_all, ivc_request_all, @@ -491,8 +405,6 @@ module sw_alloc_sub#( clk, reset ); - - localparam P_1 = P-1,//assumed that no port request for itself! PV = V * P, @@ -500,9 +412,8 @@ module sw_alloc_sub#( PVP_1 = P * VP_1, PP_1 = P_1 * P, PP = P * P; - - - output [PV-1 : 0] ivc_granted_all; + + output [PV-1 : 0] ivc_granted_all; input [PV-1 : 0] ivc_request_all; input [PV-1 : 0] assigned_ovc_not_full_all; input [PVP_1-1 : 0] dest_port_all; @@ -525,7 +436,6 @@ module sw_alloc_sub#( wire [V-1 : 0] ivc_not_full [P-1 : 0]; wire [VP_1-1 : 0] dest_port_ivc [P-1 : 0]; wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; - // internal wires wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter @@ -535,16 +445,14 @@ module sw_alloc_sub#( wire [P_1-1 : 0] second_arbiter_weight_consumed [P-1 : 0]; wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; wire [P-1 : 0] winner_weight_consumed; - wire [P_1-1 : 0] single_flit_granted_dst [P-1 : 0]; wire [PP-1 : 0] single_flit_granted_dst_all; wire [V-1 : 0] pck_is_single_flit [P-1 : 0]; - wire [P-1 : 0] single_flit_pck_local_grant; - + wire [P-1 : 0] single_flit_pck_local_grant; + genvar i,j; generate - - for(i=0;i< P;i=i+1) begin :port_loop + for(i=0;i< P;i=i+1) begin : P_ //assign in/out to the port based wires //output assign ivc_granted_all [(i+1)*V-1 : i*V] = ivc_granted [i]; @@ -555,134 +463,95 @@ module sw_alloc_sub#( assign ivc_not_full[i] = assigned_ovc_not_full_all[(i+1)*V-1 : i*V]; assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; assign vc_weight_is_consumed[i] = vc_weight_is_consumed_all [(i+1)*V-1 : i*V]; - //mask assign ivc_masked[i] = ivc_request[i] & ivc_not_full[i]; - //first level arbiter swa_input_port_arbiter #( - .ARBITER_WIDTH(V), - .EXT_P_EN(0), - .ARBITER_TYPE(SWA_ARBITER_TYPE) - ) - input_arbiter - ( - .ext_pr_en_i(1'b1),// not used here anyway - .request(ivc_masked [i]), - .grant(first_arbiter_grant[i]), - .any_grant( ), - .clk(clk), - .reset(reset), - .vc_weight_is_consumed(vc_weight_is_consumed[i]), + .ARBITER_WIDTH(V), + .EXT_P_EN(0), + .ARBITER_TYPE(SWA_ARBITER_TYPE) + ) input_arbiter ( + .ext_pr_en_i(1'b1),// not used here anyway + .request(ivc_masked [i]), + .grant(first_arbiter_grant[i]), + .any_grant( ), + .clk(clk), + .reset(reset), + .vc_weight_is_consumed(vc_weight_is_consumed[i]), .winner_weight_consumed(winner_weight_consumed[i]) ); - //destination port multiplexer one_hot_mux #( .IN_WIDTH(VP_1), .SEL_WIDTH(V) - ) - multiplexer - ( - .mux_in (dest_port_ivc [i]), - .mux_out(dest_port [i]), + ) mux ( + .mux_in (dest_port_ivc[i]), + .mux_out(dest_port[i]), .sel(first_arbiter_grant[i]) ); - - assign first_arbiter_granted_port_all[(i+1)*P_1-1 : i*P_1] = dest_port [i]; - - - if(MIN_PCK_SIZE == 1) begin :single_flit_supported - assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; + assign first_arbiter_granted_port_all[(i+1)*P_1-1 : i*P_1] = dest_port [i]; + if(MIN_PCK_SIZE == 1) begin + assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; //single_flit req multiplexer one_hot_mux #( .IN_WIDTH (V), .SEL_WIDTH (V) - ) - multiplexer2 - ( + ) mux2 ( .mux_in (pck_is_single_flit [i]), .mux_out (single_flit_pck_local_grant[i]), .sel (first_arbiter_grant[i]) - ); - assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; - add_sw_loc_one_hot #( .P(P), .SW_LOC(i) - ) - add_sw_loc - ( + ) add_sw_loc ( .destport_in(single_flit_granted_dst[i]), .destport_out(single_flit_granted_dst_all[(i+1)*P-1 : i*P]) ); - end else begin : single_flit_notsupported assign single_flit_pck_local_grant[i] = 1'b0; assign single_flit_granted_dst[i] = {P_1{1'b0}}; assign single_flit_granted_dst_all[(i+1)*P-1 : i*P]={P{1'b0}}; end - - - -//second arbiter input/output generate - for(j=0;jj)begin: hh + end else if(i>j)begin assign second_arbiter_request[i][j] = dest_port [j][i-1]; //assign second_arbiter_weight_consumed[i][j] =winner_weight_consumed[j]; assign second_arbiter_weight_consumed[i][j] =iport_weight_is_consumed_all[j]; assign granted_dest_port[j][i-1] = second_arbiter_grant [i][j]; end //if(i==j) wires are left disconnected - end - - - //second level arbiter swa_output_port_arbiter #( .ARBITER_WIDTH(P_1), .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA - ) - output_arbiter - ( + ) output_arbiter ( .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA - .clk(clk), - .reset(reset), - .request(second_arbiter_request [i]), - .grant(second_arbiter_grant [i]), - .any_grant(outport_granted_all [i]) + .clk(clk), + .reset(reset), + .request(second_arbiter_request [i]), + .grant(second_arbiter_grant [i]), + .any_grant(outport_granted_all [i]) ); - - - //any ivc assign any_ivc_grant[i] = | granted_dest_port[i]; - assign ivc_granted[i] = (any_ivc_grant[i]) ? first_arbiter_grant[i] : {V{1'b0}}; - assign inport_granted_all[i] =any_ivc_grant[i]; end//for endgenerate - - custom_or #( - .IN_NUM(P), - .OUT_WIDTH(P) - ) - or_dst - ( - .or_in(single_flit_granted_dst_all), - .or_out(granted_dst_is_from_a_single_flit_pck) - ); - - -endmodule - - + custom_or #( + .IN_NUM(P), + .OUT_WIDTH(P) + ) or_dst ( + .or_in(single_flit_granted_dst_all), + .or_out(granted_dst_is_from_a_single_flit_pck) + ); +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index 5f48418..925bf71 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -1,34 +1,33 @@ `include "pronoc_def.v" /********************************************************************** -** File: comb-nonspec.v +** File: comb-nonspec.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** VC allocator combined with non-speculative switch -** allocator where the free VC availability is checked at -** the beginning of switch allocation (comb-nonspec). +** Description: +** VC allocator combined with non-speculative switch +** allocator where the free VC availability is checked at +** the beginning of switch allocation (comb-nonspec). ** ***********************************************************************/ - module comb_nonspec_allocator # ( parameter NOC_ID = 0, parameter P = 5 //port number @@ -37,8 +36,7 @@ module comb_nonspec_allocator # ( //input dest_port_all, // from input port masked_ovc_request_all, - pck_is_single_flit_all, - + pck_is_single_flit_all, //output ovc_allocated_all,//to the output port @@ -61,11 +59,10 @@ module comb_nonspec_allocator # ( // global clk, reset - ); - - `NOC_CONF - + + `NOC_CONF + localparam P_1 = (SELF_LOOP_EN == "NO")? P-1 : P, PV = V * P, @@ -74,43 +71,33 @@ module comb_nonspec_allocator # ( PP_1 = P_1 * P, PVV = PV * V, PVP_1 = PV * P_1; - - input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; - input [PVV-1 : 0] masked_ovc_request_all; input [PVP_1-1 : 0] dest_port_all; - input [PV-1 : 0] pck_is_single_flit_all; output [PV-1 : 0] ovc_allocated_all; output [PVV-1 : 0] granted_ovc_num_all; output [PV-1 : 0] ivc_num_getting_ovc_grant; - - output [PP_1-1 : 0] granted_dest_port_all; output [PV-1 : 0] ivc_num_getting_sw_grant; output [P-1 : 0] any_ivc_sw_request_granted_all; output [P-1 : 0] any_ovc_granted_in_outport_all; output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; - input clk,reset; input [PV-1 : 0] vc_weight_is_consumed_all; input [P-1 : 0] iport_weight_is_consumed_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - - - + //internal wires switch allocator wire [PV-1 : 0] first_arbiter_granted_ivc_all; wire [PV-1 : 0] ivc_request_masked_all; wire [P-1 : 0] any_cand_ovc_exsit; - wire [PV-1 : 0] ivc_request_all; wire [PV-1 : 0] ovc_is_assigned_all; wire [PV-1 : 0] assigned_ovc_not_full_all; assign nonspec_first_arbiter_granted_ivc_all = first_arbiter_granted_ivc_all; - + //nonspeculative switch allocator nonspec_sw_alloc #( .V(V), @@ -119,10 +106,7 @@ module comb_nonspec_allocator # ( .SWA_ARBITER_TYPE (SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE), .SELF_LOOP_EN(SELF_LOOP_EN) - ) - nonspeculative_sw_allocator - ( - + ) nonspeculative_sw_allocator ( .ivc_granted_all (ivc_num_getting_sw_grant), .ivc_request_masked_all (ivc_request_masked_all), .pck_is_single_flit_all(pck_is_single_flit_all), @@ -137,19 +121,19 @@ module comb_nonspec_allocator # ( .clk (clk), .reset (reset) ); - + wire [PVV-1 : 0] masked_ovc_request_all; - wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; + wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; wire [PV-1 : 0] masked_assigned_request; wire [PV-1 : 0] assigned_ovc_request_all ; - wire [VV-1 : 0] masked_candidate_ovc_per_port [P-1 : 0] ; + wire [VV-1 : 0] masked_candidate_ovc_per_port [P-1 : 0] ; wire [V-1 : 0] first_arbiter_granted_ivc_per_port[P-1 : 0] ; - wire [V-1 : 0] candidate_ovc_local_num [P-1 : 0] ; - wire [V-1 : 0] first_arbiter_ovc_granted [PV-1 : 0]; - wire [P_1-1 : 0] granted_dest_port_per_port [P-1 : 0]; - wire [VP_1-1 : 0] cand_ovc_granted [P-1 : 0]; - wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; - wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; + wire [V-1 : 0] candidate_ovc_local_num [P-1 : 0] ; + wire [V-1 : 0] first_arbiter_ovc_granted [PV-1 : 0]; + wire [P_1-1 : 0] granted_dest_port_per_port [P-1 : 0]; + wire [VP_1-1 : 0] cand_ovc_granted [P-1 : 0]; + wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; + wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; wire [V-1 : 0] ivc_local_num_getting_ovc_grant[P-1 : 0]; wire [V : 0] summ_in [PV-1 : 0]; wire [V-1 : 0] vc_pririty [PV-1 : 0] ; @@ -159,167 +143,98 @@ module comb_nonspec_allocator # ( genvar i,j; generate // IVC loop - for(i=0;i< PV;i=i+1) begin :total_vc_loop - - // mask unavailable ovc from requests - assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; - assign masked_assigned_request [i] = assigned_ovc_not_full_all [i] & assigned_ovc_request_all [i]; - + for(i=0;i< PV;i=i+1) begin :PV_ + // mask unavailable ovc from requests + assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; + assign masked_assigned_request [i] = assigned_ovc_not_full_all [i] & assigned_ovc_request_all [i]; // summing assigned and non-assigned VC requests - assign summ_in[i] ={masked_non_assigned_request [i],masked_assigned_request [i]}; + assign summ_in[i] ={masked_non_assigned_request [i], masked_assigned_request [i]}; assign ivc_request_masked_all[i] = | summ_in[i]; - //first level arbiter to candidate only one OVC //if(VC_ARBITER_TYPE=="RRA")begin :round_robin - - arbiter #( - .ARBITER_WIDTH(V) - ) - ovc_arbiter - ( - .clk (clk), - .reset (reset), - .request (masked_non_assigned_request [i]), - .grant (first_arbiter_ovc_granted[i]), - .any_grant () - ); - /* - end else begin :fixarb - - vc_priority_based_dest_port#( - .P(P), - .V(V) - ) - priority_setting - ( - .dest_port(lk_destination_all [((i+1)*P_1)-1 : i*P_1]), - .vc_pririty(vc_pririty[i]) - ); - - - - arbiter_ext_priority #( - .ARBITER_WIDTH (V) - ) - ovc_arbiter - ( - .request (masked_non_assigned_request [i]), - .priority_in(vc_pririty[i]), - .grant(first_arbiter_ovc_granted[i]), - .any_grant() - ); - - end - */ - + arbiter #( + .ARBITER_WIDTH(V) + ) ovc_arbiter ( + .clk (clk), + .reset (reset), + .request (masked_non_assigned_request [i]), + .grant (first_arbiter_ovc_granted[i]), + .any_grant() + ); end//for wire [P-1 : 0] ovc_assigned_local; - - for(i=0;i< P;i=i+1) begin :port_loop3 - for(j=0;j< V;j=j+1) begin :vc_loop - //merge masked_candidate_ovc in each port - - assign ivc_request_all[i*V+j] = ivc_info[i][j].ivc_req; - assign ovc_is_assigned_all[i*V+j] = ivc_info[i][j].ovc_is_assigned; - assign assigned_ovc_not_full_all[i*V+j] =ivc_info[i][j].assigned_ovc_not_full; - - - assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = first_arbiter_ovc_granted [i*V+j]; - end//for j - - assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; - assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - + + for(i=0;i< P;i=i+1) begin :P_ + for(j=0;j< V;j=j+1) begin :V_ + //merge masked_candidate_ovc in each port + assign ivc_request_all[i*V+j] = ivc_info[i][j].ivc_req; + assign ovc_is_assigned_all[i*V+j] = ivc_info[i][j].ovc_is_assigned; + assign assigned_ovc_not_full_all[i*V+j] =ivc_info[i][j].assigned_ovc_not_full; + assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = first_arbiter_ovc_granted [i*V+j]; + assign granted_ovc_num_all[(i*VV)+((j+1)*V)-1 : (i*VV)+(j*V)]=granted_ovc_local_num_per_port[i]; + end//for j + + assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; + assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; // multiplex candidate OVC of first level switch allocatore winner onehot_mux_1D #( - .W (V), - .N (V) - ) - multiplexer2 - ( - .in (masked_candidate_ovc_per_port [i]), - .out (candidate_ovc_local_num [i]), - .sel (first_arbiter_granted_ivc_per_port [i]) - + .W(V), + .N(V) + ) mux2 ( + .in(masked_candidate_ovc_per_port[i]), + .out(candidate_ovc_local_num[i]), + .sel(first_arbiter_granted_ivc_per_port[i]) ); - - onehot_mux_1D #( - .W (1), - .N (V) - ) - multiplexer2_1 - ( - .in (ovc_is_assigned_all[(i+1)*V-1 : i*V]), - .out (ovc_assigned_local[i]), - .sel (first_arbiter_granted_ivc_per_port [i]) - - ); - - - // assign any_cand_ovc_exsit[i] = | candidate_ovc_local_num [i]; - + .W (1), + .N (V) + ) mux2_1 ( + .in (ovc_is_assigned_all[(i+1)*V-1 : i*V]), + .out (ovc_assigned_local[i]), + .sel (first_arbiter_granted_ivc_per_port [i]) + ); //demultiplexer one_hot_demux #( .IN_WIDTH(V), .SEL_WIDTH(P_1) - ) - demux1 - ( + )demux1 ( .demux_sel(granted_dest_port_per_port [i]),//selectore .demux_in(candidate_ovc_local_num[i]),//repeated .demux_out(cand_ovc_granted [i]) ); - - assign granted_ovc_local_num_per_port [i]=(any_ivc_sw_request_granted_all[i] )? candidate_ovc_local_num[i] : {V{1'b0}}; - assign ivc_local_num_getting_ovc_grant [i]= (any_ivc_sw_request_granted_all[i] & ~ovc_assigned_local[i])? first_arbiter_granted_ivc_per_port [i] : {V{1'b0}}; + + assign granted_ovc_local_num_per_port[i] = (any_ivc_sw_request_granted_all[i] )? candidate_ovc_local_num[i] : {V{1'b0}}; + assign ivc_local_num_getting_ovc_grant [i] = (any_ivc_sw_request_granted_all[i] & ~ovc_assigned_local[i])? first_arbiter_granted_ivc_per_port [i] : {V{1'b0}}; assign ivc_num_getting_ovc_grant [(i+1)*V-1 : i*V] = ivc_local_num_getting_ovc_grant[i]; - for(j=0;jj) begin: hh + end else if((i/V)>j) begin assign ovc_allocated_all_gen[i][j] = cand_ovc_granted[j][i-V]; - end - end else begin : slp - assign ovc_allocated_all_gen[i][j] = cand_ovc_granted[j][i]; + end else begin + assign ovc_allocated_all_gen[i][j] = cand_ovc_granted[j][i]; end end//j - assign ovc_allocated_all [i] = |ovc_allocated_all_gen[i]; - end//i - endgenerate - endmodule - - - /************************************************************** -* * comb_nonspec_v2 -* * first arbiter has been shifted after first multiplexer * -* *********************************************************/ - - - module comb_nonspec_v2_allocator #( parameter V = 4, parameter P = 5, @@ -327,7 +242,6 @@ module comb_nonspec_v2_allocator #( parameter SWA_ARBITER_TYPE = "WRRA", parameter MIN_PCK_SIZE=2, //minimum packet size in flits. The minimum value is 1. parameter SELF_LOOP_EN= "NO" - )( //VC allocator //input @@ -358,10 +272,7 @@ module comb_nonspec_v2_allocator #( // global clk, reset - ); - - localparam P_1 = (SELF_LOOP_EN == "NO") ? P-1 :P, PV = V * P, @@ -371,13 +282,10 @@ module comb_nonspec_v2_allocator #( PVV = PV * V, PVP_1 = PV * P_1; - - - input [PVV-1 : 0] masked_ovc_request_all; input [PVP_1-1 : 0] dest_port_all; input [PV-1 : 0] ovc_is_assigned_all; - input [PV-1 : 0] pck_is_single_flit_all; + input [PV-1 : 0] pck_is_single_flit_all; output [PV-1 : 0] ovc_allocated_all; output [PVV-1 : 0] granted_ovc_num_all; output [PV-1 : 0] ivc_num_getting_ovc_grant; @@ -391,15 +299,14 @@ module comb_nonspec_v2_allocator #( input clk,reset; input [PV-1 : 0] vc_weight_is_consumed_all; input [P-1 : 0] iport_weight_is_consumed_all; - + output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; //internal wires switch allocator wire [PV-1 : 0] first_arbiter_granted_ivc_all; wire [PV-1 : 0] ivc_request_masked_all; wire [P-1 : 0] any_cand_ovc_exsit; - output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - + assign nonspec_first_arbiter_granted_ivc_all = first_arbiter_granted_ivc_all; - + //nonspeculative switch allocator nonspec_sw_alloc #( .V(V), @@ -407,10 +314,7 @@ module comb_nonspec_v2_allocator #( .FIRST_ARBITER_EXT_P_EN(FIRST_ARBITER_EXT_P_EN), .SWA_ARBITER_TYPE(SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE) - ) - nonspeculative_sw_allocator - ( - + ) nonspeculative_sw_allocator ( .ivc_granted_all (ivc_num_getting_sw_grant), .ivc_request_masked_all (ivc_request_masked_all), .pck_is_single_flit_all(pck_is_single_flit_all), @@ -425,7 +329,6 @@ module comb_nonspec_v2_allocator #( .iport_weight_is_consumed_all(iport_weight_is_consumed_all), .clk (clk), .reset (reset) - ); wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; @@ -442,87 +345,64 @@ module comb_nonspec_v2_allocator #( wire [V-1 : 0] ivc_local_num_getting_ovc_grant[P-1 : 0]; wire [V : 0] summ_in [PV-1 : 0]; - - assign assigned_ovc_request_all = ivc_request_all & ovc_is_assigned_all; - + assign assigned_ovc_request_all = ivc_request_all & ovc_is_assigned_all; genvar i,j; generate - // IVC loop - for(i=0;i< PV;i=i+1) begin :total_vc_loop - + for(i=0;i< PV;i=i+1) begin :PV_ // mask unavailable ovc from requests assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; assign masked_assigned_request [i] = assigned_ovc_not_full_all[i] & assigned_ovc_request_all[i]; - // summing assigned and non-assigned VC requests assign summ_in[i] ={masked_non_assigned_request [i],masked_assigned_request [i]}; assign ivc_request_masked_all[i] = | summ_in[i]; - end//for - - for(i=0;i< P;i=i+1) begin :port_loop3 - for(j=0;j< V;j=j+1) begin :vc_loop - //merge masked_candidate_ovc in each port - assign masked_non_assigned_request_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; - end//for j - - assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; - - assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - - + for(i=0;i< P;i=i+1) begin : P_ + for(j=0;j< V;j=j+1) begin : V_ + //merge masked_candidate_ovc in each port + assign masked_non_assigned_request_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; + assign granted_ovc_num_all[(i*VV)+((j+1)*V)-1 : (i*VV)+(j*V)]=granted_ovc_local_num_per_port[i]; + end//for j + assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; + assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; + onehot_mux_1D #( - .W (V), - .N (V) - ) - multiplexer2 - ( - .in (masked_non_assigned_request_per_port [i]), - .out (candidate_ovc_local_num [i]), - .sel (first_arbiter_granted_ivc_per_port [i]) - + .W(V), + .N(V) + ) mux2 ( + .in (masked_non_assigned_request_per_port [i]), + .out (candidate_ovc_local_num [i]), + .sel (first_arbiter_granted_ivc_per_port [i]) ); - assign any_cand_ovc_exsit[i] = | candidate_ovc_local_num [i]; - //first level arbiter to candidate only one OVC arbiter #( .ARBITER_WIDTH (V) - ) - first_arbiter - ( + ) arbiter1 ( .clk (clk), .reset (reset), .request (candidate_ovc_local_num[i]), .grant (first_arbiter_ovc_granted[i]), .any_grant ( ) ); - //demultiplexer one_hot_demux #( .IN_WIDTH (V), .SEL_WIDTH (P_1) - ) - demux1 - ( + ) demux1 ( .demux_sel (granted_dest_port_per_port [i]),//selectore .demux_in (first_arbiter_ovc_granted[i]),//repeated .demux_out (cand_ovc_granted [i]) - ); - - + ); + assign granted_ovc_local_num_per_port [i]=(any_ivc_sw_request_granted_all[i] )? first_arbiter_ovc_granted[i] : {V{1'b0}}; assign ivc_local_num_getting_ovc_grant [i]= (any_ivc_sw_request_granted_all[i] & any_cand_ovc_exsit[i])? first_arbiter_granted_ivc_per_port [i] : {V{1'b0}}; assign ivc_num_getting_ovc_grant [(i+1)*V-1 : i*V] = ivc_local_num_getting_ovc_grant[i]; - for(j=0;jj) begin: hh assign ovc_allocated_all_gen[i][j] = cand_ovc_granted[j][i-V]; - end end//j - assign ovc_allocated_all [i] = |ovc_allocated_all_gen[i]; - end//i - endgenerate - endmodule - /******************************************** * * nonspeculative switch allocator * ******************************************/ - module nonspec_sw_alloc #( parameter V = 4, parameter P = 5, @@ -557,9 +430,7 @@ module nonspec_sw_alloc #( parameter SWA_ARBITER_TYPE = "WRRA", parameter MIN_PCK_SIZE=2, //minimum packet size in flits. The minimum value is 1. parameter SELF_LOOP_EN="NO" - )( - ivc_granted_all, ivc_request_masked_all, pck_is_single_flit_all, @@ -574,18 +445,16 @@ module nonspec_sw_alloc #( iport_weight_is_consumed_all, clk, reset - ); - - localparam + + localparam P_1 = (SELF_LOOP_EN== "NO") ? P-1 : P, PV = V * P, VP_1 = V * P_1, PP_1 = P_1 * P, PVP_1 = PV * P_1, PP = P*P; - - + output [PV-1 : 0] ivc_granted_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; input [PV-1 : 0] ivc_request_masked_all; @@ -618,11 +487,11 @@ module nonspec_sw_alloc #( wire [P_1-1 : 0] second_arbiter_weight_consumed [P-1 : 0]; wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; wire [P-1 :0] winner_weight_consumed; - + genvar i,j; generate - for(i=0;i< P;i=i+1) begin :port_loop + for(i=0;i< P;i=i+1) begin : P_ //assign in/out to the port based wires //output assign ivc_granted_all [(i+1)*V-1 : i*V] = ivc_granted [i]; @@ -630,169 +499,133 @@ module nonspec_sw_alloc #( assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]= first_arbiter_grant[i]; //input assign ivc_masked[i] = ivc_request_masked_all [(i+1)*V-1 : i*V]; - assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; assign vc_weight_is_consumed[i] = vc_weight_is_consumed_all [(i+1)*V-1 : i*V]; //first level arbiter swa_input_port_arbiter #( - .ARBITER_WIDTH(V), - .EXT_P_EN(FIRST_ARBITER_EXT_P_EN), - .ARBITER_TYPE(SWA_ARBITER_TYPE) - ) - input_arbiter - ( - .ext_pr_en_i(any_ivc_granted_all[i]), - .request(ivc_masked [i]), - .grant(first_arbiter_grant[i]), - .any_grant( ), - .clk(clk), - .reset(reset), - .vc_weight_is_consumed(vc_weight_is_consumed[i]), - .winner_weight_consumed(winner_weight_consumed[i]) + .ARBITER_WIDTH(V), + .EXT_P_EN(FIRST_ARBITER_EXT_P_EN), + .ARBITER_TYPE(SWA_ARBITER_TYPE) + ) input_arbiter ( + .ext_pr_en_i(any_ivc_granted_all[i]), + .request(ivc_masked [i]), + .grant(first_arbiter_grant[i]), + .any_grant( ), + .clk(clk), + .reset(reset), + .vc_weight_is_consumed(vc_weight_is_consumed[i]), + .winner_weight_consumed(winner_weight_consumed[i]) ); - - - //destination port multiplexer onehot_mux_1D #( .W (P_1), .N (V) - ) - multiplexer - ( - .in (dest_port_ivc [i]), - .out (dest_port [i]), - .sel(first_arbiter_grant[i]) - + ) mux ( + .in (dest_port_ivc [i]), + .out (dest_port[i]), + .sel(first_arbiter_grant[i]) ); - if(MIN_PCK_SIZE == 1) begin :single_flit_supported + + if(MIN_PCK_SIZE == 1) begin //single_flit req multiplexer assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; onehot_mux_1D #( .W (1), .N (V) - ) - multiplexer2 - ( + ) mux2 ( .in (pck_is_single_flit [i]), .out (single_flit_pck_local_grant[i]), .sel (first_arbiter_grant[i]) - ); assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; - - if (SELF_LOOP_EN == "NO") begin :nslp + + if (SELF_LOOP_EN == "NO") begin add_sw_loc_one_hot #( .P(P), .SW_LOC(i) - ) - add_sw_loc - ( + ) add_sw_loc ( .destport_in(single_flit_granted_dst[i]), .destport_out(single_flit_granted_dst_all[(i+1)*P-1 : i*P]) ); - end else begin :slp + end else begin assign single_flit_granted_dst_all[(i+1)*P-1 : i*P] = single_flit_granted_dst[i]; end - end else begin : single_flit_notsupported + end else begin assign single_flit_pck_local_grant[i] = 1'bx; assign single_flit_granted_dst[i] = {P_1{1'bx}}; assign single_flit_granted_dst_all[(i+1)*P-1 : i*P]={P{1'b0}}; end - //second arbiter input/output generate - - - for(j=0;jj)begin: hh - assign second_arbiter_request[i][j] = dest_port [j][i-1] ; - //assign second_arbiter_weight_consumed[i][j] =winner_weight_consumed[j]; - assign second_arbiter_weight_consumed[i][j] =iport_weight_is_consumed_all[j]; - assign granted_dest_port[j][i-1] = second_arbiter_grant [i][j] ; + //second arbiter input/output generate + for(j=0;jj)begin + assign second_arbiter_request[i][j] = dest_port [j][i-1] ; + //assign second_arbiter_weight_consumed[i][j] =winner_weight_consumed[j]; + assign second_arbiter_weight_consumed[i][j] =iport_weight_is_consumed_all[j]; + assign granted_dest_port[j][i-1] = second_arbiter_grant [i][j] ; + end + //if(i==j) wires are left disconnected + end else begin + assign second_arbiter_request[i][j] = dest_port[j][i]; + assign second_arbiter_weight_consumed[i][j] =iport_weight_is_consumed_all[j] ; + assign granted_dest_port[j][i] = second_arbiter_grant [i][j] ; end - //if(i==j) wires are left disconnected - end else begin :slp - assign second_arbiter_request[i][j] = dest_port[j][i]; - assign second_arbiter_weight_consumed[i][j] =iport_weight_is_consumed_all[j] ; - assign granted_dest_port[j][i] = second_arbiter_grant [i][j] ; - end - end - - + end //P_ //second level arbiter swa_output_port_arbiter #( .ARBITER_WIDTH(P_1), .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA - ) - output_arbiter - ( - .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA - .clk(clk), - .reset(reset), - .request(second_arbiter_request [i]), - .grant(second_arbiter_grant [i]), - .any_grant(any_ovc_granted_all [i]) + ) output_arbiter ( + .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA + .clk(clk), + .reset(reset), + .request(second_arbiter_request [i]), + .grant(second_arbiter_grant [i]), + .any_grant(any_ovc_granted_all [i]) ); - - //any ivc assign any_ivc_granted_all[i] = | granted_dest_port[i]; assign ivc_granted[i] = (any_ivc_granted_all[i]) ? first_arbiter_grant[i] : {V{1'b0}}; - - - end//for - endgenerate - - custom_or #( + end//for P_ + endgenerate + + custom_or #( .IN_NUM(P), .OUT_WIDTH(P) - ) - or_dst - ( - .or_in(single_flit_granted_dst_all), - .or_out(granted_dst_is_from_a_single_flit_pck) - ); - + ) or_dst ( + .or_in(single_flit_granted_dst_all), + .or_out(granted_dst_is_from_a_single_flit_pck) + ); endmodule - /******************* * swa_input_port_arbiter * ********************/ - - module swa_input_port_arbiter #( parameter ARBITER_WIDTH =4, parameter EXT_P_EN = 1, parameter ARBITER_TYPE = "WRRA"// RRA, WRRA - )( - ext_pr_en_i, // it is used only if the EXT_P_EN is 1 - clk, - reset, - request, - grant, - any_grant, - vc_weight_is_consumed, // only for WRRA - winner_weight_consumed // only for WRRA + ext_pr_en_i, // it is used only if the EXT_P_EN is 1 + clk, + reset, + request, + grant, + any_grant, + vc_weight_is_consumed, // only for WRRA + winner_weight_consumed // only for WRRA ); - - - - - input ext_pr_en_i; input [ARBITER_WIDTH-1 : 0] request; output[ARBITER_WIDTH-1 : 0] grant; @@ -801,34 +634,27 @@ module swa_input_port_arbiter #( input reset; input [ARBITER_WIDTH-1 : 0] vc_weight_is_consumed; output winner_weight_consumed; - - + generate /* verilator lint_off WIDTH */ - if(ARBITER_TYPE != "RRA") begin : wrra_m + if(ARBITER_TYPE != "RRA") begin: wrra_ /* verilator lint_on WIDTH */ - // one hot mux onehot_mux_1D #( .W(1), .N(ARBITER_WIDTH) - ) - mux - ( + ) mux ( .in(vc_weight_is_consumed), .out(winner_weight_consumed), .sel(grant) ); - + wire priority_en = (EXT_P_EN == 1) ? ext_pr_en_i & winner_weight_consumed : winner_weight_consumed; - + //round robin arbiter with external priority - arbiter_priority_en #( .ARBITER_WIDTH(ARBITER_WIDTH) - ) - rra - ( + ) rra ( .request(request), .grant(grant), .any_grant(any_grant), @@ -836,7 +662,6 @@ module swa_input_port_arbiter #( .reset(reset), .priority_en(priority_en) ); - end else begin : rra_m //RRA assign winner_weight_consumed = 1'bx; if(EXT_P_EN==1) begin : arbiter_ext_en @@ -853,14 +678,10 @@ module swa_input_port_arbiter #( .any_grant (any_grant ), .priority_en (ext_pr_en_i) ); - end else begin: first_lvl_arbiter_internal_en - arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - arb - ( + ) arb( .clk (clk), .reset (reset), .request (request), @@ -869,47 +690,34 @@ module swa_input_port_arbiter #( ); end//else - end endgenerate - endmodule - - - /******************* * swa_output_port_arbiter * ********************/ - - module swa_output_port_arbiter #( parameter ARBITER_WIDTH =4, parameter ARBITER_TYPE = "WRRA" // RRA, WRRA - - )( - weight_consumed, // only used for WRRA - clk, - reset, - request, - grant, - any_grant + weight_consumed, // only used for WRRA + clk, + reset, + request, + grant, + any_grant ); - - - + input [ARBITER_WIDTH-1 : 0] request; output [ARBITER_WIDTH-1 : 0] grant; output any_grant; input clk; input reset; input [ARBITER_WIDTH-1 : 0] weight_consumed; - - - - generate + + generate /* verilator lint_off WIDTH */ if(ARBITER_TYPE == "WRRA") begin : wrra_mine /* verilator lint_on WIDTH */ @@ -919,21 +727,15 @@ module swa_output_port_arbiter #( onehot_mux_1D #( .W(1), .N(ARBITER_WIDTH) - ) - multiplexer - ( + ) mux ( .in(weight_consumed), .out(pr_en), .sel(grant) - ); - arbiter_priority_en #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - arb - ( + ) arb ( .clk (clk), .reset (reset), .request (request), @@ -941,8 +743,7 @@ module swa_output_port_arbiter #( .any_grant (any_grant ), .priority_en (pr_en) ); - - + /* verilator lint_off WIDTH */ end else if(ARBITER_TYPE == "WRRA_CLASSIC") begin : wrra_classic /* verilator lint_on WIDTH */ @@ -951,28 +752,21 @@ module swa_output_port_arbiter #( wire [ARBITER_WIDTH-1 : 0] masked_req= request & ~weight_consumed; wire sel = |masked_req; wire [ARBITER_WIDTH-1 : 0] mux_req = (sel==1'b1)? masked_req : request; - + arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH ) - ) - arb - ( + ) arb ( .clk (clk), .reset (reset), .request (mux_req), .grant (grant), .any_grant (any_grant ) ); - - - end else begin : rra_m - + arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH ) - ) - arb - ( + ) arb ( .clk (clk), .reset (reset), .request (request), @@ -980,7 +774,6 @@ module swa_output_port_arbiter #( .any_grant (any_grant ) ); - end - endgenerate -endmodule - + end + endgenerate +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/comb_spec2.v b/mpsoc/rtl/src_noc/comb_spec2.v index 07d841a..e0883a5 100755 --- a/mpsoc/rtl/src_noc/comb_spec2.v +++ b/mpsoc/rtl/src_noc/comb_spec2.v @@ -1,34 +1,33 @@ -`timescale 1ns/1ps +`include "pronoc_def.v" /********************************************************************** -** File: comb_spec2.v +** File: comb_spec2.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** VC allocator combined with speculative switch allocator -** where the free VC availability is checked in the middle -** of switch allocator after first level of arbitration -** (comb-spec2). +** Description: +** VC allocator combined with speculative switch allocator +** where the free VC availability is checked in the middle +** of switch allocator after first level of arbitration +** (comb-spec2). ** -**************************************************************/ - +*************************************************************/ module comb_spec2_allocator #( parameter V = 4,// Virtual chanel num per port @@ -58,7 +57,6 @@ module comb_spec2_allocator #( granted_dst_is_from_a_single_flit_pck, clk,reset ); - localparam PV = V * P, VV = V * V, @@ -67,37 +65,31 @@ module comb_spec2_allocator #( VP_1 = V * P_1, PP_1 = P_1 * P, PVP_1 = PV * P_1; - input [PVP_1-1 : 0] dest_port_all; - input [PVV-1 : 0] masked_ovc_request_all; + input [PVV-1 : 0] masked_ovc_request_all; input [PV-1 : 0] ovc_is_assigned_all; input [PV-1 : 0] ivc_request_all; input [PV-1 : 0] assigned_ovc_not_full_all; input [PV-1 : 0] vc_weight_is_consumed_all; input [P-1 : 0] iport_weight_is_consumed_all; - output [PV-1 : 0] ovc_allocated_all; output [PVV-1 : 0] granted_ovc_num_all; output [PV-1 : 0] ivc_num_getting_ovc_grant; output [PV-1 : 0] ivc_num_getting_sw_grant; output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; output [PV-1 : 0] spec_first_arbiter_granted_ivc_all; - output [PP_1-1 : 0] granted_dest_port_all; output [PP_1-1 : 0] nonspec_granted_dest_port_all; output [P-1 : 0] any_ivc_sw_request_granted_all; - input [PV-1 : 0] pck_is_single_flit_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; input clk,reset; - //internal wires switch allocator - wire [PV-1 : 0] spec_first_arbiter_granted_ivc_all; wire [PP_1-1 : 0] spec_granted_dest_port_all; wire [P-1 : 0] spec_any_ivc_grant_valid; wire [PV-1 : 0] valid_speculation; - + //speculative switch allocator spec_sw_alloc2 #( .V (V), @@ -105,9 +97,7 @@ module comb_spec2_allocator #( .DEBUG_EN (DEBUG_EN), .SWA_ARBITER_TYPE (SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE) - ) - speculative_sw_allocator - ( + ) speculative_sw_allocator ( .ivc_granted_all(ivc_num_getting_sw_grant), .ivc_request_all(ivc_request_all), .ovc_is_assigned_all(ovc_is_assigned_all), @@ -128,7 +118,7 @@ module comb_spec2_allocator #( .clk(clk), .reset(reset) ); - + wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0]; wire [VV-1 : 0] masked_candidate_ovc_per_port [P-1 : 0]; wire [V-1 : 0] spec_first_arbiter_granted_ivc_per_port[P-1 : 0]; @@ -139,120 +129,87 @@ module comb_spec2_allocator #( wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; wire [V-1 : 0] ivc_local_num_getting_ovc_grant [P-1 : 0]; - + genvar i,j; generate - - // IVC loop - for(i=0;i< PV;i=i+1) begin :total_vc_loop - - // mask unavailable ovc from requests - assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; - assign valid_speculation [i] = | masked_non_assigned_request [i]; - - end//for - - for(i=0;i< P;i=i+1) begin :port_loop3 - for(j=0;j< V;j=j+1) begin :vc_loop - //merge masked_candidate_ovc in each port - assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; - - end//for j - + for(i=0;i< P;i=i+1) begin : P_ + for(j=0;j< V;j=j+1) begin : V_ + //merge masked_candidate_ovc in each port + assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; + assign granted_ovc_num_all[(i*VV)+((j+1)*V)-1 : (i*VV)+(j*V)]=granted_ovc_local_num_per_port[i]; + end//for j assign spec_first_arbiter_granted_ivc_per_port[i] =spec_first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; assign spec_granted_dest_port_per_port[i] =spec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; // multiplex candidate OVC of first level switch allocatore winner - one_hot_mux #( .IN_WIDTH (VV), .SEL_WIDTH (V) - ) - multiplexer2 - ( + ) multiplexer2( .mux_in(masked_candidate_ovc_per_port [i]), .mux_out(spec_first_arbiter_ovc_request [i]), .sel(spec_first_arbiter_granted_ivc_per_port [i]) - ); - + ); //first level arbiter to candidate only one OVC arbiter #( .ARBITER_WIDTH (V) - ) - second_arbiter - ( + )second_arbiter ( .clk(clk), .reset(reset), .request(spec_first_arbiter_ovc_request[i]), .grant(spec_first_arbiter_ovc_granted[i]), .any_grant( ) - ); - + ); //demultiplexer one_hot_demux #( .IN_WIDTH(V), .SEL_WIDTH(P_1) - ) - demux1 - ( + ) demux1 ( .demux_sel(spec_granted_dest_port_per_port [i]),//selectore .demux_in(spec_first_arbiter_ovc_granted[i]),//repeated .demux_out(cand_ovc_granted[i]) ); - //assign cand_ovc_granted [i] = (spec_any_ivc_grant_valid[i])? cand_ovc_demuxed[i]: {VP_1{1'b0}}; assign granted_ovc_local_num_per_port[i]=(spec_any_ivc_grant_valid[i])? spec_first_arbiter_ovc_granted[i] : {V{1'b0}}; assign ivc_local_num_getting_ovc_grant[i]= (spec_any_ivc_grant_valid[i])? spec_first_arbiter_granted_ivc_per_port [i] : {V{1'b0}}; assign ivc_num_getting_ovc_grant[(i+1)*V-1 : i*V] = ivc_local_num_getting_ovc_grant[i]; - for(j=0;jj) begin: hh + end else if((i/V)>j) begin assign ovc_allocated_all_gen[i][j] = cand_ovc_granted[j][i-V]; end end//j - assign ovc_allocated_all [i] = |ovc_allocated_all_gen[i]; - - //synthesis translate_off - //synopsys translate_off - if(DEBUG_EN)begin :dbg + + `ifdef SIMULATION + if(DEBUG_EN)begin : dbg is_onehot0 #( .IN_WIDTH(P_1) - ) - check_ovc_allocated - ( - .in (ovc_allocated_all_gen[i]), - .result (result[i]) + ) check_ovc_allocated ( + .in (ovc_allocated_all_gen[i]), + .result (result[i]) ); - always @(posedge clk ) begin if(~result[i]) $display("%t,Error: An OVC is assigned to more than one IVC %m",$time); end end //DEBUG - //synopsys translate_on - //synthesis translate_on - + `endif//SIMULATION end//i - endgenerate - endmodule /*************************** speculative switch allocator for comb_spec2 ****************************/ - - module spec_sw_alloc2 #( parameter V = 4, parameter P = 5, @@ -280,58 +237,51 @@ module spec_sw_alloc2 #( clk, reset ); - localparam P_1 = P-1,//assumed that no port request for itself! PV = V * P, VP_1= V * P_1, PVP_1 = P * VP_1, PP_1 = P_1 * P; - - output [PV-1 : 0] ivc_granted_all; - input [PV-1 : 0] ivc_request_all; - input [PV-1 : 0] ovc_is_assigned_all; - input [PV-1 : 0] assigned_ovc_not_full_all; + output [PV-1 : 0] ivc_granted_all; + input [PV-1 : 0] ivc_request_all; + input [PV-1 : 0] ovc_is_assigned_all; + input [PV-1 : 0] assigned_ovc_not_full_all; input [PVP_1-1 : 0] dest_port_all; - output [PP_1-1 : 0] granted_dest_port_all; - output [PP_1-1 : 0] nonspec_granted_dest_port_all; - input [PV-1 : 0] valid_speculation; - output [PV-1 : 0] spec_first_arbiter_granted_ivc_all; - output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; + output [PP_1-1 : 0] granted_dest_port_all; + output [PP_1-1 : 0] nonspec_granted_dest_port_all; + input [PV-1 : 0] valid_speculation; + output [PV-1 : 0] spec_first_arbiter_granted_ivc_all; + output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; output [PP_1-1 : 0] spec_granted_dest_port_all; - output [P-1 : 0] spec_any_ivc_grant_valid; - output [P-1 : 0] any_ivc_sw_request_granted_all; + output [P-1 : 0] spec_any_ivc_grant_valid; + output [P-1 : 0] any_ivc_sw_request_granted_all; input [PV-1 : 0] vc_weight_is_consumed_all; input [P-1 : 0] iport_weight_is_consumed_all; input [PV-1 : 0] pck_is_single_flit_all; - output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - + output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; input clk,reset; - //internal wire - wire [PV-1 : 0] spec_ivc_granted_all,nonspec_ivc_granted_all; - wire [PV-1 : 0] spec_ivc_request_all,nonspec_ivc_request_all; - wire [PV-1 : 0] spec_assigned_ovc_not_full_all,nonspec_assigned_ovc_not_full_all; - wire [PVP_1-1 : 0] spec_dest_port_all,nonspec_dest_port_all; - wire [PP_1-1 : 0] spec_granted_dest_port_all,spec_granted_dest_port_all_accepted; - wire [P-1 : 0] nonspec_inport_granted_all,nonspec_outport_granted_all; - wire [PP_1-1 : 0] spec_granted_dest_port_all_pre; - - wire [P_1-1 : 0] nonspec_portsel_granted [P-1 : 0]; - wire [PP_1-1 : 0] spec_request_acceptable; - wire [P_1-1 : 0] spec_request_accepted [P-1 : 0]; - wire [P-1 : 0] any_spec_request_accepted; - wire [PV-1 : 0] spec_ivc_granted_all_accepted; - wire [P-1 : 0] spec_any_ivc_grant,nonspec_any_ivc_grant; - + wire [PV-1 : 0] spec_ivc_granted_all,nonspec_ivc_granted_all; + wire [PV-1 : 0] spec_ivc_request_all,nonspec_ivc_request_all; + wire [PV-1 : 0] spec_assigned_ovc_not_full_all,nonspec_assigned_ovc_not_full_all; + wire [PVP_1-1 : 0] spec_dest_port_all,nonspec_dest_port_all; + wire [PP_1-1 : 0] spec_granted_dest_port_all,spec_granted_dest_port_all_accepted; + wire [P-1 : 0] nonspec_inport_granted_all,nonspec_outport_granted_all; + wire [PP_1-1 : 0] spec_granted_dest_port_all_pre; + wire [P_1-1 : 0] nonspec_portsel_granted [P-1 : 0]; + wire [PP_1-1 : 0] spec_request_acceptable; + wire [P_1-1 : 0] spec_request_accepted [P-1 : 0]; + wire [P-1 : 0] any_spec_request_accepted; + wire [PV-1 : 0] spec_ivc_granted_all_accepted; + wire [P-1 : 0] spec_any_ivc_grant,nonspec_any_ivc_grant; + spec_sw_alloc_sub2#( .V(V), .P(P), .SWA_ARBITER_TYPE(SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE) - ) - speculative_alloc - ( + ) speculative_alloc ( .valid_speculation (valid_speculation), .ivc_granted_all (spec_ivc_granted_all), .ivc_request_all (spec_ivc_request_all), @@ -350,16 +300,13 @@ module spec_sw_alloc2 #( .clk (clk), .reset (reset) ); - + sw_alloc_sub2#( .V (V), .P (P), .SWA_ARBITER_TYPE(SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE) - ) - nonspeculative_alloc - ( - + ) nonspeculative_alloc ( .ivc_granted_all (nonspec_ivc_granted_all), .ivc_request_all (nonspec_ivc_request_all), .assigned_ovc_not_full_all (nonspec_assigned_ovc_not_full_all), @@ -377,58 +324,54 @@ module spec_sw_alloc2 #( .clk (clk), .reset (reset) ); - - assign nonspec_ivc_request_all = ivc_request_all & ovc_is_assigned_all; - assign spec_ivc_request_all = ivc_request_all & ~ovc_is_assigned_all; - assign spec_assigned_ovc_not_full_all = {PV{1'b1}}; - assign nonspec_assigned_ovc_not_full_all = assigned_ovc_not_full_all; - assign spec_dest_port_all = dest_port_all; - assign nonspec_dest_port_all = dest_port_all; - - wire [P_1-1 : 0] nonspec_check [P-1:0]; - wire [P_1-1 : 0] spec_check [P-1:0]; - + + assign nonspec_ivc_request_all = ivc_request_all & ovc_is_assigned_all; + assign spec_ivc_request_all = ivc_request_all & ~ovc_is_assigned_all; + assign spec_assigned_ovc_not_full_all = {PV{1'b1}}; + assign nonspec_assigned_ovc_not_full_all = assigned_ovc_not_full_all; + assign spec_dest_port_all = dest_port_all; + assign nonspec_dest_port_all = dest_port_all; + + wire [P_1-1 : 0] nonspec_check [P-1:0]; + wire [P_1-1 : 0] spec_check [P-1:0]; + genvar i,j; generate - for(i=0;ij)begin: hh - assign nonspec_portsel_granted[i][j] = nonspec_outport_granted_all [j]; + for(j=0;jj)begin + assign nonspec_portsel_granted[i][j] = nonspec_outport_granted_all [j]; end //if(i==j) wires are left disconnected end//j // an speculative grant is acceptable if the non-speculative request is not granted for both inport request and outport grant - assign spec_request_acceptable[(i+1)*P_1-1 : i*P_1] = (nonspec_inport_granted_all[i])? {P_1{1'b0}} : ~nonspec_portsel_granted[i]; - assign spec_request_accepted [i]= spec_request_acceptable[(i+1)*P_1-1 : i*P_1] & spec_granted_dest_port_all_pre[(i+1)*P_1-1 : i*P_1]; + assign spec_request_acceptable[(i+1)*P_1-1 : i*P_1] = (nonspec_inport_granted_all[i])? {P_1{1'b0}} : ~nonspec_portsel_granted[i]; + assign spec_request_accepted [i]= spec_request_acceptable[(i+1)*P_1-1 : i*P_1] & spec_granted_dest_port_all_pre[(i+1)*P_1-1 : i*P_1]; assign any_spec_request_accepted [i] = |spec_request_accepted [i]; - assign spec_ivc_granted_all_accepted[(i+1)*V-1 : i*V] = (any_spec_request_accepted [i] )? spec_ivc_granted_all[(i+1)*V-1 : i*V]: {V{1'b0}}; - assign spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]= spec_request_accepted [i]; - - //synthesis translate_off - //synopsys translate_off - if(DEBUG_EN)begin :dbg - assign nonspec_check[i] = nonspec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - assign spec_check[i]= spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]; + assign spec_ivc_granted_all_accepted[(i+1)*V-1 : i*V] = (any_spec_request_accepted [i] )? spec_ivc_granted_all[(i+1)*V-1 : i*V]: {V{1'b0}}; + assign spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]= spec_request_accepted [i]; + + `ifdef SIMULATION + if(DEBUG_EN)begin : dbg + assign nonspec_check[i] = nonspec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; + assign spec_check[i]= spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]; always @(posedge clk) begin - if(nonspec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1] >0 && spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]>0 ) $display("%t: Error: Both speculative and nonspeculative is granted for one port",$time); - if(nonspec_ivc_granted_all [(i+1)*V-1 : i*V] >0 && spec_ivc_granted_all_accepted[(i+1)*V-1 : i*V]>0 ) $display("%t: Error: Both speculative and nonspeculative is granted for one port",$time); + if(nonspec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1] >0 && spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]>0 ) $display("%t: Error: Both speculative and nonspeculative is granted for one port",$time); + if(nonspec_ivc_granted_all [(i+1)*V-1 : i*V] >0 && spec_ivc_granted_all_accepted[(i+1)*V-1 : i*V]>0 ) $display("%t: Error: Both speculative and nonspeculative is granted for one port",$time); end//always end // DEBUG - //synopsys translate_on - //synthesis translate_on + `endif //SIMULATION end//i endgenerate - - assign spec_any_ivc_grant_valid = any_spec_request_accepted & spec_any_ivc_grant; - assign any_ivc_sw_request_granted_all = nonspec_any_ivc_grant | spec_any_ivc_grant_valid; - - assign granted_dest_port_all = nonspec_granted_dest_port_all | spec_granted_dest_port_all_accepted; - assign ivc_granted_all = nonspec_ivc_granted_all | spec_ivc_granted_all_accepted; - assign spec_granted_dest_port_all = spec_granted_dest_port_all_accepted; - + + assign spec_any_ivc_grant_valid = any_spec_request_accepted & spec_any_ivc_grant; + assign any_ivc_sw_request_granted_all = nonspec_any_ivc_grant | spec_any_ivc_grant_valid; + assign granted_dest_port_all = nonspec_granted_dest_port_all | spec_granted_dest_port_all_accepted; + assign ivc_granted_all = nonspec_ivc_granted_all | spec_ivc_granted_all_accepted; + assign spec_granted_dest_port_all = spec_granted_dest_port_all_accepted; endmodule @@ -442,7 +385,6 @@ module sw_alloc_sub2#( parameter P = 5, parameter SWA_ARBITER_TYPE="RRA", parameter MIN_PCK_SIZE=2 //minimum packet size in flits. The minimum value is 1. - )( ivc_granted_all, ivc_request_all, @@ -461,7 +403,7 @@ module sw_alloc_sub2#( clk, reset ); - + localparam P_1 = P-1,//assumed that no port request for itself! PV = V * P, @@ -469,73 +411,67 @@ module sw_alloc_sub2#( PVP_1 = P * VP_1, PP_1 = P_1 * P, PP = P * P; - - output [PV-1 : 0] ivc_granted_all; - input [PV-1 : 0] ivc_request_all; - input [PV-1 : 0] assigned_ovc_not_full_all; - input [PVP_1-1 : 0] dest_port_all; - output [PP_1-1 : 0] granted_dest_port_all; - output [P-1 : 0] inport_granted_all; - output [P-1 : 0] outport_granted_all; - output [PV-1 : 0] first_arbiter_granted_ivc_all; - output [PP_1-1 : 0] first_arbiter_granted_port_all; - output [P-1 : 0] any_ivc_grant; + + output [PV-1 : 0] ivc_granted_all; + input [PV-1 : 0] ivc_request_all; + input [PV-1 : 0] assigned_ovc_not_full_all; + input [PVP_1-1 : 0] dest_port_all; + output [PP_1-1 : 0] granted_dest_port_all; + output [P-1 : 0] inport_granted_all; + output [P-1 : 0] outport_granted_all; + output [PV-1 : 0] first_arbiter_granted_ivc_all; + output [PP_1-1 : 0] first_arbiter_granted_port_all; + output [P-1 : 0] any_ivc_grant; input [PV-1 : 0 ] vc_weight_is_consumed_all; input [P-1 : 0 ] iport_weight_is_consumed_all; input [PV-1 : 0] pck_is_single_flit_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; input clk; input reset; - + //separte input per port - wire [V-1 : 0] ivc_granted [P-1 : 0]; - wire [V-1 : 0] ivc_request [P-1 : 0]; - wire [V-1 : 0] ivc_not_full [P-1 : 0]; - wire [VP_1-1 : 0] dest_port_ivc [P-1 : 0]; - wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; - + wire [V-1 : 0] ivc_granted [P-1 : 0]; + wire [V-1 : 0] ivc_request [P-1 : 0]; + wire [V-1 : 0] ivc_not_full [P-1 : 0]; + wire [VP_1-1 : 0] dest_port_ivc [P-1 : 0]; + wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; + // internal wires - wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and - wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter - wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer - wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; - wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; + wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and + wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter + wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer + wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; + wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; wire [P_1-1 : 0] second_arbiter_weight_consumed [P-1 : 0]; wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; wire [P-1 : 0] winner_weight_consumed; - + wire [P_1-1 : 0] single_flit_granted_dst [P-1 : 0]; wire [PP-1 : 0] single_flit_granted_dst_all; wire [V-1 : 0] pck_is_single_flit [P-1 : 0]; wire [P-1 : 0] single_flit_pck_local_grant; - + genvar i,j; - generate - - for(i=0;i< P;i=i+1) begin :port_loop + generate + for(i=0;i< P;i=i+1) begin : P_ //assign in/out to the port based wires //output - assign ivc_granted_all [(i+1)*V-1 : i*V] = ivc_granted [i]; - assign granted_dest_port_all [(i+1)*P_1-1 : i*P_1] = granted_dest_port[i]; - assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]= first_arbiter_grant[i]; + assign ivc_granted_all [(i+1)*V-1 : i*V] = ivc_granted [i]; + assign granted_dest_port_all [(i+1)*P_1-1 : i*P_1] = granted_dest_port[i]; + assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V] = first_arbiter_grant[i]; //input - assign ivc_request[i] = ivc_request_all [(i+1)*V-1 : i*V]; - assign ivc_not_full[i] = assigned_ovc_not_full_all[(i+1)*V-1 : i*V]; - assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; - assign vc_weight_is_consumed[i] = vc_weight_is_consumed_all [(i+1)*V-1 : i*V]; - + assign ivc_request[i] = ivc_request_all [(i+1)*V-1 : i*V]; + assign ivc_not_full[i] = assigned_ovc_not_full_all[(i+1)*V-1 : i*V]; + assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; + assign vc_weight_is_consumed[i] = vc_weight_is_consumed_all [(i+1)*V-1 : i*V]; //mask - assign ivc_masked[i] = ivc_request[i] & ivc_not_full[i]; - - - //first level arbiter + assign ivc_masked[i] = ivc_request[i] & ivc_not_full[i]; + //first level arbiter swa_input_port_arbiter #( .ARBITER_WIDTH(V), .EXT_P_EN(0), .ARBITER_TYPE(SWA_ARBITER_TYPE) - ) - input_arbiter - ( + )input_arbiter ( .ext_pr_en_i(1'b1),// not used here anyway .request(ivc_masked [i]), .grant(first_arbiter_grant[i]), @@ -545,60 +481,50 @@ module sw_alloc_sub2#( .vc_weight_is_consumed(vc_weight_is_consumed[i]), .winner_weight_consumed(winner_weight_consumed[i]) ); - //destination port multiplexer one_hot_mux #( .IN_WIDTH (VP_1), .SEL_WIDTH(V) - ) - multiplexer - ( + ) multiplexer ( .mux_in(dest_port_ivc [i]), .mux_out(dest_port [i]), .sel(first_arbiter_grant [i]) - ); - assign first_arbiter_granted_port_all[(i+1)*P_1-1 : i*P_1] = dest_port [i]; - if(MIN_PCK_SIZE == 1) begin :single_flit_supported + assign first_arbiter_granted_port_all[(i+1)*P_1-1 : i*P_1] = dest_port [i]; + if(MIN_PCK_SIZE == 1) begin assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; //single_flit req multiplexer one_hot_mux #( - .IN_WIDTH (V), - .SEL_WIDTH (V) - ) - multiplexer2 - ( + .IN_WIDTH (V), + .SEL_WIDTH (V) + ) multiplexer2 ( .mux_in (pck_is_single_flit [i]), .mux_out (single_flit_pck_local_grant[i]), .sel (first_arbiter_grant[i]) ); - + assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; - + add_sw_loc_one_hot #( .P(P), .SW_LOC(i) - ) - add_sw_loc - ( + ) add_sw_loc ( .destport_in(single_flit_granted_dst[i]), .destport_out(single_flit_granted_dst_all[(i+1)*P-1 : i*P]) ); - - end else begin : single_flit_notsupported + end else begin assign single_flit_pck_local_grant[i] = 1'b0; assign single_flit_granted_dst[i] = {P_1{1'b0}}; assign single_flit_granted_dst_all[(i+1)*P-1 : i*P]={P{1'b0}}; end - //second arbiter input/output generate - for(j=0;jj)begin: hh + end else if(i>j)begin assign second_arbiter_request[i][j] = dest_port [j][i-1]; // assign second_arbiter_weight_consumed[i][j] = winner_weight_consumed[j]; assign second_arbiter_weight_consumed[i][j] = iport_weight_is_consumed_all[j]; @@ -606,14 +532,12 @@ module sw_alloc_sub2#( end //if(i==j) wires are left disconnected end - + //second level arbiter swa_output_port_arbiter #( .ARBITER_WIDTH(P_1), .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA - ) - output_arbiter - ( + ) output_arbiter( .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA .clk(clk), .reset(reset), @@ -621,28 +545,24 @@ module sw_alloc_sub2#( .grant(second_arbiter_grant [i]), .any_grant(outport_granted_all [i]) ); - + //any ivc assign any_ivc_grant[i] = | granted_dest_port[i]; - assign ivc_granted[i] = (any_ivc_grant[i]) ? first_arbiter_grant[i] : {V{1'b0}}; - assign inport_granted_all[i] =any_ivc_grant[i]; end//for i endgenerate - + custom_or #( .IN_NUM(P), .OUT_WIDTH(P) - ) - or_dst - ( + ) or_dst ( .or_in(single_flit_granted_dst_all), .or_out(granted_dst_is_from_a_single_flit_pck) ); - endmodule + module spec_sw_alloc_sub2#( parameter V = 4, parameter P = 5, @@ -667,7 +587,7 @@ module spec_sw_alloc_sub2#( clk, reset ); - + localparam P_1 = P-1,//assumed that no port request for itself! PV = V * P, @@ -675,73 +595,67 @@ module spec_sw_alloc_sub2#( PVP_1 = P * VP_1, PP_1 = P_1 * P, PP = P * P; - - input [PV-1 : 0] valid_speculation; - output [PV-1 : 0] ivc_granted_all; - input [PV-1 : 0] ivc_request_all; - input [PV-1 : 0] assigned_ovc_not_full_all; - input [PVP_1-1 : 0] dest_port_all; - output [PP_1-1 : 0] granted_dest_port_all; - output [P-1 : 0] inport_granted_all; - output [P-1 : 0] outport_granted_all; - output [PV-1 : 0] first_arbiter_granted_ivc_all; - output [PP_1-1 : 0] first_arbiter_granted_port_all; - output [P-1 : 0] any_ivc_grant; + + input [PV-1 : 0] valid_speculation; + output [PV-1 : 0] ivc_granted_all; + input [PV-1 : 0] ivc_request_all; + input [PV-1 : 0] assigned_ovc_not_full_all; + input [PVP_1-1 : 0] dest_port_all; + output [PP_1-1 : 0] granted_dest_port_all; + output [P-1 : 0] inport_granted_all; + output [P-1 : 0] outport_granted_all; + output [PV-1 : 0] first_arbiter_granted_ivc_all; + output [PP_1-1 : 0] first_arbiter_granted_port_all; + output [P-1 : 0] any_ivc_grant; input [PV-1 : 0 ] vc_weight_is_consumed_all; input [P-1 : 0 ] iport_weight_is_consumed_all; input [PV-1 : 0] pck_is_single_flit_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; input clk, reset; - + //separte input per port - wire [V-1 : 0] ivc_granted [P-1 : 0]; - wire [V-1 : 0] ivc_request [P-1 : 0]; - wire [V-1 : 0] ivc_not_full [P-1 : 0]; - wire [VP_1-1 : 0] dest_port_ivc [P-1 : 0]; - wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; - + wire [V-1 : 0] ivc_granted [P-1 : 0]; + wire [V-1 : 0] ivc_request [P-1 : 0]; + wire [V-1 : 0] ivc_not_full [P-1 : 0]; + wire [VP_1-1 : 0] dest_port_ivc [P-1 : 0]; + wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; + // internal wires - wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and - wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter - wire [V-1 : 0] first_arbiter_grant_masked [P-1 : 0];//output of first arbiter - wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer - wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; - wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; + wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and + wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter + wire [V-1 : 0] first_arbiter_grant_masked [P-1 : 0];//output of first arbiter + wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer + wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; + wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; wire [P_1-1 : 0] second_arbiter_weight_consumed [P-1 : 0]; wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; - wire [P-1 : 0] winner_weight_consumed; - + wire [P-1 : 0] winner_weight_consumed; wire [P_1-1 : 0] single_flit_granted_dst [P-1 : 0]; wire [PP-1 : 0] single_flit_granted_dst_all; wire [V-1 : 0] pck_is_single_flit [P-1 : 0]; - wire [P-1 : 0] single_flit_pck_local_grant; - + wire [P-1 : 0] single_flit_pck_local_grant; + genvar i,j; - generate - - for(i=0;i< P;i=i+1) begin :port_loop + generate + for(i=0;i< P;i=i+1) begin : P_ //assign in/out to the port based wires //output - assign ivc_granted_all [(i+1)*V-1 : i*V] = ivc_granted [i]; - assign granted_dest_port_all [(i+1)*P_1-1: i*P_1] = granted_dest_port[i]; - assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V] = first_arbiter_grant_masked[i]; + assign ivc_granted_all [(i+1)*V-1 : i*V] = ivc_granted [i]; + assign granted_dest_port_all [(i+1)*P_1-1: i*P_1] = granted_dest_port[i]; + assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V] = first_arbiter_grant_masked[i]; //input - assign ivc_request[i] = ivc_request_all [(i+1)*V-1 : i*V]; - assign ivc_not_full[i] = assigned_ovc_not_full_all[(i+1)*V-1 : i*V]; - assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; + assign ivc_request[i] = ivc_request_all [(i+1)*V-1 : i*V]; + assign ivc_not_full[i] = assigned_ovc_not_full_all[(i+1)*V-1 : i*V]; + assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; assign vc_weight_is_consumed[i] = vc_weight_is_consumed_all [(i+1)*V-1 : i*V]; - //mask - assign ivc_masked[i] = ivc_request[i] & ivc_not_full[i]; - + assign ivc_masked[i] = ivc_request[i] & ivc_not_full[i]; //first level arbiter swa_input_port_arbiter #( .ARBITER_WIDTH(V), .EXT_P_EN(0), .ARBITER_TYPE(SWA_ARBITER_TYPE) - ) - input_arbiter - ( + ) input_arbiter ( .ext_pr_en_i(1'b1),// not used here anyway .request(ivc_masked [i]), .grant(first_arbiter_grant[i]), @@ -750,107 +664,83 @@ module spec_sw_alloc_sub2#( .reset(reset), .vc_weight_is_consumed(vc_weight_is_consumed[i]), .winner_weight_consumed(winner_weight_consumed[i]) - ); - + ); // mask unvalid speculation - assign first_arbiter_grant_masked[i]= first_arbiter_grant[i] & valid_speculation [(i+1)*V-1 : i*V]; - - if(MIN_PCK_SIZE == 1) begin :single_flit_supported - + assign first_arbiter_grant_masked[i]= first_arbiter_grant[i] & valid_speculation [(i+1)*V-1 : i*V]; + if(MIN_PCK_SIZE == 1) begin assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; //single_flit req multiplexer one_hot_mux #( - .IN_WIDTH (V), - .SEL_WIDTH (V) - ) - multiplexer2 - ( + .IN_WIDTH (V), + .SEL_WIDTH (V) + ) multiplexer2 ( .mux_in (pck_is_single_flit [i]), .mux_out (single_flit_pck_local_grant[i]), .sel (first_arbiter_grant[i]) ); - - assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; - + assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; add_sw_loc_one_hot #( .P(P), .SW_LOC(i) - ) - add_sw_loc - ( + ) add_sw_loc ( .destport_in(single_flit_granted_dst[i]), .destport_out(single_flit_granted_dst_all[(i+1)*P-1 : i*P]) ); - - end else begin : single_flit_notsupported + end else begin assign single_flit_pck_local_grant[i] = 1'b0; assign single_flit_granted_dst[i] = {P_1{1'b0}}; assign single_flit_granted_dst_all[(i+1)*P-1 : i*P]={P{1'b0}}; end - //destination port multiplexer one_hot_mux #( .IN_WIDTH (VP_1), .SEL_WIDTH (V) - ) - multiplexer - ( + ) multiplexer ( .mux_in (dest_port_ivc [i]), .mux_out (dest_port [i]), .sel (first_arbiter_grant_masked[i]) ); - assign first_arbiter_granted_port_all[(i+1)*P_1-1 : i*P_1] = dest_port [i]; - - + assign first_arbiter_granted_port_all[(i+1)*P_1-1 : i*P_1] = dest_port [i]; //second arbiter input/output generate - for(j=0;jj)begin: hh + end else if(i>j)begin assign second_arbiter_request[i][j] = dest_port [j][i-1]; //assign second_arbiter_weight_consumed[i][j] =winner_weight_consumed[j]; - assign second_arbiter_weight_consumed[i][j] =iport_weight_is_consumed_all[j]; - assign granted_dest_port[j][i-1] = second_arbiter_grant [i][j] ; + assign second_arbiter_weight_consumed[i][j] = iport_weight_is_consumed_all[j]; + assign granted_dest_port[j][i-1] = second_arbiter_grant [i][j] ; end //if(i==j) wires are left disconnected - end - + end //second level arbiter swa_output_port_arbiter #( .ARBITER_WIDTH(P_1), .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA - ) - output_arbiter - ( + ) output_arbiter ( .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA .clk(clk), .reset(reset), .request(second_arbiter_request [i]), .grant(second_arbiter_grant [i]), .any_grant(outport_granted_all [i]) - ); - + ); //any ivc assign any_ivc_grant[i] = | granted_dest_port[i]; - assign ivc_granted[i] = (any_ivc_grant[i]) ? first_arbiter_grant_masked[i] : {V{1'b0}}; - assign inport_granted_all[i] =any_ivc_grant[i]; - end//for + end//for P_ endgenerate - + custom_or #( .IN_NUM(P), .OUT_WIDTH(P) - ) - or_dst - ( + ) or_dst ( .or_in(single_flit_granted_dst_all), .or_out(granted_dst_is_from_a_single_flit_pck) ); - -endmodule +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv b/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv index 375ced9..94fb0a1 100755 --- a/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv +++ b/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv @@ -1,31 +1,30 @@ `include "pronoc_def.v" /********************************************************************** -** File: combined_vc_sw_alloc.v +** File: combined_vc_sw_alloc.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** combined VC/SW allocator. VC allocation is done in parallel with swich allocator -** for header flits which are successfully get sw grant +** Description: +** combined VC/SW allocator. VC allocation is done in parallel with swich allocator +** for header flits which are successfully get sw grant *************************************/ - module combined_vc_sw_alloc #( parameter NOC_ID=0, parameter P = 5 //port number @@ -50,10 +49,9 @@ module combined_vc_sw_alloc #( granted_dst_is_from_a_single_flit_pck, clk, reset - ); - `NOC_CONF - + `NOC_CONF + localparam PV = V * P, PVV = PV * V, @@ -64,8 +62,6 @@ module combined_vc_sw_alloc #( input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; input [PVP_1-1 : 0] dest_port_all; input [PVV-1 : 0] masked_ovc_request_all; - - output [PV-1 : 0] ovc_allocated_all; output [PVV-1 : 0] granted_ovc_num_all; output [PV-1 : 0] ivc_num_getting_ovc_grant; @@ -78,14 +74,11 @@ module combined_vc_sw_alloc #( output [PP_1-1 : 0] nonspec_granted_dest_port_all; output [PP_1-1 : 0] spec_granted_dest_port_all; output [PVV-1 : 0] spec_ovc_num_all; - input [PV-1 : 0] vc_weight_is_consumed_all; input [P-1 : 0] iport_weight_is_consumed_all; - output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - input clk,reset; - + wire [PV-1 : 0] ivc_request_all; wire [PV-1 : 0] assigned_ovc_not_full_all; wire [PV-1 : 0] ovc_is_assigned_all; @@ -93,22 +86,16 @@ module combined_vc_sw_alloc #( genvar i; generate - for (i=0; i7)begin :cmb_v2 - - comb_nonspec_v2_allocator #( + if(V>7)begin : cmb_v2 + comb_nonspec_v2_allocator #( .V(V), .P(P), .FIRST_ARBITER_EXT_P_EN(FIRST_ARBITER_EXT_P_EN), .SWA_ARBITER_TYPE (SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE), .SELF_LOOP_EN(SELF_LOOP_EN) - ) - nonspec_comb - ( + ) nonspec_comb ( .dest_port_all(dest_port_all), .masked_ovc_request_all(masked_ovc_request_all), .ovc_is_assigned_all(ovc_is_assigned_all), @@ -253,17 +227,13 @@ module combined_vc_sw_alloc #( .clk(clk), .reset(reset) ); - end else begin :cmb_v1 - comb_nonspec_allocator #( .NOC_ID(NOC_ID), .P(P) - ) - nonspec_comb - ( - .ivc_info(ivc_info), - .dest_port_all(dest_port_all), + ) nonspec_comb ( + .ivc_info(ivc_info), + .dest_port_all(dest_port_all), .masked_ovc_request_all(masked_ovc_request_all), .ovc_allocated_all(ovc_allocated_all), .granted_ovc_num_all(granted_ovc_num_all), @@ -281,11 +251,10 @@ module combined_vc_sw_alloc #( .reset(reset) ); end - assign nonspec_granted_dest_port_all = granted_dest_port_all; assign spec_granted_dest_port_all = {PP_1{1'bx}}; assign spec_ovc_num_all = {PVV{1'bx}}; assign spec_first_arbiter_granted_ivc_all = nonspec_first_arbiter_granted_ivc_all ; end endgenerate -endmodule +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.v b/mpsoc/rtl/src_noc/congestion_analyzer.v index 486e83b..544fabb 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.v +++ b/mpsoc/rtl/src_noc/congestion_analyzer.v @@ -1,173 +1,137 @@ -`timescale 1ns/1ps +`include "pronoc_def.v" /********************************************************************** -** File: congestion_analyzer.v -** -** Copyright (C) 2014-2017 Alireza Monemi -** -** This file is part of ProNoC +** File: congestion_analyzer.v +** +** Copyright (C) 2014-2017 Alireza Monemi +** +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** This file includes all files for getting congestion information and -** Port selection modules for supporting adaptive routing +** Description: +** This file includes all files for getting congestion information and +** Port selection modules for supporting adaptive routing ** **************************************************************/ - - - - /***************************** - - port_presel - - *****************************/ - - - /*************************************** - - port_presel_based_dst_ports_vc - CONGESTION_INDEX==0 +* +* port_presel_based_dst_ports_vc +* CONGESTION_INDEX==0 ***************************************/ - - //congestion analyzer based on number of occupied VCs module port_presel_based_dst_ports_vc #( parameter PPSw=4, - parameter P = 5, - parameter V = 4 - ) - ( + parameter P = 5, + parameter V = 4 + )( ovc_status, port_pre_sel - ); - + ); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 vc_counter[Y_PLUS]); - assign conjestion_cmp[X_MINUS_Y_PLUS] = (vc_counter[X_MINUS] > vc_counter[Y_PLUS]); - assign conjestion_cmp[X_PLUS_Y_MINUS] = (vc_counter[X_PLUS] > vc_counter[Y_MINUS]); - assign conjestion_cmp[X_MINUS_Y_MINUS]= (vc_counter[X_MINUS] > vc_counter[Y_MINUS]); - + localparam + X_PLUS_Y_PLUS = 3, + X_MINUS_Y_PLUS = 1, + X_PLUS_Y_MINUS = 2, + X_MINUS_Y_MINUS= 0; + + assign conjestion_cmp[X_PLUS_Y_PLUS] = (vc_counter[X_PLUS] > vc_counter[Y_PLUS]); + assign conjestion_cmp[X_MINUS_Y_PLUS] = (vc_counter[X_MINUS] > vc_counter[Y_PLUS]); + assign conjestion_cmp[X_PLUS_Y_MINUS] = (vc_counter[X_PLUS] > vc_counter[Y_MINUS]); + assign conjestion_cmp[X_MINUS_Y_MINUS]= (vc_counter[X_MINUS] > vc_counter[Y_MINUS]); //assign port_pre_sel = conjestion_cmp; - - assign port_pre_sel = conjestion_cmp; - - - - - - endmodule - +endmodule + /************************************* -* -* port_presel_based_dst_ports_credit -* CONGESTION_INDEX==1 +* port_presel_based_dst_ports_credit +* CONGESTION_INDEX==1 *************************************/ - - //congestion analyzer based on number of total available credit of a port module port_presel_based_dst_ports_credit #( parameter PPSw=4, - parameter P = 5, - parameter V = 4, - parameter B = 4 -) -( + parameter P = 5, + parameter V = 4, + parameter B = 4 +)( credit_decreased_all, credit_increased_all, port_pre_sel, @@ -175,286 +139,199 @@ module port_presel_based_dst_ports_credit #( reset ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 congestion_y_plus)? YDIR : XDIR; + assign conjestion_cmp[X_PLUS_Y_PLUS] = (congestion_x_plus > congestion_y_plus)? YDIR : XDIR; assign conjestion_cmp[X_MINUS_Y_PLUS] = (congestion_x_min > congestion_y_plus)? YDIR : XDIR; assign conjestion_cmp[X_PLUS_Y_MINUS] = (congestion_x_plus > congestion_y_min)? YDIR : XDIR; assign conjestion_cmp[X_MINUS_Y_MINUS]= (congestion_x_min > congestion_y_min)? YDIR : XDIR; - - - - // assign port_pre_sel = conjestion_cmp; - pronoc_register #(.W(PPSw)) reg1 (.in(conjestion_cmp ), .reset(reset), .clk(clk), .out(port_pre_sel)); - - + pronoc_register #(.W(PPSw)) reg1 (.in(conjestion_cmp ), .reset(reset), .clk(clk), .out(port_pre_sel)); endmodule /********************************* - -port_presel_based_dst_routers_ovc - CONGESTION_INDEX==8,10 +* port_presel_based_dst_routers_ovc +* CONGESTION_INDEX==8,10 ********************************/ - - module port_presel_based_dst_routers_ovc #( parameter PPSw=4, parameter P=5, parameter V=4, parameter CONGw=2 //congestion width per port -) -( +)( port_pre_sel, congestion_in_all ); - - - localparam P_1 = P-1, - CONG_ALw= CONGw* P; // congestion width per router; - - - input [CONG_ALw-1 : 0] congestion_in_all; - output [PPSw-1 : 0] port_pre_sel; - - - - - /************* - N - Q1 | Q3 - w--------E - Q0 | Q2 - S - ***************/ - - localparam Q3 = 3, - Q1 = 1, - Q2 = 2, - Q0 = 0; - - localparam EAST = 0, - NORTH= 1, - WEST = 2, - SOUTH= 3; - - localparam XDIR =1'b0, - YDIR =1'b1; + localparam + P_1 = P-1, + CONG_ALw = CONGw* P; // congestion width per router; - wire [CONGw-1 : 0] congestion_in [P_1-1 : 0]; - assign {congestion_in[SOUTH],congestion_in[WEST],congestion_in[NORTH],congestion_in[EAST]} = congestion_in_all[CONG_ALw-1 : CONGw]; - - wire [(CONGw/2)-1 : 0]cong_from_west_Q1 , cong_from_west_Q0; - wire [(CONGw/2)-1 : 0]cong_from_south_Q0 , cong_from_south_Q2; - wire [(CONGw/2)-1 : 0]cong_from_east_Q2 , cong_from_east_Q3; - wire [(CONGw/2)-1 : 0]cong_from_north_Q3 , cong_from_north_Q1; + input [CONG_ALw-1 : 0] congestion_in_all; + output [PPSw-1 : 0] port_pre_sel; + /************* + * N + * Q1 | Q3 + * w--------E + * Q0 | Q2 + * S + ***************/ + localparam + Q3 = 3, + Q1 = 1, + Q2 = 2, + Q0 = 0; + localparam + EAST = 0, + NORTH = 1, + WEST = 2, + SOUTH = 3; + localparam + XDIR =1'b0, + YDIR =1'b1; + wire [CONGw-1 : 0] congestion_in [P_1-1 : 0]; + assign {congestion_in[SOUTH],congestion_in[WEST],congestion_in[NORTH],congestion_in[EAST]} = congestion_in_all[CONG_ALw-1 : CONGw]; + wire [(CONGw/2)-1 : 0]cong_from_west_Q1 , cong_from_west_Q0; + wire [(CONGw/2)-1 : 0]cong_from_south_Q0 , cong_from_south_Q2; + wire [(CONGw/2)-1 : 0]cong_from_east_Q2 , cong_from_east_Q3; + wire [(CONGw/2)-1 : 0]cong_from_north_Q3 , cong_from_north_Q1; - - assign {cong_from_west_Q1 ,cong_from_west_Q0 }=congestion_in[WEST]; assign {cong_from_south_Q0 ,cong_from_south_Q2 }=congestion_in[SOUTH]; assign {cong_from_east_Q2 ,cong_from_east_Q3 }=congestion_in[EAST]; assign {cong_from_north_Q3 ,cong_from_north_Q1 }=congestion_in[NORTH]; - /**************** - congestion: - 0: list congested - 3: most congested - pre_sel - 0: xdir - 1: ydir - *******************/ - wire [P_1-1 : 0] conjestion_cmp; - - - - assign conjestion_cmp[Q3] = (cong_from_east_Q3 > cong_from_north_Q3)? YDIR :XDIR; - assign conjestion_cmp[Q2] = (cong_from_east_Q2 > cong_from_south_Q2)? YDIR :XDIR; - assign conjestion_cmp[Q1] = (cong_from_west_Q1 > cong_from_north_Q1)? YDIR :XDIR; - assign conjestion_cmp[Q0] = (cong_from_west_Q0 > cong_from_south_Q0)? YDIR :XDIR; - - - - - - - assign port_pre_sel = conjestion_cmp; - - - - - + *congestion: + * 0: list congested + * 3: most congested + *pre_sel + * 0: xdir + * 1: ydir + ********************/ + wire [P_1-1 : 0] conjestion_cmp; + assign conjestion_cmp[Q3] = (cong_from_east_Q3 > cong_from_north_Q3)? YDIR :XDIR; + assign conjestion_cmp[Q2] = (cong_from_east_Q2 > cong_from_south_Q2)? YDIR :XDIR; + assign conjestion_cmp[Q1] = (cong_from_west_Q1 > cong_from_north_Q1)? YDIR :XDIR; + assign conjestion_cmp[Q0] = (cong_from_west_Q0 > cong_from_south_Q0)? YDIR :XDIR; + assign port_pre_sel = conjestion_cmp; endmodule /*********************** - - port_pre_sel_gen - - +* port_pre_sel_gen ************************/ - - - module port_pre_sel_gen #( parameter PPSw=4, parameter P=5, @@ -463,8 +340,7 @@ module port_pre_sel_gen #( parameter CONGESTION_INDEX=2, parameter CONGw=2, parameter ROUTE_TYPE="ADAPTIVE", - parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001 - + parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001 )( port_pre_sel, ovc_status, @@ -474,230 +350,166 @@ module port_pre_sel_gen #( credit_increased_all, reset, clk - ); - localparam P_1 = P-1, - PV = P * V, - CONG_ALw = CONGw * P; - - output [PPSw-1 : 0] port_pre_sel; - input [PV-1 : 0] ovc_status; - input [PV-1 : 0] ovc_avalable_all; - input [PV-1 : 0] credit_decreased_all; - input [PV-1 : 0] credit_increased_all; - input [CONG_ALw-1 : 0] congestion_in_all; - input reset,clk; - + localparam + P_1 = P-1, + PV = P * V, + CONG_ALw = CONGw * P; + output [PPSw-1 : 0] port_pre_sel; + input [PV-1 : 0] ovc_status; + input [PV-1 : 0] ovc_avalable_all; + input [PV-1 : 0] credit_decreased_all; + input [PV-1 : 0] credit_increased_all; + input [CONG_ALw-1 : 0] congestion_in_all; + input reset,clk; -generate + generate /* verilator lint_off WIDTH */ - if(ROUTE_TYPE == "DETERMINISTIC") begin : detrministic + if(ROUTE_TYPE == "DETERMINISTIC") begin : detrministic /* verilator lint_on WIDTH */ - assign port_pre_sel = {PPSw{1'b0}}; - + assign port_pre_sel = {PPSw{1'b0}}; end else begin : adaptive if(CONGESTION_INDEX==0) begin:indx0 - - port_presel_based_dst_ports_vc #( - .PPSw(PPSw), - .P(P), - .V(V) - - ) - port_presel_gen - ( - .ovc_status (ovc_status [PV-1 : V]), - .port_pre_sel(port_pre_sel) - - - ); - + port_presel_based_dst_ports_vc #( + .PPSw(PPSw), + .P(P), + .V(V) + ) port_presel_gen ( + .ovc_status (ovc_status [PV-1 : V]), + .port_pre_sel(port_pre_sel) + ); end else if(CONGESTION_INDEX==1) begin :indx1 - - port_presel_based_dst_ports_credit #( - .PPSw(PPSw), - .P(P), - .V(V), - .B(B) - ) - port_presel_gen - ( - .credit_decreased_all (credit_decreased_all [PV-1 : V]),//remove local port signals - .credit_increased_all (credit_increased_all [PV-1 : V]), - .port_pre_sel (port_pre_sel), - .clk (clk), - .reset (reset) - ); - end else if ( (CONGESTION_INDEX==2) || (CONGESTION_INDEX==3) || - (CONGESTION_INDEX==4) || (CONGESTION_INDEX==5) || - (CONGESTION_INDEX==6) || (CONGESTION_INDEX==7) || - (CONGESTION_INDEX==9) || - (CONGESTION_INDEX==11)|| (CONGESTION_INDEX==12)) begin :dst_vc - - mesh_torus_port_presel_based_dst_routers_vc #( - .PPSw(PPSw), - .P(P), - .CONGw(CONGw) - ) - port_presel_gen - ( - .congestion_in_all(congestion_in_all), - .port_pre_sel(port_pre_sel), - .reset(reset), - .clk(clk) - ); - end else if((CONGESTION_INDEX==8) || (CONGESTION_INDEX==10) )begin :dst_ovc + port_presel_based_dst_ports_credit #( + .PPSw(PPSw), + .P(P), + .V(V), + .B(B) + ) port_presel_gen ( + .credit_decreased_all (credit_decreased_all [PV-1 : V]),//remove local port signals + .credit_increased_all(credit_increased_all [PV-1 : V]), + .port_pre_sel(port_pre_sel), + .clk(clk), + .reset(reset) + ); + end else if ( + (CONGESTION_INDEX==2) || (CONGESTION_INDEX==3) || + (CONGESTION_INDEX==4) || (CONGESTION_INDEX==5) || + (CONGESTION_INDEX==6) || (CONGESTION_INDEX==7) || + (CONGESTION_INDEX==9) || + (CONGESTION_INDEX==11)|| (CONGESTION_INDEX==12)) begin :dst_vc + + mesh_torus_port_presel_based_dst_routers_vc #( + .PPSw(PPSw), + .P(P), + .CONGw(CONGw) + ) port_presel_gen ( + .congestion_in_all(congestion_in_all), + .port_pre_sel(port_pre_sel), + .reset(reset), + .clk(clk) + ); + end else if((CONGESTION_INDEX==8) || (CONGESTION_INDEX==10) )begin :dst_ovc port_presel_based_dst_routers_ovc #( .PPSw(PPSw), .P(P), .V(V), .CONGw(CONGw) - ) - port_presel_gen - ( + ) port_presel_gen ( .port_pre_sel(port_pre_sel), .congestion_in_all(congestion_in_all) ); - - end end endgenerate endmodule - - - /********************************* - - congestion_out_gen - - ********************************/ - - - - - - /******************************* - - congestion based on number of active ivc - CONGESTION_INDEX==2 CONGw = 2 - CONGESTION_INDEX==3 CONGw = 3 - ********************************/ - module congestion_out_based_ivc_req #( +/******************************* +* congestion based on number of active ivc +* CONGESTION_INDEX==2 CONGw = 2 +* CONGESTION_INDEX==3 CONGw = 3 +* ********************************/ +module congestion_out_based_ivc_req #( parameter P=5, parameter V=4, - parameter CONGw = 2 //congestion width per port - - ) - ( + parameter CONGw = 2 //congestion width per port +)( ivc_request_all, congestion_out_all - - ); +); + localparam + PV = (V*P), + CONG_ALw = (CONGw* P); // congestion width per router; - - localparam PV = (V * P), - CONG_ALw= (CONGw* P); // congestion width per router; - - - - - input [PV-1 : 0] ivc_request_all; - output [CONG_ALw-1 : 0] congestion_out_all; - - - wire [CONGw-1 : 0] congestion_out ; + input [PV-1 : 0] ivc_request_all; + output [CONG_ALw-1 : 0] congestion_out_all; + wire [CONGw-1 : 0] congestion_out ; parallel_count_normalize #( - .INw (PV), - .OUTw (CONGw) - ) - ivc_req_counter - ( - .in (ivc_request_all), - .out (congestion_out) - + .INw (PV), + .OUTw (CONGw) + ) ivc_req_counter ( + .in (ivc_request_all), + .out (congestion_out) ); - - assign congestion_out_all = {P{congestion_out}}; - endmodule - - - /******************************* - - congestion based on number of - active ivc requests that are not granted - CONGESTION_INDEX==4 CONGw = 2 - CONGESTION_INDEX==5 CONGw = 3 +* congestion based on number of +* active ivc requests that are not granted +* CONGESTION_INDEX==4 CONGw = 2 +* CONGESTION_INDEX==5 CONGw = 3 ********************************/ - module congestion_out_based_ivc_notgrant #( +module congestion_out_based_ivc_notgrant #( parameter P=5, parameter V=4, parameter CONGw=2 //congestion width per port - - ) - ( +)( ivc_request_all, congestion_out_all, ivc_num_getting_sw_grant, clk, reset - - ); - +); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 ((MAX_IN *i)/OUT_ON_HOT_NUM)) && (in<= ((MAX_IN *(i+1))/OUT_ON_HOT_NUM))); end - /* verilator lint_on WIDTH */ + /* verilator lint_off WIDTH */ + if(i==0) begin : i0 assign one_hot_out[i]= (in<= (MAX_IN /OUT_ON_HOT_NUM)); end + else begin :ib0 assign one_hot_out[i]= ((in> ((MAX_IN *i)/OUT_ON_HOT_NUM)) && (in<= ((MAX_IN *(i+1))/OUT_ON_HOT_NUM))); end + /* verilator lint_on WIDTH */ end//for endgenerate - - one_hot_to_bin#( .ONE_HOT_WIDTH(OUT_ON_HOT_NUM) - ) - conv - ( + )cnv ( .one_hot_code(one_hot_out), .bin_code(out) ); - - - endmodule - - - - - +endmodule - - - - - - - /************************** - - - congestion_out_gen - - -**************************/ - - - - + congestion_out_gen +*************************/ module congestion_out_gen #( parameter P=5, parameter V=4, parameter ROUTE_TYPE ="ADAPTIVE", parameter CONGESTION_INDEX=2, parameter CONGw=2 - -) -( - ivc_request_all, - ivc_num_getting_sw_grant, - ovc_avalable_all, - congestion_out_all, - clk, - reset +)( + ivc_request_all, + ivc_num_getting_sw_grant, + ovc_avalable_all, + congestion_out_all, + clk, + reset ); -localparam PV = P*V, - CONG_ALw = CONGw* P; // congestion width per router;; - - input [PV-1 : 0] ovc_avalable_all; - input [PV-1 : 0] ivc_request_all; - input [PV-1 : 0] ivc_num_getting_sw_grant; - output [CONG_ALw-1 : 0] congestion_out_all; - input clk,reset; - - wire [CONG_ALw-1 : 0] congestion_out_all_next; -generate -if(ROUTE_TYPE != "DETERMINISTIC") begin :adpt +localparam + PV = P*V, + CONG_ALw = CONGw* P; // congestion width per router;; + + input [PV-1 : 0] ovc_avalable_all; + input [PV-1 : 0] ivc_request_all; + input [PV-1 : 0] ivc_num_getting_sw_grant; + output [CONG_ALw-1 : 0] congestion_out_all; + input clk,reset; + + wire [CONG_ALw-1 : 0] congestion_out_all_next; + generate + if(ROUTE_TYPE != "DETERMINISTIC") begin :adpt if((CONGESTION_INDEX==2) || (CONGESTION_INDEX==3)) begin :based_ivc - congestion_out_based_ivc_req #( - .P(P), - .V(V), - .CONGw(CONGw) - ) - the_congestion_out_gen - ( - .ivc_request_all(ivc_request_all), - .congestion_out_all(congestion_out_all_next) - ); + congestion_out_based_ivc_req #( + .P(P), + .V(V), + .CONGw(CONGw) + ) the_congestion_out_gen ( + .ivc_request_all(ivc_request_all), + .congestion_out_all(congestion_out_all_next) + ); end else if((CONGESTION_INDEX==4) || (CONGESTION_INDEX==5)) begin :based_ng_ivc - - congestion_out_based_ivc_notgrant #( - .P(P), - .V(V), - .CONGw(CONGw) - ) - the_congestion_out_gen - ( - .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant), - .ivc_request_all(ivc_request_all), - .congestion_out_all(congestion_out_all_next), - .clk(clk), - .reset(reset) - ); - + congestion_out_based_ivc_notgrant #( + .P(P), + .V(V), + .CONGw(CONGw) + ) the_congestion_out_gen ( + .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant), + .ivc_request_all(ivc_request_all), + .congestion_out_all(congestion_out_all_next), + .clk(clk), + .reset(reset) + ); end else if ((CONGESTION_INDEX==6) || (CONGESTION_INDEX==7)) begin :avb_ovc1 - congestion_out_based_3port_avb_ovc#( - .P(P), - .V(V), - .CONGw(CONGw) - ) - the_congestion_out_gen - ( - .ovc_avalable_all(ovc_avalable_all), + .P(P), + .V(V), + .CONGw(CONGw) + ) the_congestion_out_gen ( + .ovc_avalable_all(ovc_avalable_all), .congestion_out_all(congestion_out_all_next) - ); - - - end else if (CONGESTION_INDEX==8) begin :indx8 - - + ); + end else if (CONGESTION_INDEX==8) begin :indx8 congestion_out_based_avb_ovc_w2 #( .P(P), .V(V) - ) - the_congestion_out_gen - ( + ) the_congestion_out_gen ( .ovc_avalable_all(ovc_avalable_all), .congestion_out_all(congestion_out_all_next) - ); - end else if (CONGESTION_INDEX==9) begin :indx9 - + end else if (CONGESTION_INDEX==9) begin :indx9 congestion_out_based_avb_ovc_w3 #( .P(P), .V(V) - ) - the_congestion_out_gen - ( + ) the_congestion_out_gen ( .ovc_avalable_all(ovc_avalable_all), .congestion_out_all(congestion_out_all_next) - ); - end else if (CONGESTION_INDEX==10) begin :indx10 - + end else if (CONGESTION_INDEX==10) begin :indx10 congestion_out_based_avb_ovc_w4 #( .P(P), .V(V) - ) - the_congestion_out_gen - ( + ) the_congestion_out_gen ( .ovc_avalable_all(ovc_avalable_all), .congestion_out_all(congestion_out_all_next) - ); - - end else if (CONGESTION_INDEX==11 || CONGESTION_INDEX==12) begin :indx11 - + end else if (CONGESTION_INDEX==11 || CONGESTION_INDEX==12) begin :indx11 congestion_out_based_avb_ovc_not_granted_ivc #( .P(P), .V(V), .CONGw(CONGw) //congestion width per port - ) - the_congestion_out_gen - ( + ) the_congestion_out_gen ( .ovc_avalable_all(ovc_avalable_all), .ivc_request_all(ivc_request_all), .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant), @@ -1552,136 +1085,95 @@ if(ROUTE_TYPE != "DETERMINISTIC") begin :adpt .reset(reset), .congestion_out_all(congestion_out_all_next) ); - - end else begin :nocong assign congestion_out_all_next = {CONG_ALw{1'bx}}; end - - end else begin :dtrmn - assign congestion_out_all_next = {CONG_ALw{1'bx}}; - + assign congestion_out_all_next = {CONG_ALw{1'bx}}; end - -endgenerate - - - pronoc_register #( - .W(CONG_ALw) - ) reg1 ( - .in(congestion_out_all_next), - .reset(reset), - .clk(clk), - .out(congestion_out_all) - ); - - + endgenerate + pronoc_register #( + .W(CONG_ALw) + ) reg1 ( + .in(congestion_out_all_next), + .reset(reset), + .clk(clk), + .out(congestion_out_all) + ); endmodule /************************* - - deadlock_detector - +* deadlock_detector **************************/ - module deadlock_detector #( parameter P=5, parameter V=4, parameter MAX_CLK = 16 - )( ivc_num_getting_sw_grant, ivc_request_all, reset, clk, detect - ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** NoC router crosbar module +** Description: +** NoC router crosbar module ** **************************************************************/ @@ -34,23 +34,20 @@ module crossbar #( parameter MUX_TYPE="BINARY", //"ONE_HOT" or "BINARY" parameter SSA_EN="YES", // "YES" , "NO" parameter SELF_LOOP_EN= "NO" -) -( +)( granted_dest_port_all, flit_in_all, flit_out_all, flit_out_wr_all, ssa_flit_wr_all - ); - - +); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2j) begin :if1 + if(i>j) begin assign mux_in[i][(j+1)*Fw-1 : j*Fw]= flit_in_all[(j+1)*Fw-1 : j*Fw]; assign mux_sel_pre[i][j] = granted_dest_port[j][i-1]; end - else if(i0 )begin - $display("%t ERROR: a header flit is received in an active IVC %m",$time); - $finish; - end - if((~hdr_passed & vc_num_tail_wr & ~single_flit_pck )>0 ) begin - $display("%t ERROR: a tail flit is received in an inactive IVC %m",$time); - $finish; - end - if ((~hdr_passed & vc_num_bdy_wr )>0)begin - $display("%t ERROR: a body flit is received in an inactive IVC %m",$time); - $finish; - end - /* verilator lint_off WIDTH */ - if((PCK_TYPE == "SINGLE_FLIT") & flit_in_wr & ~(hdr_flg_in & tail_flg_in )) begin - $display("%t ERROR: both tail and header flit flags must be asserted in SINGLE_FLIT mode %m",$time); - $finish; - end - /* verilator lint_on WIDTH */ - if( (MIN_PCK_SIZE !=1) & flit_in_wr & hdr_flg_in & tail_flg_in ) begin - $display("%t ERROR: A single flit packet is injected while the minimum packet size is set to %d. %m",$time,MIN_PCK_SIZE); - $finish; - end - //TODO check that the injected packet size meets the MIN_PCK_SIZE - + if(( hdr_passed & vc_num_hdr_wr)>0 )begin + $display("%t ERROR: a header flit is received in an active IVC %m",$time); + $finish; + end + if((~hdr_passed & vc_num_tail_wr & ~single_flit_pck )>0 ) begin + $display("%t ERROR: a tail flit is received in an inactive IVC %m",$time); + $finish; + end + if ((~hdr_passed & vc_num_bdy_wr )>0)begin + $display("%t ERROR: a body flit is received in an inactive IVC %m",$time); + $finish; + end + /* verilator lint_off WIDTH */ + if((PCK_TYPE == "SINGLE_FLIT") & flit_in_wr & ~(hdr_flg_in & tail_flg_in )) begin + $display("%t ERROR: both tail and header flit flags must be asserted in SINGLE_FLIT mode %m",$time); + $finish; + end + /* verilator lint_on WIDTH */ + if( (MIN_PCK_SIZE !=1) & flit_in_wr & hdr_flg_in & tail_flg_in ) begin + $display("%t ERROR: A single flit packet is injected while the minimum packet size is set to %d. %m",$time,MIN_PCK_SIZE); + $finish; + end + //TODO check that the injected packet size meets the MIN_PCK_SIZE end//always - // synthesis translate_on + `endif endmodule - - - - module debug_mesh_tori_route_ckeck #( parameter T1=4, parameter T2=4, @@ -120,15 +105,14 @@ module debug_mesh_tori_route_ckeck #( ); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log20)begin - not_empty_next = not_empty & ~ivc_num_getting_sw_grant; - end//tail wr out - end//always - - always@( posedge clk ) begin - if(hdr_flg_in & flit_in_wr) begin - if( ((AVC_ATOMIC_EN==1)&& (SW_LOC!= LOCAL)) || (SW_LOC== NORTH) || (SW_LOC== SOUTH) )begin - if((vc_num_in & ~ESCAP_VC_MASK)>0) begin // adaptive VCs - if( (not_empty & vc_num_in)>0) $display("%t :Error AVC allocated nonatomicly in %d port %m",$time,SW_LOC); end - end//( AVC_ATOMIC_EN || SW_LOC== NORTH || SW_LOC== SOUTH ) - if((vc_num_in & ESCAP_VC_MASK)>0 && (SW_LOC== SOUTH || SW_LOC== NORTH) ) begin // escape vc - // if (a & b) $display("%t :Error EVC allocation violate subfunction routing rules %m",$time); + end//if + end//always + /* verilator lint_off WIDTH */ + if(ROUTE_TYPE == "FULL_ADAPTIVE") begin :full_adpt + /* verilator lint_on WIDTH */ + wire [V-1 : 0] not_empty; + reg [V-1 : 0] not_empty_next; + pronoc_register #( + .W(V) + ) reg2 ( + .in(not_empty_next), + .reset(reset), + .clk(clk), + .out(not_empty) + ); + always@(*) begin + not_empty_next = not_empty; + if(hdr_flg_in & flit_in_wr) begin + not_empty_next = not_empty | vc_num_in; + end//hdr_wr_in + if((flit_is_tail & ivc_num_getting_sw_grant)>0)begin + not_empty_next = not_empty & ~ivc_num_getting_sw_grant; + end//tail wr out + end//always + always@( posedge clk ) begin + if(hdr_flg_in & flit_in_wr) begin + if( ((AVC_ATOMIC_EN==1)&& (SW_LOC!= LOCAL)) || (SW_LOC== NORTH) || (SW_LOC== SOUTH) )begin + if((vc_num_in & ~ESCAP_VC_MASK)>0) begin // adaptive VCs + if( (not_empty & vc_num_in)>0) $display("%t :Error AVC allocated nonatomicly in %d port %m",$time,SW_LOC); + end + end//( AVC_ATOMIC_EN || SW_LOC== NORTH || SW_LOC== SOUTH ) + if((vc_num_in & ESCAP_VC_MASK)>0 && (SW_LOC== SOUTH || SW_LOC== NORTH) ) begin // escape vc + // if (a & b) $display("%t :Error EVC allocation violate subfunction routing rules %m",$time); if ((current_x - x_dst_in) !=0 && (current_y- y_dst_in) !=0) $display("%t :Error EVC allocation violate subfunction routing rules src_x=%d src_y=%d dst_x%d dst_y=%d %m",$time,x_src_in, y_src_in, x_dst_in,y_dst_in); - end - end//hdr_wr_in + end + end//hdr_wr_in end//always - end //SW_LOC - - + end /* verilator lint_off WIDTH */ if(TOPOLOGY=="MESH")begin :mesh /* verilator lint_on WIDTH */ wire [EXw-1 : 0] low_x,high_x; wire [EYw-1 : 0] low_y,high_y; - - - assign low_x = (x_src_in < x_dst_in)? x_src_in : x_dst_in; assign low_y = (y_src_in < y_dst_in)? y_src_in : y_dst_in; assign high_x = (x_src_in < x_dst_in)? x_dst_in : x_src_in; assign high_y = (y_src_in < y_dst_in)? y_dst_in : y_src_in; - - always@( posedge clk)begin - if((current_x high_x) | (current_y high_y) ) - if(flit_in_wr & hdr_flg_in )begin - $display ( "%t\t ERROR: non_minimal routing %m",$time ); - $finish; - end - + if((current_x high_x) | (current_y high_y) ) begin + if(flit_in_wr & hdr_flg_in )begin + $display ( "%t\t ERROR: non_minimal routing %m",$time ); + $finish; + end + end end - - end// mesh - endgenerate - - // synthesis translate_on - - endmodule - - - module debug_mesh_edges #( + endgenerate + `endif +endmodule + + +module debug_mesh_edges #( parameter T1=2, parameter T2=2, parameter T3=3, parameter T4=3, parameter RAw=4, parameter P=5 - )( +)( clk, current_r_addr, flit_out_wr_all - ); - +); + function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2=i)? current_addr_encoded[(i+1)*Kw-1 : i*Kw] : {Kw{1'b0}}; - assign dest_addr [i] = dest_addr_encoded[(i+1)*Kw-1 : i*Kw]; assign parrents_node_missmatch[i]= current_addr [i] != parrent_dest_addr [i]; end//for endgenerate - - assign current_node_dest_port = dest_addr[current_level]; - wire [K-1:0] current_node_dest_port_one_hot; - - bin_to_one_hot #( - .BIN_WIDTH(Kw), - .ONE_HOT_WIDTH(K) - ) - conv - ( + assign current_node_dest_port = dest_addr[current_level]; + wire [K-1:0] current_node_dest_port_one_hot; + + bin_to_one_hot #( + .BIN_WIDTH(Kw), + .ONE_HOT_WIDTH(K) + ) conv ( .bin_code(current_node_dest_port), .one_hot_code(current_node_dest_port_one_hot) - ); + ); assign destport_encoded = (parrents_node_missmatch != {L{1'b0}}) ? /*go up*/{1'b1,counter} : /*go down*/{1'b0,current_node_dest_port_one_hot}; - endmodule - - // ============================================================ // FATTREE: Nearest Common Ancestor w/ destination port Up. // The up port is selected based on destination connected port num @@ -129,105 +105,86 @@ endmodule module fattree_nca_destp_up_routing #( parameter K = 2, // number of last level individual router`s endpoints. parameter L = 2 // Fattree layer number (The height of FT) - -) -( +)( reset, clk, current_addr_encoded, // connected to current router x address current_level, //connected to current router y address dest_addr_encoded, // destination address destport_encoded // router output port - ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2=i)? current_addr_encoded[(i+1)*Kw-1 : i*Kw] : {Kw{1'b0}}; - assign dest_addr [i] = dest_addr_encoded[(i+1)*Kw-1 : i*Kw]; assign parrents_node_missmatch[i]= current_addr [i] != parrent_dest_addr [i]; end//for endgenerate - - assign current_node_dest_port = dest_addr[current_level]; - wire [K-1:0] current_node_dest_port_one_hot; - - bin_to_one_hot #( - .BIN_WIDTH(Kw), - .ONE_HOT_WIDTH(K) - ) - conv - ( - .bin_code(current_node_dest_port), - .one_hot_code(current_node_dest_port_one_hot) - ); + assign current_node_dest_port = dest_addr[current_level]; + wire [K-1:0] current_node_dest_port_one_hot; + bin_to_one_hot #( + .BIN_WIDTH(Kw), + .ONE_HOT_WIDTH(K) + ) conv ( + .bin_code(current_node_dest_port), + .one_hot_code(current_node_dest_port_one_hot) + ); assign destport_encoded = (parrents_node_missmatch != {L{1'b0}}) ? /*go up*/{1'b1,current_node_dest_port_one_hot} : /*go down*/{1'b0,current_node_dest_port_one_hot}; - endmodule @@ -239,179 +196,139 @@ endmodule module fattree_nca_straight_up_routing #( parameter K = 2, // number of last level individual router`s endpoints. parameter L = 2 // Fattree layer number (The height of FT) - -) -( +) ( reset, clk, current_addr_encoded, // connected to current router x address current_level, //connected to current router y address dest_addr_encoded, // destination address destport_encoded // router output port - ); - - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2=i)? current_addr_encoded[(i+1)*Kw-1 : i*Kw] : {Kw{1'b0}}; - + // assign current_addr [i] = (current_level >=i)? current_addr_encoded[(i+1)*Kw-1 : i*Kw] : {Kw{1'b0}}; assign dest_addr [i] = dest_addr_encoded[(i+1)*Kw-1 : i*Kw]; assign parrents_node_missmatch[i]= current_addr [i] != parrent_dest_addr [i]; end//for endgenerate - - assign current_node_dest_port = dest_addr[current_level]; - wire [K-1:0] current_node_dest_port_one_hot; - - bin_to_one_hot #( - .BIN_WIDTH(Kw), - .ONE_HOT_WIDTH(K) - ) - conv - ( - .bin_code(current_node_dest_port), - .one_hot_code(current_node_dest_port_one_hot) - ); + assign current_node_dest_port = dest_addr[current_level]; + wire [K-1:0] current_node_dest_port_one_hot; + + bin_to_one_hot #( + .BIN_WIDTH(Kw), + .ONE_HOT_WIDTH(K) + ) conv ( + .bin_code(current_node_dest_port), + .one_hot_code(current_node_dest_port_one_hot) + ); // if going up the destination port num is statis straigh. It will be filled at reciver port of the next router so leave it empty assign destport_encoded = (parrents_node_missmatch != {L{1'b0}}) ? /*go up*/{1'b1,{K{1'b0}}} : /*go down*/{1'b0,current_node_dest_port_one_hot}; - endmodule module fattree_destport_up_select #( - parameter K=3, - parameter SW_LOC=0 + parameter K=3, + parameter SW_LOC=0 )( - destport_in, - destport_o + destport_in, + destport_o ); - + input [K :0] destport_in; output [K :0] destport_o; - + localparam [K-1 : 0] SW_LOC_ONHOT = 1<< SW_LOC; - wire going_up = destport_in[K]; assign destport_o = (going_up)? {1'b1,SW_LOC_ONHOT[K-1 : 0]} : destport_in; - endmodule - - /************************* * fattree_conventional_routing * **********************/ - - module fattree_conventional_routing #( parameter ROUTE_NAME = "NCA_RND_UP", parameter K = 2, // number of last level individual router`s endpoints. parameter L = 2 // Fattree layer number (The height of FT) - ) -( +)( reset, clk, current_addr_encoded, // connected to current router x address current_level, //connected to current router y address dest_addr_encoded, // destination address destport_encoded // router output port - ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21) begin :multi - assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ - { {(NL-1){1'b0}} ,portout}; - end else begin - assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ - portout; - end - - if(SELF_LOOP_EN == "NO") begin :nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) - remove_sw_loc - ( - .destport_in(destport_onehot), - .destport_out(dest_port_out) - ); - end else begin: slp - assign dest_port_out = destport_onehot; - end - - endgenerate + localparam P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P; + + input [DSTPw-1 : 0] dest_port_coded; + input [PLw-1 : 0] endp_localp_num; + output [P_1-1 : 0] dest_port_out; + input swap_port_presel; + input [PPSw-1 : 0] port_pre_sel; + + wire [P-1 : 0] endp_localp_onehot; + reg [4:0] portout; + + generate + if( ROUTE_TYPE == "DETERMINISTIC") begin :dtrmn + wire x,y,a,b; + assign {x,y,a,b} = dest_port_coded; + always @(*)begin + case({a,b}) + 2'b10 : portout = {1'b0,~x,1'b0,x,1'b0}; + 2'b01 : portout = {~y,1'b0,y,1'b0,1'b0}; + 2'b00 : portout = 5'b00001; + 2'b11 : portout = {~y,1'b0,y,1'b0,1'b0}; //invalid condition in determinstic routing + endcase + end //always + end else begin : adpv + wire x,y,a,b; + assign {x,y,a,b} = dest_port_coded; + wire [PPSw-1:0] port_pre_sel_final; + assign port_pre_sel_final= (swap_port_presel)? ~port_pre_sel: port_pre_sel; + always @(*)begin + case({a,b}) + 2'b10 : portout = {1'b0,~x,1'b0,x,1'b0}; + 2'b01 : portout = {~y,1'b0,y,1'b0,1'b0}; + 2'b11 : portout = (port_pre_sel_final[{x,y}])? {~y,1'b0,y,1'b0,1'b0} : {1'b0,~x,1'b0,x,1'b0}; + 2'b00 : portout = 5'b00001; + endcase + end //always + end //adaptive + wire [P-1 : 0] destport_onehot; + bin_to_one_hot #( + .BIN_WIDTH(PLw), + .ONE_HOT_WIDTH(P) + ) conv ( + .bin_code(endp_localp_num), + .one_hot_code(endp_localp_onehot) + ); + if(NL>1) begin :multi + assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ + { {(NL-1){1'b0}} ,portout}; + end else begin + assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ + portout; + end + if(SELF_LOOP_EN == "NO") begin :nslp + remove_sw_loc_one_hot #( + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(destport_onehot), + .destport_out(dest_port_out) + ); + end else begin: slp + assign dest_port_out = destport_onehot; + end + endgenerate endmodule - /******************** - - distance_gen - +* distance_gen ********************/ - module fmesh_distance_gen #( - parameter T1= 4, // number of router in x axis - parameter T2= 4, // number of router in y axis - parameter T3= 4, - parameter EAw=4, - parameter DISTw=4 + parameter T1= 4, // number of router in x axis + parameter T2= 4, // number of router in y axis + parameter T3= 4, + parameter EAw=4, + parameter DISTw=4 )( - src_e_addr, - dest_e_addr, - distance + src_e_addr, + dest_e_addr, + distance ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 dest_x)? src_x - dest_x : dest_x - src_x; - y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; - end - - - /* verilator lint_off WIDTH */ - assign distance = x_offset + y_offset +1'b1; - /* verilator lint_on WIDTH */ -endmodule - - + localparam + Xw = log2(T1), // number of node in x axis + Yw = log2(T2); // number of node in y axis + localparam [Xw : 0] NX = T1; + localparam [Yw : 0] NY = T2; + + input [EAw-1 : 0] src_e_addr; + input [EAw-1 : 0] dest_e_addr; + output[DISTw-1: 0]distance; + + wire [Xw-1 : 0]src_x,dest_x; + wire [Yw-1 : 0]src_y,dest_y; + + fmesh_endp_addr_decode #( + .T1(T1), + .T2(T2), + .T3(T3), + .EAw(EAw) + ) src_addr_decode ( + .e_addr(src_e_addr), + .ex(src_x), + .ey(src_y), + .ep(), + .valid() + ); + + fmesh_endp_addr_decode #( + .T1(T1), + .T2(T2), + .T3(T3), + .EAw(EAw) + ) dest_addr_decode ( + .e_addr(dest_e_addr), + .ex(dest_x), + .ey(dest_y), + .ep(), + .valid() + ); + + reg [Xw-1 : 0] x_offset; + reg [Yw-1 : 0] y_offset; + always @(*) begin + x_offset = (src_x> dest_x)? src_x - dest_x : dest_x - src_x; + y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; + end + /* verilator lint_off WIDTH */ + assign distance = x_offset + y_offset +1'b1; + /* verilator lint_on WIDTH */ +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index 62f77a2..4ef2339 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -42,16 +42,15 @@ module header_flit_generator #( vc_num_in, be_in, data_in -); +); - `NOC_CONF - + `NOC_CONF localparam HDR_FLAG = 2'b10; - localparam Dw = (DATA_w==0)? 1 : DATA_w, - DATA_LSB= MSB_BE+1, DATA_MSB= (DATA_LSB + DATA_w)1)begin :have_class assign flit_out [CLASS_MSB :CLASS_LSB] = class_in; end - + /* verilator lint_off WIDTH */ if(SWA_ARBITER_TYPE != "RRA")begin : wrra_b /* verilator lint_on WIDTH */ @@ -83,31 +81,26 @@ module header_flit_generator #( assign flit_out [BE_MSB : BE_LSB] = be_in; end - if (DATA_w ==0) begin :no_data if(FPAYw>DATA_LSB) begin: dontcare - assign flit_out [FPAYw-1 : DATA_LSB] = {(FPAYw-DATA_LSB){1'bX}}; + assign flit_out [FPAYw-1 : DATA_LSB] = {(FPAYw-DATA_LSB){1'bX}}; end end else begin :have_data - assign flit_out [DATA_MSB : DATA_LSB] = data_in[DATA_MSB-DATA_LSB : 0]; // we have enough space for adding whole of the data + assign flit_out [DATA_MSB : DATA_LSB] = data_in[DATA_MSB-DATA_LSB : 0]; // we have enough space for adding whole of the data end endgenerate - + assign flit_out [FPAYw+V-1 : FPAYw] = vc_num_in; assign flit_out [Fw-1 : Fw-2] = HDR_FLAG; - - //synthesis translate_off - //synopsys translate_off + `ifdef SIMULATION initial begin if((DATA_LSB + DATA_w)-1 > FPAYw)begin $display("%t: ERROR: The reqired header flit size is %d which is larger than %d payload size ",$time,(DATA_LSB + DATA_w)-1,FPAYw); $finish; end end - //synopsys translate_on - //synthesis translate_on - + `endif endmodule @@ -130,20 +123,19 @@ module extract_header_flit_info # ( vc_num_o, hdr_flit_wr_o, be_o -); +); + + `NOC_CONF - `NOC_CONF - localparam W = WEIGHTw, Dw = (DATA_w==0)? 1 : DATA_w, - DATA_LSB= MSB_BE+1, DATA_MSB= (DATA_LSB + DATA_w)1)begin :have_class assign class_o = flit_in [CLASS_MSB : CLASS_LSB]; end else begin : no_class - assign class_o = {Cw{1'b0}}; - end - + assign class_o = {Cw{1'b0}}; + end /* verilator lint_off WIDTH */ if(SWA_ARBITER_TYPE != "RRA")begin : wrra_b /* verilator lint_on WIDTH */ @@ -181,51 +167,35 @@ module extract_header_flit_info # ( end else begin : rra_b assign weight_o = {WEIGHTw{1'bX}}; end - if( BYTE_EN ) begin : be_1 assign be_o = flit_in [BE_MSB : BE_LSB]; end else begin : be_0 assign be_o = {BEw{1'bX}}; end - - assign offset = flit_in [DATA_MSB : DATA_LSB]; - - if(Dw > OFFSETw) begin : if1 assign data_o={{(Dw-OFFSETw){1'b0}},offset}; end else begin : if2 assign data_o=offset[Dw-1 : 0]; end - endgenerate - /* verilator lint_off WIDTH */ assign hdr_flg_o = (PCK_TYPE == "MULTI_FLIT") ? flit_in [Fw-1] : 1'b1; assign tail_flg_o = (PCK_TYPE == "MULTI_FLIT") ? flit_in [Fw-2] : 1'b1; /* verilator lint_on WIDTH */ - - assign vc_num_o = flit_in [FPAYw+V-1 : FPAYw]; assign hdr_flit_wr_o= (flit_in_wr & hdr_flg_o )? vc_num_o : {V{1'b0}}; - endmodule - - - - /*********************************** * flit_update * update the header flit look ahead routing and output VC -**********************************/ - +*********************************/ module header_flit_update_lk_route_ovc #( parameter NOC_ID=0, parameter P = 5 -) -( +)( flit_in , flit_out, vc_num_in, @@ -237,13 +207,12 @@ module header_flit_update_lk_route_ovc #( reset, clk ); - - `NOC_CONF - + `NOC_CONF + localparam VDSTPw = V * DSTPw, VV = V * V; - + input [Fw-1 : 0] flit_in; output reg [Fw-1 : 0] flit_out; input [V-1 : 0] vc_num_in; @@ -259,50 +228,43 @@ module header_flit_update_lk_route_ovc #( wire [V-1 : 0] ovc_num; wire [DSTPw-1 : 0] lk_dest,dest_coded; wire [DSTPw-1 : 0] lk_mux_out; - + pronoc_register #(.W(V)) reg1 (.in(vc_num_in), .out(vc_num_delayed), .reset(reset), .clk(clk)); - + /* verilator lint_off WIDTH */ assign hdr_flag = ( PCK_TYPE == "MULTI_FLIT")? flit_in[Fw-1]: 1'b1; /* verilator lint_on WIDTH */ - + onehot_mux_1D #( .W(DSTPw), .N(V) - ) - lkdest_mux - ( + ) lkdest_mux ( .in(lk_dest_all_in), .out(lk_mux_out), .sel(vc_num_delayed) ); - + generate /* verilator lint_off WIDTH */ if( SSA_EN == "YES" ) begin : predict // bypass the lk fifo when no ivc is granted /* verilator lint_on WIDTH */ logic ivc_any_delayed; - pronoc_register #(.W(1)) reg2 (.in(any_ivc_sw_request_granted ), .out(ivc_any_delayed), .reset(reset), .clk(clk)); - assign lk_dest = (ivc_any_delayed == 1'b0)? lk_dest_not_registered : lk_mux_out; - end else begin : no_predict assign lk_dest =lk_mux_out; end endgenerate - - onehot_mux_1D #( + + onehot_mux_1D #( .W(V), .N(V) - ) - ovc_num_mux - ( + ) ovc_num_mux( .in(assigned_ovc_num), .out(ovc_num), .sel(vc_num_delayed) ); - + generate /* verilator lint_off WIDTH */ if((TOPOLOGY == "MESH" || TOPOLOGY == "FMESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING") && ROUTE_TYPE != "DETERMINISTIC" )begin :coded @@ -314,53 +276,40 @@ module header_flit_update_lk_route_ovc #( .Fw(Fw), .DST_P_MSB(DST_P_MSB), .DST_P_LSB(DST_P_LSB) - ) - dest_encoder - ( + ) dest_encoder ( .sel(sel), .dest_coded_out(dest_coded), .vc_num_delayed(vc_num_delayed), .lk_dest(lk_dest), .flit_in(flit_in) ); - - end else begin : dtrmn1 assign dest_coded = lk_dest; /* - mesh_torus_dtrmn_dest_encoder #( + mesh_torus_dtrmn_dest_encoder #( .P(P), .DSTPw(DSTPw), .Fw(Fw), .DST_P_MSB(DST_P_MSB), .DST_P_LSB(DST_P_LSB) - ) - dest_encoder - ( - .dest_coded_out(dest_coded), - .lk_dest(lk_dest), - .flit_in(flit_in) - ); + ) dest_encoder ( + .dest_coded_out(dest_coded), + .lk_dest(lk_dest), + .flit_in(flit_in) + ); */ end always @(*)begin - flit_out = {flit_in[Fw-1 : Fw-2],ovc_num,flit_in[FPAYw-1 :0]}; - if(hdr_flag) flit_out[DST_P_MSB : DST_P_LSB]= dest_coded; + flit_out = {flit_in[Fw-1 : Fw-2],ovc_num,flit_in[FPAYw-1 :0]}; + if(hdr_flag) flit_out[DST_P_MSB : DST_P_LSB]= dest_coded; end - - endgenerate - - - - endmodule /****************** * hdr_flit_weight_update * ****************/ - module hdr_flit_weight_update #( parameter NOC_ID = 0 ) ( @@ -368,14 +317,11 @@ module hdr_flit_weight_update #( flit_in, flit_out ); - - `NOC_CONF + `NOC_CONF input [WEIGHTw-1 : 0] new_weight; input [Fw-1 : 0] flit_in; output [Fw-1 : 0] flit_out; assign flit_out = {flit_in[Fw-1 : WEIGHT_LSB+WEIGHTw ] ,new_weight, flit_in[WEIGHT_LSB-1 : 0] }; - -endmodule - +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index f0e9896..4f6f79c 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -1,28 +1,27 @@ `include "pronoc_def.v" - /********************************************************************** -** File: mesh_torus.v +** File: mesh_torus.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** +** Description: +** ** ***************************************/ @@ -49,7 +48,6 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( parameter SSA_EN ="NO", parameter PPSw=4, parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000 // mask scape vc, valid only for full adaptive - )( ovc_avalable_all, dest_port_coded_all, @@ -75,7 +73,7 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( VP_1 = V * P_1, PVDSTPw = PV * DSTPw; - localparam LOCAL = 3'd0, + localparam LOCAL = 3'd0, EAST = 3'd1, NORTH = 3'd2, WEST = 3'd3, @@ -132,48 +130,48 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( for(i=0;i< PV;i=i+1) begin :all_vc_loop mesh_torus_adaptive_avb_ovc_mux #( - .V(V) + .V(V) ) the_adaptive_avb_ovc_mux ( - .ovc_avalable (ovc_avalable_perport [i/V]), - .sel (sel [i]), - .candidate_ovc_x (candidate_ovc_x_all [((i+1)*V)-1 : i*V]), - .candidate_ovc_y (candidate_ovc_y_all [((i+1)*V)-1 : i*V]), - .non_assigned_ovc_request (non_assigned_ovc_request_all[i]), - .xydir (dest_port_coded_all [((i+1)*DSTPw)-1 : ((i+1)*DSTPw)-2]), - .masked_ovc_request (masked_ovc_request_all [((i+1)*V)-1 : i*V]) + .ovc_avalable (ovc_avalable_perport [i/V]), + .sel (sel [i]), + .candidate_ovc_x (candidate_ovc_x_all [((i+1)*V)-1 : i*V]), + .candidate_ovc_y (candidate_ovc_y_all [((i+1)*V)-1 : i*V]), + .non_assigned_ovc_request (non_assigned_ovc_request_all[i]), + .xydir (dest_port_coded_all [((i+1)*DSTPw)-1 : ((i+1)*DSTPw)-2]), + .masked_ovc_request (masked_ovc_request_all [((i+1)*V)-1 : i*V]) ); mesh_torus_port_selector #( - .SW_LOC (i/V), - .PPSw(PPSw) + .SW_LOC (i/V), + .PPSw(PPSw) ) the_portsel ( - .port_pre_sel (port_pre_sel_perport[i/V]), - .swap_port_presel (swap_port_presel[i]), - .sel (sel[i]), - .dest_port_in (dest_port_coded_all[((i+1)*DSTPw)-1 : i*DSTPw]), - .y_evc_forbiden (y_evc_forbiden[i]), + .port_pre_sel (port_pre_sel_perport[i/V]), + .swap_port_presel (swap_port_presel[i]), + .sel (sel[i]), + .dest_port_in (dest_port_coded_all[((i+1)*DSTPw)-1 : i*DSTPw]), + .y_evc_forbiden (y_evc_forbiden[i]), .x_evc_forbiden (x_evc_forbiden[i]) - ); + ); mesh_tori_dspt_clear_gen #( - .SSA_EN(SSA_EN), - .DSTPw(DSTPw), - .SW_LOC(i/V) + .SSA_EN(SSA_EN), + .DSTPw(DSTPw), + .SW_LOC(i/V) ) dspt_clear_gen ( - .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]), - .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant[i]), - .sel(sel[i]), - .ssa_ivc_num_getting_ovc_grant(ssa_ivc_num_getting_ovc_grant_all[i]) - ); - - - /* verilator lint_off WIDTH */ + .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]), + .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant[i]), + .sel(sel[i]), + .ssa_ivc_num_getting_ovc_grant(ssa_ivc_num_getting_ovc_grant_all[i]) + ); + + + /* verilator lint_off WIDTH */ if(ROUTE_TYPE == "FULL_ADAPTIVE") begin: full_adpt /* verilator lint_on WIDTH */ assign candidate_ovc_y_all[((i+1)*V)-1 : i*V] = (y_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) : candidate_ovc_all[((i+1)*V)-1 : i*V]; @@ -188,14 +186,14 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( ) the_swap_port_presel ( - .avc_unavailable(avc_unavailable[i]), - .y_evc_forbiden(y_evc_forbiden[i]), - .x_evc_forbiden(x_evc_forbiden[i]), - .non_assigned_ovc_request(non_assigned_ovc_request_all[i]), - .sel(sel[i]), - .clk(clk), - .reset(reset), - .swap_port_presel(swap_port_presel[i]) + .avc_unavailable(avc_unavailable[i]), + .y_evc_forbiden(y_evc_forbiden[i]), + .x_evc_forbiden(x_evc_forbiden[i]), + .non_assigned_ovc_request(non_assigned_ovc_request_all[i]), + .sel(sel[i]), + .clk(clk), + .reset(reset), + .swap_port_presel(swap_port_presel[i]) ); @@ -290,8 +288,8 @@ module mesh_torus_mask_non_assignable_destport #( ) remove_sw_loc ( - .destport_in(dest_port_in), - .destport_out(dest_port_in_tmp) + .destport_in(dest_port_in), + .destport_out(dest_port_in_tmp) ); //currently loop-back only can happen in local ports. //Current supported routing algorithms does not results in loop-back in other ports @@ -321,9 +319,9 @@ module mesh_torus_mask_non_assignable_destport #( ) mask_no_self_loop ( - .dest_port_in(dest_port_in_tmp), - .dest_port_out(dest_port_out_tmp), - .odd_column(odd_column) + .dest_port_in(dest_port_in_tmp), + .dest_port_out(dest_port_out_tmp), + .odd_column(odd_column) ); @@ -866,19 +864,19 @@ module mesh_torus_distance_gen #( wire [Yw-1 : 0]src_y,dest_y; mesh_tori_endp_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) + .TOPOLOGY(TOPOLOGY), + .T1(T1), + .T2(T2), + .T3(T3), + .EAw(EAw) ) src_addr_decode ( - .e_addr(src_e_addr), - .ex(src_x), - .ey(src_y), - .el(), - .valid() + .e_addr(src_e_addr), + .ex(src_x), + .ey(src_y), + .el(), + .valid() ); mesh_tori_endp_addr_decode #( @@ -988,24 +986,20 @@ module mesh_torus_ssa_check_destport #( destport_encoded, //exsited packet dest port destport_in_encoded, // incomming packet dest port ss_port_hdr_flit, - ss_port_nonhdr_flit -//synthesis translate_off -//synopsys translate_off + ss_port_nonhdr_flit + `ifdef SIMULATION ,clk, ivc_num_getting_sw_grant, hdr_flg -//synopsys translate_on -//synthesis translate_on + `endif ); input [DSTPw-1 : 0] destport_encoded, destport_in_encoded; output ss_port_hdr_flit, ss_port_nonhdr_flit; -//synthesis translate_off -//synopsys translate_off - input clk, ivc_num_getting_sw_grant,hdr_flg; -//synopsys translate_on -//synthesis translate_on + `ifdef SIMULATION + input clk, ivc_num_getting_sw_grant,hdr_flg; + `endif //MESH, TORUS Topology p=5 localparam LOCAL = 0, @@ -1043,24 +1037,18 @@ generate assign ss_port_nonhdr_flit = bb; end -//synthesis translate_off -//synopsys translate_off - -if(DEBUG_EN) begin :dbg - always @(posedge clk) begin - //if(!reset)begin - if(ivc_num_getting_sw_grant & aa & bb & ~hdr_flg) begin - $display("%t: SSA ERROR: There are two output ports that a non-header flit can be sent to. %m",$time); - $finish; - end - //end - end -end //dbg - -//synopsys translate_on -//synthesis translate_on - - + `ifdef SIMULATION + if(DEBUG_EN) begin :dbg + always @(posedge clk) begin + //if(!reset)begin + if(ivc_num_getting_sw_grant & aa & bb & ~hdr_flg) begin + $display("%t: SSA ERROR: There are two output ports that a non-header flit can be sent to. %m",$time); + $finish; + end + //end + end + end //dbg + `endif endgenerate endmodule @@ -1077,7 +1065,6 @@ module line_ring_ssa_check_destport #( destport_in_encoded, // incomming packet dest port ss_port_hdr_flit, ss_port_nonhdr_flit - ); input [DSTPw-1 : 0] destport_encoded, destport_in_encoded; @@ -1090,13 +1077,13 @@ wire [P-1 : 0] dest_port_num,assigned_dest_port_num; line_ring_decode_dstport cnv1( - .dstport_one_hot(dest_port_num), - .dstport_encoded(destport_in_encoded) + .dstport_one_hot(dest_port_num), + .dstport_encoded(destport_in_encoded) ); line_ring_decode_dstport cnv2( - .dstport_one_hot(assigned_dest_port_num), - .dstport_encoded(destport_encoded) + .dstport_one_hot(assigned_dest_port_num), + .dstport_encoded(destport_encoded) ); assign ss_port_hdr_flit = dest_port_num [SS_PORT]; @@ -1592,19 +1579,19 @@ module mesh_torus_destp_decoder #( end else begin :mlp wire [P-1 : 0] destport_onehot; - + bin_to_one_hot #( - .BIN_WIDTH(ELw), - .ONE_HOT_WIDTH(NL) + .BIN_WIDTH(ELw), + .ONE_HOT_WIDTH(NL) ) conv ( - .bin_code(endp_localp_num), - .one_hot_code(endp_localp_onehot) + .bin_code(endp_localp_num), + .one_hot_code(endp_localp_onehot) ); assign destport_onehot =(portout[0])? { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/ - { {(NL-1){1'b0}} ,portout}; + { {(NL-1){1'b0}} ,portout}; if(SELF_LOOP_EN == "NO") begin :nslp remove_sw_loc_one_hot #( .P(P), @@ -1655,8 +1642,8 @@ module line_ring_destp_decoder #( line_ring_decode_dstport decoder( - .dstport_one_hot(portout), - .dstport_encoded(dest_port_coded) + .dstport_one_hot(portout), + .dstport_encoded(dest_port_coded) ); diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index df88a45..1bc1949 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -1,5 +1,4 @@ `include "pronoc_def.v" - /********************************************************************** ** File: mesh_torus_noc_top.v ** diff --git a/mpsoc/rtl/src_noc/mesh_torus_routting.v b/mpsoc/rtl/src_noc/mesh_torus_routting.v index f97c029..2ed65dc 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_routting.v +++ b/mpsoc/rtl/src_noc/mesh_torus_routting.v @@ -1,18 +1,17 @@ -`timescale 1ns / 1ps - +`include "pronoc_def.v" /************************************ - - mesh_torus_look_ahead_routing - +* +* mesh_torus_look_ahead_routing +* *************************************/ module mesh_torus_look_ahead_routing #( - parameter NX =4, - parameter NY =4, - parameter SW_LOC =0, - parameter TOPOLOGY ="MESH",//"MESH","TORUS" - parameter ROUTE_NAME="XY",// - parameter ROUTE_TYPE="DETERMINISTIC"// "DETERMINISTIC", "FULL_ADAPTIVE", "PAR_ADAPTIVE" + parameter NX = 4, + parameter NY = 4, + parameter SW_LOC = 0, + parameter TOPOLOGY = "MESH",//"MESH","TORUS" + parameter ROUTE_NAME = "XY",// + parameter ROUTE_TYPE = "DETERMINISTIC"// "DETERMINISTIC", "FULL_ADAPTIVE", "PAR_ADAPTIVE" ) ( current_x, //current router x address @@ -30,53 +29,50 @@ module mesh_torus_look_ahead_routing #( /* verilator lint_on WIDTH */ function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 destport_in_bin ) ? destport_in_bin : destport_in_bin -1'b1; - assign destport_out_bin=temp[P_1w-1 :0]; + wire [Pw-1 : 0] temp; + assign temp = (receiver_port_bin > destport_in_bin ) ? destport_in_bin : destport_in_bin -1'b1; + assign destport_out_bin=temp[P_1w-1 : 0]; bin_to_one_hot #( .BIN_WIDTH(P_1w), .ONE_HOT_WIDTH(P_1) - ) - convert3( + ) convert3 ( .bin_code(destport_out_bin), .one_hot_code(destport_out) ); - - - endmodule /************************************** - - add_sw_loc_one_hot - - +* add_sw_loc_one_hot ****************************************/ module add_sw_loc_one_hot #( - parameter P = 5, - parameter SW_LOC = 1 - -) -( + parameter P = 5, + parameter SW_LOC = 1 +)( destport_in, destport_out ); - localparam P_1 = P-1; - - input [P_1-1 : 0] destport_in; - output reg [P-1 : 0] destport_out; + input [P_1-1 : 0] destport_in; + output reg [P-1 : 0] destport_out; integer i; always @(*)begin for(i=0;iSW_LOC) destport_out[i] = destport_in[i-1]; - else if (i==SW_LOC) destport_out[i] = 1'b0; - else destport_out[i] = destport_in[i]; + if (i>SW_LOC) destport_out[i] = destport_in[i-1]; + else if (i==SW_LOC) destport_out[i] = 1'b0; + else destport_out[i] = destport_in[i]; end//for end - - - - endmodule +endmodule module add_sw_loc_one_hot_val #( - parameter P = 5, - parameter SW_LOC = 1 + parameter P = 5, + parameter SW_LOC = 1 -) -( +)( sw_loc_val, destport_in, destport_out ); - localparam P_1 = P-1; input sw_loc_val; - input [P_1-1 : 0] destport_in; - output reg [P-1 : 0] destport_out; + input [P_1-1 : 0] destport_in; + output reg [P-1 : 0] destport_out; integer i; always @(*)begin for(i=0;iSW_LOC) destport_out[i] = destport_in[i-1]; - else if (i==SW_LOC) destport_out[i] = sw_loc_val; - else destport_out[i] = destport_in[i]; + if (i>SW_LOC) destport_out[i] = destport_in[i-1]; + else if (i==SW_LOC) destport_out[i] = sw_loc_val; + else destport_out[i] = destport_in[i]; end//for end - - - - endmodule +endmodule /*************************************************** - - conventional routing - +* conventional routing ***************************************************/ - module mesh_torus_conventional_routing #( - parameter TOPOLOGY = "MESH", - parameter ROUTE_NAME = "XY", - parameter ROUTE_TYPE = "DETERMINISTIC", - parameter NX = 4, - parameter NY = 4, - parameter LOCATED_IN_NI = 0//use for add even only - - ) - ( + parameter TOPOLOGY = "MESH", + parameter ROUTE_NAME = "XY", + parameter ROUTE_TYPE = "DETERMINISTIC", + parameter NX = 4, + parameter NY = 4, + parameter LOCATED_IN_NI = 0//use for add even only + ) ( current_x, current_y, dest_x, dest_y, destport - ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2= (NX-2)) && (xd <= (NX-4))) || - ((xdiff> 0) && (xd<= (NX-3)))) - tranc_x_plus = 1'b1; - else tranc_x_min = 1'b1; + (xdiff == (-NX+1)) || + ((xc == (NX-4)) && (xd == (NX-2))) || + ((xc >= (NX-2)) && (xd <= (NX-4))) || + ((xdiff> 0) && (xd<= (NX-3)))) + tranc_x_plus = 1'b1; + else tranc_x_min = 1'b1; end - end//always - assign same_x = (xdiff == 0); - - - - + always@(*)begin if (same_x ) destport_one_hot= LOCAL; else begin - if (tranc_x_plus) destport_one_hot= PLUS; - else if (tranc_x_min) destport_one_hot= MINUS; - end + if (tranc_x_plus) destport_one_hot= PLUS; + else if (tranc_x_min) destport_one_hot= MINUS; + end end - - line_ring_encode_dstport encode( + line_ring_encode_dstport encode( .dstport_one_hot(destport_one_hot), .dstport_encoded(destport) ); - endmodule /******************************************** - xy_line +* xy_line *********************************************/ - module xy_line_routing #( - parameter NX = 8 -) -( + parameter NX = 8 +)( current_x, dest_x, destport - ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 current_x) destport_one_hot = PLUS [2 :0]; - else if (dest_x < current_x) destport_one_hot = MINUS [2 :0]; + destport_one_hot = LOCAL [2 : 0]; + if (dest_x > current_x) destport_one_hot = PLUS [2 : 0]; + else if (dest_x < current_x) destport_one_hot = MINUS [2 : 0]; end - line_ring_encode_dstport encode( - .dstport_one_hot(destport_one_hot), - .dstport_encoded(destport) + .dstport_one_hot(destport_one_hot), + .dstport_encoded(destport) ); - endmodule @@ -1217,26 +969,22 @@ module line_ring_encode_dstport ( dstport_one_hot, dstport_encoded ); - - input [2 : 0] dstport_one_hot; + input [2 : 0] dstport_one_hot; output [1 : 0] dstport_encoded; - - localparam FORWARD = 2'd1, - BACKWARD= 2'd2; - + localparam + FORWARD = 2'd1, + BACKWARD = 2'd2; /************************ - - destination-port_in - 2'b11 : FORWARD or BACKWARD // can be sent to any of them - 2'b10 : BACKWARD - 2'b01 : FORWARD - 2'b00 : LOCAL + * destination-port_in + * 2'b11 : FORWARD or BACKWARD // can be sent to any of them + * 2'b10 : BACKWARD + * 2'b01 : FORWARD + * 2'b00 : LOCAL *******************/ -// code the destination port + // code the destination port assign dstport_encoded = {dstport_one_hot[BACKWARD], dstport_one_hot[FORWARD]}; - endmodule @@ -1244,60 +992,36 @@ module line_ring_decode_dstport ( dstport_one_hot, dstport_encoded ); - output reg [2 : 0] dstport_one_hot; - input [1 : 0] dstport_encoded; - - /************************ - localparam FORWARD = 2'd1, - BACKWARD= 2'd2; - destination-port_in - 2'b11 : FORWARD or BACKWARD // can be sey to any of them - 2'b10 : BACKWARD - 2'b01 : FORWARD - 2'b00 : LOCAL - *******************/ -// code the destination port - //assign dstport_encoded = {dstport_one_hot[BACKWARD], dstport_one_hot[FORWARD]}; - - - - always @(*)begin - dstport_one_hot = 3'b000; - case(dstport_encoded) - 2'b10 : dstport_one_hot=3'b100; - 2'b01 : dstport_one_hot=3'b010; - 2'b00 : dstport_one_hot=3'b001; - 2'b11 : dstport_one_hot=3'b110; //invalid condition in determinstic routing - endcase - end //always + input [1 : 0] dstport_encoded; + + always @(*)begin + dstport_one_hot = 3'b000; + case(dstport_encoded) + 2'b10 : dstport_one_hot=3'b100; + 2'b01 : dstport_one_hot=3'b010; + 2'b00 : dstport_one_hot=3'b001; + 2'b11 : dstport_one_hot=3'b110; //invalid condition in determinstic routing + endcase + end //always endmodule - module mesh_tori_decode_dstport ( dstport_encoded, dstport_one_hot - ); - - - input [3 : 0] dstport_encoded; + input [3 : 0] dstport_encoded; output reg [4 : 0] dstport_one_hot; - wire x,y,a,b; - - assign {x,y,a,b} = dstport_encoded; - - always @(*)begin + always @(*)begin dstport_one_hot = 5'd0; case({a,b}) 2'b10 : dstport_one_hot = {1'b0,~x,1'b0,x,1'b0}; 2'b01 : dstport_one_hot = {~y,1'b0,y,1'b0,1'b0}; 2'b11 : dstport_one_hot = {1'b0,~x,1'b0,x,1'b0}; //illegal - 2'b00 : dstport_one_hot = 5'b00001; - endcase + 2'b00 : dstport_one_hot = 5'b00001; + endcase end //always - -endmodule +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/multicast.sv b/mpsoc/rtl/src_noc/multicast.sv index 6943f44..79a23cf 100644 --- a/mpsoc/rtl/src_noc/multicast.sv +++ b/mpsoc/rtl/src_noc/multicast.sv @@ -731,7 +731,7 @@ module multicast_chan_in_process #( - //synthesis translate_off + `ifdef SIMULATION if(DEBUG_EN) begin :debg always @(posedge clk) begin /* verilator lint_off WIDTH */ @@ -754,8 +754,8 @@ module multicast_chan_in_process #( end end//debug - //synthesis translate_on - + `endif + endgenerate endmodule diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index e4290e5..acf1f69 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -1,27 +1,27 @@ `include "pronoc_def.v" /********************************************************************** -** File: output_ports.sv +** File: output_ports.sv ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** output_ports module: contain output VC (OVC) status registers and credit counters, +** Description: +** output_ports module: contain output VC (OVC) status registers and credit counters, ** **************************************************************/ @@ -60,81 +60,71 @@ module output_ports #( ); - `NOC_CONF + `NOC_CONF localparam - PV = V * P, - VV = V * V, - PVV = PV * V, - P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, - VP_1 = V * P_1, - PP_1 = P_1 * P, - PVP_1 = PV * P_1; - - localparam [V-1 : 0] ADAPTIVE_VC_MASK = ~ ESCAP_VC_MASK; - localparam CONG_ALw= CONGw * P; // congestion width per router; - - input [PV-1 : 0] vsa_ovc_allocated_all; - input [PV-1 : 0] flit_is_tail_all; - input [PVP_1-1 : 0] dest_port_all; - input [PP_1-1 : 0] nonspec_granted_dest_port_all; - input [PV-1 : 0] credit_in_all; - input [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; - input [PV-1 : 0] ivc_num_getting_sw_grant; - output [PV-1 : 0] ovc_avalable_all; - output [PV-1 : 0] assigned_ovc_not_full_all; - input reset,clk; - output [PPSw-1 : 0] port_pre_sel; - input [CONG_ALw-1 : 0] congestion_in_all; - input [PVV-1 : 0] granted_ovc_num_all; - input [P-1 : 0] granted_dst_is_from_a_single_flit_pck; - input [P-1 : 0] crossbar_flit_out_wr_all; - input [P-1 : 0] any_ovc_granted_in_outport_all; - output [PV-1 : 0] vsa_ovc_released_all; - output [PV-1 : 0] vsa_credit_decreased_all; + PV = V * P, + VV = V * V, + PVV = PV * V, + P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, + VP_1 = V * P_1, + PP_1 = P_1 * P, + PVP_1 = PV * P_1; + + localparam [V-1 : 0] ADAPTIVE_VC_MASK = ~ ESCAP_VC_MASK; + localparam CONG_ALw= CONGw * P; // congestion width per router; + + input [PV-1 : 0] vsa_ovc_allocated_all; + input [PV-1 : 0] flit_is_tail_all; + input [PVP_1-1 : 0] dest_port_all; + input [PP_1-1 : 0] nonspec_granted_dest_port_all; + input [PV-1 : 0] credit_in_all; + input [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; + input [PV-1 : 0] ivc_num_getting_sw_grant; + output [PV-1 : 0] ovc_avalable_all; + output [PV-1 : 0] assigned_ovc_not_full_all; + input reset,clk; + output [PPSw-1 : 0] port_pre_sel; + input [CONG_ALw-1 : 0] congestion_in_all; + input [PVV-1 : 0] granted_ovc_num_all; + input [P-1 : 0] granted_dst_is_from_a_single_flit_pck; + input [P-1 : 0] crossbar_flit_out_wr_all; + input [P-1 : 0] any_ovc_granted_in_outport_all; + output [PV-1 : 0] vsa_ovc_released_all; + output [PV-1 : 0] vsa_credit_decreased_all; output oport_info_t oport_info [P-1:0]; - output ovc_info_t ovc_info [P-1 : 0][V-1 : 0]; - input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; - input vsa_ctrl_t vsa_ctrl_in [P-1: 0]; - input ssa_ctrl_t ssa_ctrl_in [P-1: 0]; - input smart_ctrl_t smart_ctrl_in [P-1: 0]; - input [CRDTw-1 : 0 ] credit_init_val_in [P-1 : 0][V-1 : 0]; - - wire [PVV-1 : 0] ssa_granted_ovc_num_all; - - logic [PV-1 : 0] ovc_status; - logic [PV-1 : 0] ovc_status_next; - wire [PV-1 : 0] assigned_ovc_is_full_all; - wire [VP_1-1 : 0] credit_decreased [P-1 : 0]; - wire [P_1-1 : 0] credit_decreased_gen [PV-1 : 0]; - - wire [PV-1 : 0] credit_increased_all; - wire [VP_1-1 : 0] ovc_released [P-1 : 0]; - wire [P_1-1 : 0] ovc_released_gen [PV-1 : 0]; - - wire [VP_1-1 : 0] credit_in_perport [P-1 : 0]; - wire [VP_1-1 : 0] full_perport [P-1 : 0]; - wire [VP_1-1 : 0] nearly_full_perport [P-1 : 0]; - - wire [PV-1 : 0] full_all,nearly_full_all, empty_all; - wire [PV-1 : 0] full_all_next,nearly_full_all_next,empty_all_next; - - - wire [PV-1 : 0] credit_decreased_all; - wire [PV-1 : 0] ovc_released_all; - wire [PV-1 : 0] ovc_allocated_all; - wire [CREDITw-1 : 0] credit_counter [PV-1 : 0]; - - wire [PVV-1 : 0] assigned_ovc_num_all; - wire [PV-1 : 0] ovc_is_assigned_all; - + output ovc_info_t ovc_info [P-1 : 0][V-1 : 0]; + input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + input vsa_ctrl_t vsa_ctrl_in [P-1: 0]; + input ssa_ctrl_t ssa_ctrl_in [P-1: 0]; + input smart_ctrl_t smart_ctrl_in [P-1: 0]; + input [CRDTw-1 : 0 ] credit_init_val_in [P-1 : 0][V-1 : 0]; + + wire [PVV-1 : 0] ssa_granted_ovc_num_all; + logic [PV-1 : 0] ovc_status; + logic [PV-1 : 0] ovc_status_next; + wire [PV-1 : 0] assigned_ovc_is_full_all; + wire [VP_1-1 : 0] credit_decreased [P-1 : 0]; + wire [P_1-1 : 0] credit_decreased_gen [PV-1 : 0]; + wire [PV-1 : 0] credit_increased_all; + wire [VP_1-1 : 0] ovc_released [P-1 : 0]; + wire [P_1-1 : 0] ovc_released_gen [PV-1 : 0]; + wire [VP_1-1 : 0] credit_in_perport [P-1 : 0]; + wire [VP_1-1 : 0] full_perport [P-1 : 0]; + wire [VP_1-1 : 0] nearly_full_perport [P-1 : 0]; + wire [PV-1 : 0] full_all,nearly_full_all, empty_all; + wire [PV-1 : 0] full_all_next,nearly_full_all_next,empty_all_next; + wire [PV-1 : 0] credit_decreased_all; + wire [PV-1 : 0] ovc_released_all; + wire [PV-1 : 0] ovc_allocated_all; + wire [CREDITw-1 : 0] credit_counter [PV-1 : 0]; + wire [PVV-1 : 0] assigned_ovc_num_all; + wire [PV-1 : 0] ovc_is_assigned_all; pronoc_register #(.W(PV)) reg_1 ( .in(full_all_next), .reset(reset), .clk(clk), .out(full_all)); pronoc_register #(.W(PV)) reg_2 ( .in(nearly_full_all_next), .reset(reset), .clk(clk), .out(nearly_full_all)); pronoc_register #(.W(PV)) reg_3 ( .in(empty_all_next), .reset(reset), .clk(clk), .out(empty_all)); - - integer k; genvar i,j; generate @@ -142,25 +132,23 @@ module output_ports #( if(VC_REALLOCATION_TYPE=="ATOMIC") begin :atomic /* verilator lint_on WIDTH */ // in atomic architecture an OVC is available if its not allocated and its empty - assign ovc_avalable_all = ~ovc_status & empty_all; - + assign ovc_avalable_all = ~ovc_status & empty_all; end else begin :nonatomic //NONATOMIC /* verilator lint_off WIDTH */ - if(ROUTE_TYPE == "FULL_ADAPTIVE") begin :full_adpt + if(ROUTE_TYPE == "FULL_ADAPTIVE") begin :full_adpt /* verilator lint_on WIDTH */ - reg [PV-1 : 0] full_adaptive_ovc_mask,full_adaptive_ovc_mask_next; - + reg [PV-1 : 0] full_adaptive_ovc_mask,full_adaptive_ovc_mask_next; always @(*) begin for(k=0; kj) begin: hh - assign ovc_released_gen [i][j] = ovc_released[j][i-V]; - assign credit_decreased_gen[i][j] = credit_decreased[j][i-V]; - end - end else begin :slp - assign ovc_released_gen [i][j] = ovc_released[j][i]; - assign credit_decreased_gen[i][j] = credit_decreased [j][i]; - end + if ( SELF_LOOP_EN=="NO") begin : nslp + if((i/V)j) begin: hh + assign ovc_released_gen [i][j] = ovc_released[j][i-V]; + assign credit_decreased_gen[i][j] = credit_decreased[j][i-V]; + end + end else begin :slp + assign ovc_released_gen [i][j] = ovc_released[j][i]; + assign credit_decreased_gen[i][j] = credit_decreased [j][i]; + end end//j - assign vsa_ovc_released_all [i] = |ovc_released_gen[i]; + assign vsa_ovc_released_all [i] = |ovc_released_gen[i]; assign vsa_credit_decreased_all [i] = (|credit_decreased_gen[i])|vsa_ovc_allocated_all[i]; end//i if ( SELF_LOOP_EN=="NO") begin : nslp - //remove source port from the list - for(i=0;i< P;i=i+1) begin :port_loop - if(i==0) begin :i0 - assign credit_in_perport [i]=credit_in_all [PV-1 : V]; - assign full_perport [i]=full_all [PV-1 : V]; - assign nearly_full_perport [i]=nearly_full_all [PV-1 : V]; - end else if(i==(P-1)) begin :ip_1 - assign credit_in_perport [i]=credit_in_all [PV-V-1 : 0]; - assign full_perport [i]=full_all [PV-V-1 : 0]; - assign nearly_full_perport [i]=nearly_full_all [PV-V-1 : 0]; - end else begin : els - assign credit_in_perport [i]={credit_in_all [PV-1 : (i+1)*V],credit_in_all [(i*V)-1 : 0]}; - assign full_perport [i]={full_all [PV-1 : (i+1)*V],full_all [(i*V)-1 : 0]}; - assign nearly_full_perport [i]={nearly_full_all [PV-1 : (i+1)*V],nearly_full_all[(i*V)-1 : 0]}; - end - end//for - end else begin: slp - for(i=0;i< P;i=i+1) begin :port_loop - assign credit_in_perport [i]=credit_in_all; - assign full_perport [i]=full_all; - assign nearly_full_perport [i]=nearly_full_all; - end + //remove source port from the list + for(i=0;i< P;i=i+1) begin :port_loop + if(i==0) begin :i0 + assign credit_in_perport [i]=credit_in_all [PV-1 : V]; + assign full_perport [i]=full_all [PV-1 : V]; + assign nearly_full_perport [i]=nearly_full_all [PV-1 : V]; + end else if(i==(P-1)) begin :ip_1 + assign credit_in_perport [i]=credit_in_all [PV-V-1 : 0]; + assign full_perport [i]=full_all [PV-V-1 : 0]; + assign nearly_full_perport [i]=nearly_full_all [PV-V-1 : 0]; + end else begin : els + assign credit_in_perport [i]={credit_in_all [PV-1 : (i+1)*V],credit_in_all [(i*V)-1 : 0]}; + assign full_perport [i]={full_all [PV-1 : (i+1)*V],full_all [(i*V)-1 : 0]}; + assign nearly_full_perport [i]={nearly_full_all [PV-1 : (i+1)*V],nearly_full_all[(i*V)-1 : 0]}; + end + end//for + end else begin: slp + for(i=0;i< P;i=i+1) begin :port_loop + assign credit_in_perport [i]=credit_in_all; + assign full_perport [i]=full_all; + assign nearly_full_perport [i]=nearly_full_all; + end end @@ -280,44 +268,44 @@ module output_ports #( for(i=0; i0 && ovc_num[i] >0 && (ovc_num[i] & ovc_status)==0) $display ("%t :Error: OVC status%d missmatch:%b & %b, %m ",$time,i,ovc_num[i] , ovc_status); - end - - + always @(posedge clk)begin + if(ovc_status >0 && ovc_num[i] >0 && (ovc_num[i] & ovc_status)==0) $display ("%t :Error: OVC status%d missmatch:%b & %b, %m ",$time,i,ovc_num[i] , ovc_status); + end end//for endgenerate - - - - endmodule -//synopsys translate_on -//synthesis translate_on +`endif diff --git a/mpsoc/rtl/src_noc/route_mesh.v b/mpsoc/rtl/src_noc/route_mesh.v index cd42a96..c7eb3f3 100755 --- a/mpsoc/rtl/src_noc/route_mesh.v +++ b/mpsoc/rtl/src_noc/route_mesh.v @@ -1,5 +1,4 @@ -`timescale 1ns/1ps - +`include "pronoc_def.v" /********************************************************************** ** File: route_mesh.v ** diff --git a/mpsoc/rtl/src_noc/route_torus.v b/mpsoc/rtl/src_noc/route_torus.v index b7e4c16..540c9a5 100755 --- a/mpsoc/rtl/src_noc/route_torus.v +++ b/mpsoc/rtl/src_noc/route_torus.v @@ -1,4 +1,4 @@ -`timescale 1ns/1ps +`include "pronoc_def.v" /********************************************************************** ** File: route_torus.v diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index f7d28b4..7c7f31b 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -22,464 +22,455 @@ `include "pronoc_def.v" - + module reduction_or #( - parameter W = 5,//out width - parameter N = 4 //array lenght + parameter W = 5,//out width + parameter N = 4 //array lenght )( - in, - out + in, + out ); input [W-1 : 0] in [N-1 : 0]; - output reg [W-1 : 0] out; - + output reg [W-1 : 0] out; + // assign out = in.or(); //it is not synthesizable able by some compiler - always_comb begin - out = {W{1'b0}}; - for (int i = 0; i < N; i++) - out |= in[i]; - end + always_comb begin + out = {W{1'b0}}; + for (int i = 0; i < N; i++) + out |= in[i]; + end endmodule module onehot_mux_2D #( - parameter W = 5,//out width - parameter N = 4 //sel width - )( - in, - sel, - out - ); - - input [W-1 : 0] in [N-1 : 0]; - input [N-1 : 0] sel; - output reg [W-1 : 0] out; - - - always_comb begin - out = {W{1'b0}}; - for (int i = 0; i < N; i++) - out |= (sel[i]) ? in[i] : {W{1'b0}}; - end - + parameter W = 5,//out width + parameter N = 4 //sel width + )( + in, + sel, + out + ); + + input [W-1 : 0] in [N-1 : 0]; + input [N-1 : 0] sel; + output reg [W-1 : 0] out; + + + always_comb begin + out = {W{1'b0}}; + for (int i = 0; i < N; i++) + out |= (sel[i]) ? in[i] : {W{1'b0}}; + end + endmodule - + module onehot_mux_1D #( - parameter W = 5,//out width - parameter N = 4 //sel width - )( - input [W*N-1 : 0] in, - input [N-1 : 0] sel, - output [W-1 : 0] out - ); + parameter W = 5,//out width + parameter N = 4 //sel width + )( + input [W*N-1 : 0] in, + input [N-1 : 0] sel, + output [W-1 : 0] out + ); wire [W-1 : 0] in_array [N-1 : 0]; genvar i; generate for (i=0;i1)begin : have_class - assign hdr_flit.message_class = flit.payload [CLASS_MSB : CLASS_LSB]; - end else begin : no_class - assign hdr_flit.message_class = {Cw{1'b0}}; - end - - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra_b - /* verilator lint_on WIDTH */ - assign hdr_flit.weight = flit.payload [WEIGHT_MSB : WEIGHT_LSB]; - end else begin : rra_b - assign hdr_flit.weight = {WEIGHTw{1'bX}}; - end - - if( BYTE_EN) begin : be_1 - assign hdr_flit.be = flit.payload [BE_MSB : BE_LSB]; - end else begin : be_0 - assign hdr_flit.be = {BEw{1'bX}}; - end - - - assign offset = flit.payload [DATA_MSB : DATA_LSB]; - - - if(Dw > OFFSETw) begin : if1 - assign data_o={{(Dw-OFFSETw){1'b0}},offset}; - end else begin : if2 - assign data_o=offset[Dw-1 : 0]; - end - - endgenerate - - - + generate + if(C>1)begin : have_class + assign hdr_flit.message_class = flit.payload [CLASS_MSB : CLASS_LSB]; + end else begin : no_class + assign hdr_flit.message_class = {Cw{1'b0}}; + end + + /* verilator lint_off WIDTH */ + if(SWA_ARBITER_TYPE != "RRA")begin : wrra_b + /* verilator lint_on WIDTH */ + assign hdr_flit.weight = flit.payload [WEIGHT_MSB : WEIGHT_LSB]; + end else begin : rra_b + assign hdr_flit.weight = {WEIGHTw{1'bX}}; + end + + if( BYTE_EN) begin : be_1 + assign hdr_flit.be = flit.payload [BE_MSB : BE_LSB]; + end else begin : be_0 + assign hdr_flit.be = {BEw{1'bX}}; + end + + + assign offset = flit.payload [DATA_MSB : DATA_LSB]; + + + if(Dw > OFFSETw) begin : if1 + assign data_o={{(Dw-OFFSETw){1'b0}},offset}; + end else begin : if2 + assign data_o=offset[Dw-1 : 0]; + end + + endgenerate endmodule -//synthesis translate_off -//synopsys translate_off - +`ifdef SIMULATION module smart_chanel_check #( - parameter NOC_ID=0 + parameter NOC_ID=0 ) ( - flit_chanel, - smart_chanel, - reset, - clk + flit_chanel, + smart_chanel, + reset, + clk ); - `NOC_CONF - - input flit_chanel_t flit_chanel; - input smart_chanel_t smart_chanel; - input reset,clk; - - smart_chanel_t smart_chanel_delay; - always @(posedge clk) smart_chanel_delay<=smart_chanel; - - hdr_flit_t hdr_flit; - header_flit_info #( - .NOC_ID (NOC_ID) - ) extract ( - .flit(flit_chanel.flit), - .hdr_flit(hdr_flit), - .data_o() - ); - - always @(posedge clk) begin - if(flit_chanel.flit_wr) begin - if(smart_chanel_delay.ovc!=flit_chanel.flit.vc) begin - $display("%t: ERROR: smart ovc %d is not equal with flit ovc %d. %m",$time,smart_chanel_delay.ovc,flit_chanel.flit.vc); - $finish; - end - if(flit_chanel.flit.hdr_flag==1'b1 && hdr_flit.dest_e_addr != smart_chanel_delay.dest_e_addr) begin - $display("%t: ERROR: smart dest_e_addr %d is not equal with flit dest_e_addr %d. %m",$time,smart_chanel_delay.dest_e_addr,hdr_flit.dest_e_addr); - $finish; - end - if(flit_chanel.flit.hdr_flag!=smart_chanel_delay.hdr_flit) begin - $display("%t: ERROR: smart and current hdr flag (%d!=%d) miss-match. %m",$time, smart_chanel_delay.hdr_flit, flit_chanel.flit.hdr_flag); - $finish; - end - - end - - end -endmodule - -//synopsys translate_on -//synthesis translate_on + `NOC_CONF + + input flit_chanel_t flit_chanel; + input smart_chanel_t smart_chanel; + input reset,clk; + + smart_chanel_t smart_chanel_delay; + always @(posedge clk) smart_chanel_delay<=smart_chanel; + + hdr_flit_t hdr_flit; + header_flit_info #( + .NOC_ID (NOC_ID) + ) extract ( + .flit(flit_chanel.flit), + .hdr_flit(hdr_flit), + .data_o() + ); + + always @(posedge clk) begin + if(flit_chanel.flit_wr) begin + if(smart_chanel_delay.ovc!=flit_chanel.flit.vc) begin + $display("%t: ERROR: smart ovc %d is not equal with flit ovc %d. %m",$time,smart_chanel_delay.ovc,flit_chanel.flit.vc); + $finish; + end + if(flit_chanel.flit.hdr_flag==1'b1 && hdr_flit.dest_e_addr != smart_chanel_delay.dest_e_addr) begin + $display("%t: ERROR: smart dest_e_addr %d is not equal with flit dest_e_addr %d. %m",$time,smart_chanel_delay.dest_e_addr,hdr_flit.dest_e_addr); + $finish; + end + if(flit_chanel.flit.hdr_flag!=smart_chanel_delay.hdr_flit) begin + $display("%t: ERROR: smart and current hdr flag (%d!=%d) miss-match. %m",$time, smart_chanel_delay.hdr_flit, flit_chanel.flit.hdr_flag); + $finish; + end + end + end +endmodule +`endif module smart_forward_ivc_info #( - parameter NOC_ID=0, - parameter P=5 -) ( - ivc_info, - iport_info, - oport_info, - smart_chanel, - ovc_locally_requested, - reset,clk + parameter NOC_ID=0, + parameter P=5 +) ( + ivc_info, + iport_info, + oport_info, + smart_chanel, + ovc_locally_requested, + reset,clk ); - - `NOC_CONF - - //ivc info - input reset,clk; - input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; - input iport_info_t iport_info [P-1 : 0]; - input oport_info_t oport_info [P-1 : 0]; - output smart_chanel_t smart_chanel [P-1 : 0]; - output [V-1 : 0] ovc_locally_requested [P-1 : 0]; - - smart_ivc_info_t smart_ivc_info [P-1 : 0][V-1 : 0]; - smart_ivc_info_t smart_ivc_mux [P-1 : 0]; - - smart_ivc_info_t smart_ivc_info_all_port [P-1 : 0] [P-1 : 0]; - smart_ivc_info_t smart_vc_info_o [P-1 : 0]; - - wire [V-1 : 0] assigned_ovc [P-1:0]; - wire [V-1 : 0] non_assigned_vc_req [P-1:0]; - wire [P-1 : 0] mask_gen [P-1 : 0][V-1 :0]; - wire [V-1 : 0] ovc_locally_requested_next [P-1 : 0]; - - /* - P V P P V p - non_assigned_vc_req[i][j] destport_one_hot[z]--> [z][ j][i] - non_assigned_vc_req[0][0] destport_one_hot[3]--> | [3][0] [0] - non_assigned_vc_req[1][0] destport_one_hot[3]--> | [3][0] [1] - non_assigned_vc_req[2][0] destport_one_hot[3]--> | [3][0] [2] - */ - - smart_chanel_t smart_chanel_next [P-1 : 0]; - - - genvar i,j,z; - generate - for (i=0;i [z][ j][i] + non_assigned_vc_req[0][0] destport_one_hot[3]--> | [3][0] [0] + non_assigned_vc_req[1][0] destport_one_hot[3]--> | [3][0] [1] + non_assigned_vc_req[2][0] destport_one_hot[3]--> | [3][0] [2] + */ + + smart_chanel_t smart_chanel_next [P-1 : 0]; + + + genvar i,j,z; + generate + for (i=0;i 4) begin : local_ports - assign goes_straight_o = 1'b0; // There is not a next router in this case at all - end - else begin :non_local - - wire [4 : 0 ] destport_one_hot; - mesh_tori_decode_dstport decoder( - .dstport_encoded(destport_coded_i), - .dstport_one_hot(destport_one_hot) - ); - - assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; - end//else - end//mesh_tori - /* verilator lint_off WIDTH */ - else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :oneD - /* verilator lint_on WIDTH */ - if (SS_PORT_LOC == 0 || SS_PORT_LOC > 2) begin : local_ports - assign goes_straight_o = 1'b0; // There is not a next router in this case at all - end - else begin :non_local - - wire [2: 0 ] destport_one_hot; - - line_ring_decode_dstport decoder( - .dstport_encoded(destport_coded_i), - .dstport_one_hot(destport_one_hot) - - ); - assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; - - end //non_local - end// oneD - - //TODO Add fattree & custom - - endgenerate - -endmodule + parameter TOPOLOGY = "MESH", + parameter ROUTE_NAME = "XY", + parameter ROUTE_TYPE = "DETERMINISTIC", + parameter DSTPw = 4, + parameter SS_PORT_LOC = 1 + )( + destport_coded_i, + goes_straight_o + ); + + input [DSTPw-1 : 0] destport_coded_i; + output goes_straight_o; + + generate + /* verilator lint_off WIDTH */ + if(TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY =="FMESH") begin :twoD + /* verilator lint_on WIDTH */ + if (SS_PORT_LOC == 0 || SS_PORT_LOC > 4) begin : local_ports + assign goes_straight_o = 1'b0; // There is not a next router in this case at all + end + else begin :non_local + + wire [4 : 0 ] destport_one_hot; + mesh_tori_decode_dstport decoder( + .dstport_encoded(destport_coded_i), + .dstport_one_hot(destport_one_hot) + ); + + assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; + end//else + end//mesh_tori + /* verilator lint_off WIDTH */ + else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :oneD + /* verilator lint_on WIDTH */ + if (SS_PORT_LOC == 0 || SS_PORT_LOC > 2) begin : local_ports + assign goes_straight_o = 1'b0; // There is not a next router in this case at all + end + else begin :non_local + + wire [2: 0 ] destport_one_hot; + + line_ring_decode_dstport decoder( + .dstport_encoded(destport_coded_i), + .dstport_one_hot(destport_one_hot) + + ); + assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; + + end //non_local + end// oneD + + //TODO Add fattree & custom + + endgenerate + +endmodule - + module smart_validity_check_per_ivc #( - parameter NOC_ID=0, - parameter IVC_NUM = 0 + parameter NOC_ID=0, + parameter IVC_NUM = 0 ) ( - reset, - clk, - //smart channel - goes_straight , - smart_requests_i, - smart_ivc_i, - smart_hdr_flit, - //flit - flit_hdr_flag_i, - flit_tail_flag_i, - flit_wr_i, - //router ivc status - ovc_locally_requested, - assigned_to_ss_ovc, - assigned_ovc_not_full, - ovc_is_assigned, - ivc_request, - //ss port status - ss_ovc_avalable_in_ss_port, - ss_port_link_reg_flit_wr, - ss_ovc_crossbar_wr, - //output - smart_single_flit_pck_o, - smart_ivc_smart_en_o, - smart_credit_o, - smart_buff_space_decreased_o, - smart_ss_ovc_is_allocated_o, - smart_ss_ovc_is_released_o, - smart_mask_available_ss_ovc_o, - smart_ivc_num_getting_ovc_grant_o, - smart_ivc_reset_o, - smart_ivc_granted_ovc_num_o + reset, + clk, + //smart channel + goes_straight , + smart_requests_i, + smart_ivc_i, + smart_hdr_flit, + //flit + flit_hdr_flag_i, + flit_tail_flag_i, + flit_wr_i, + //router ivc status + ovc_locally_requested, + assigned_to_ss_ovc, + assigned_ovc_not_full, + ovc_is_assigned, + ivc_request, + //ss port status + ss_ovc_avalable_in_ss_port, + ss_port_link_reg_flit_wr, + ss_ovc_crossbar_wr, + //output + smart_single_flit_pck_o, + smart_ivc_smart_en_o, + smart_credit_o, + smart_buff_space_decreased_o, + smart_ss_ovc_is_allocated_o, + smart_ss_ovc_is_released_o, + smart_mask_available_ss_ovc_o, + smart_ivc_num_getting_ovc_grant_o, + smart_ivc_reset_o, + smart_ivc_granted_ovc_num_o ); - - - `NOC_CONF - - - input reset, clk; - //smart channel - input goes_straight, - smart_requests_i, - smart_ivc_i, - smart_hdr_flit, - //flit - flit_hdr_flag_i , - flit_tail_flag_i, - flit_wr_i, - //router ivc status - ovc_locally_requested, - assigned_to_ss_ovc, - assigned_ovc_not_full, - ovc_is_assigned, - ivc_request, - //ss port status - ss_ovc_avalable_in_ss_port, - ss_ovc_crossbar_wr, - ss_port_link_reg_flit_wr; + + + `NOC_CONF + + + input reset, clk; + //smart channel + input goes_straight, + smart_requests_i, + smart_ivc_i, + smart_hdr_flit, + //flit + flit_hdr_flag_i , + flit_tail_flag_i, + flit_wr_i, + //router ivc status + ovc_locally_requested, + assigned_to_ss_ovc, + assigned_ovc_not_full, + ovc_is_assigned, + ivc_request, + //ss port status + ss_ovc_avalable_in_ss_port, + ss_ovc_crossbar_wr, + ss_port_link_reg_flit_wr; //output output - smart_single_flit_pck_o , - smart_ivc_smart_en_o, - smart_credit_o, - smart_buff_space_decreased_o, - smart_ss_ovc_is_allocated_o, - smart_ss_ovc_is_released_o, - smart_ivc_num_getting_ovc_grant_o, - smart_ivc_reset_o, - smart_mask_available_ss_ovc_o; - + smart_single_flit_pck_o , + smart_ivc_smart_en_o, + smart_credit_o, + smart_buff_space_decreased_o, + smart_ss_ovc_is_allocated_o, + smart_ss_ovc_is_released_o, + smart_ivc_num_getting_ovc_grant_o, + smart_ivc_reset_o, + smart_mask_available_ss_ovc_o; + output reg [V-1 : 0] smart_ivc_granted_ovc_num_o; always @(*) begin - smart_ivc_granted_ovc_num_o={V{1'b0}}; - smart_ivc_granted_ovc_num_o[IVC_NUM]=smart_ivc_num_getting_ovc_grant_o; -end - - - + smart_ivc_granted_ovc_num_o={V{1'b0}}; + smart_ivc_granted_ovc_num_o[IVC_NUM]=smart_ivc_num_getting_ovc_grant_o; +end + + + wire smart_req_valid_next = smart_requests_i & smart_ivc_i & goes_straight; -logic smart_req_valid; +logic smart_req_valid; wire smart_hdr_flit_req_next = smart_req_valid_next & smart_hdr_flit; logic smart_hdr_flit_req; - + pronoc_register #(.W(1)) req1 (.in(smart_req_valid_next), .reset(reset), .clk(clk), .out(smart_req_valid)); pronoc_register #(.W(1)) req2 (.in(smart_hdr_flit_req_next), .reset(reset), .clk(clk), .out(smart_hdr_flit_req)); - + // condition1: new smart vc allocation condition -wire hdr_flit_condition = ~ovc_locally_requested & ss_ovc_avalable_in_ss_port; +wire hdr_flit_condition = ~ovc_locally_requested & ss_ovc_avalable_in_ss_port; wire nonhdr_flit_condition = assigned_to_ss_ovc & assigned_ovc_not_full; wire condition1 = - /* verilator lint_off WIDTH */ - (PCK_TYPE == "SINGLE_FLIT")? hdr_flit_condition : - /* verilator lint_on WIDTH */ - (ovc_is_assigned)? nonhdr_flit_condition : hdr_flit_condition; + /* verilator lint_off WIDTH */ + (PCK_TYPE == "SINGLE_FLIT")? hdr_flit_condition : + /* verilator lint_on WIDTH */ + (ovc_is_assigned)? nonhdr_flit_condition : hdr_flit_condition; wire condition2; generate @@ -659,24 +650,24 @@ generate wire non_empty_ivc_condition =(PCK_TYPE == "SINGLE_FLIT")? 1'b0 :ivc_request; /* verilator lint_on WIDTH */ - + if( ADD_PIPREG_AFTER_CROSSBAR == 1) begin :link_reg - assign condition2= ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr| ss_ovc_crossbar_wr); + assign condition2= ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr| ss_ovc_crossbar_wr); end else begin : no_link_reg - assign condition2= ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr); // ss_port_link_reg_flit_wr are identical with ss_ovc_crossbar_wr when there is no link reg + assign condition2= ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr); // ss_port_link_reg_flit_wr are identical with ss_ovc_crossbar_wr when there is no link reg end - -endgenerate + +endgenerate wire conditions_met = condition1 & condition2; assign smart_ivc_smart_en_o = conditions_met & smart_req_valid; - + assign smart_single_flit_pck_o = - /* verilator lint_off WIDTH */ - (PCK_TYPE == "SINGLE_FLIT")? 1'b1 : - /* verilator lint_on WIDTH */ - (MIN_PCK_SIZE==1)? flit_tail_flag_i & flit_hdr_flag_i : 1'b0; + /* verilator lint_off WIDTH */ + (PCK_TYPE == "SINGLE_FLIT")? 1'b1 : + /* verilator lint_on WIDTH */ + (MIN_PCK_SIZE==1)? flit_tail_flag_i & flit_hdr_flag_i : 1'b0; assign smart_buff_space_decreased_o = smart_ivc_smart_en_o & flit_wr_i ; assign smart_ivc_num_getting_ovc_grant_o = smart_buff_space_decreased_o & !ovc_is_assigned & flit_hdr_flag_i; @@ -686,276 +677,276 @@ assign smart_ss_ovc_is_allocated_o = smart_ivc_num_getting_ovc_grant_o & ~smart_ - + //mask the available SS OVC for local requests allocation if the following conditions met assign smart_mask_available_ss_ovc_o = smart_hdr_flit_req & ~ovc_locally_requested & condition2; - - + + pronoc_register #(.W(1)) credit(.in(smart_buff_space_decreased_o), .reset(reset), .clk(clk), .out(smart_credit_o)); - + endmodule - - - + + + module smart_allocator_per_iport # ( - parameter NOC_ID=0, - parameter P=5, - parameter SW_LOC=0, - parameter SS_PORT_LOC=1 + parameter NOC_ID=0, + parameter P=5, + parameter SW_LOC=0, + parameter SS_PORT_LOC=1 ) ( - //general - clk, - reset, - current_r_addr_i, - neighbors_r_addr_i, - //smart_chanel & flit in - smart_chanel_i, - flit_chanel_i, - //router status signals - ivc_info, - ss_ovc_info, - ovc_locally_requested,//make sure no conflict is existed between local & SMART VC allocation - ss_port_link_reg_flit_wr, - ss_smart_chanel_new, - //output - smart_destport_o, - smart_lk_destport_o, - smart_ivc_smart_en_o, - smart_credit_o, - smart_buff_space_decreased_o, - smart_ss_ovc_is_allocated_o, - smart_ss_ovc_is_released_o, - smart_ivc_num_getting_ovc_grant_o, - smart_ivc_reset_o, - smart_mask_available_ss_ovc_o, - smart_hdr_flit_req_o, - smart_ivc_granted_ovc_num_o, - smart_ivc_single_flit_pck_o, - smart_ovc_single_flit_pck_o + //general + clk, + reset, + current_r_addr_i, + neighbors_r_addr_i, + //smart_chanel & flit in + smart_chanel_i, + flit_chanel_i, + //router status signals + ivc_info, + ss_ovc_info, + ovc_locally_requested,//make sure no conflict is existed between local & SMART VC allocation + ss_port_link_reg_flit_wr, + ss_smart_chanel_new, + //output + smart_destport_o, + smart_lk_destport_o, + smart_ivc_smart_en_o, + smart_credit_o, + smart_buff_space_decreased_o, + smart_ss_ovc_is_allocated_o, + smart_ss_ovc_is_released_o, + smart_ivc_num_getting_ovc_grant_o, + smart_ivc_reset_o, + smart_mask_available_ss_ovc_o, + smart_hdr_flit_req_o, + smart_ivc_granted_ovc_num_o, + smart_ivc_single_flit_pck_o, + smart_ovc_single_flit_pck_o ); - - `NOC_CONF - - //general - input clk, reset; - input [RAw-1 :0] current_r_addr_i; - input [RAw-1: 0] neighbors_r_addr_i [P-1 : 0]; - //channels - input smart_chanel_t smart_chanel_i; - input flit_chanel_t flit_chanel_i; - //ivc - input ivc_info_t ivc_info [V-1 : 0]; - input [V-1 : 0] ovc_locally_requested; - //ss port - input ovc_info_t ss_ovc_info [V-1 : 0]; - input ss_port_link_reg_flit_wr; - input smart_chanel_t ss_smart_chanel_new; - //output - output [DSTPw-1 : 0] smart_destport_o,smart_lk_destport_o; - output smart_hdr_flit_req_o; - output [V-1 : 0] - smart_ivc_smart_en_o, - smart_credit_o, - smart_buff_space_decreased_o, - smart_ss_ovc_is_allocated_o, - smart_ss_ovc_is_released_o, - smart_mask_available_ss_ovc_o, - smart_ivc_num_getting_ovc_grant_o, - smart_ivc_reset_o, - smart_ivc_single_flit_pck_o, - smart_ovc_single_flit_pck_o; - output [V*V-1 : 0] smart_ivc_granted_ovc_num_o; - - assign smart_ovc_single_flit_pck_o = smart_ivc_single_flit_pck_o; - wire [DSTPw-1 : 0] destport,lkdestport; - wire goes_straight; - - - - /* verilator lint_off WIDTH */ - localparam LOCATED_IN_NI= - (TOPOLOGY=="RING" || TOPOLOGY=="LINE") ? (SW_LOC == 0 || SW_LOC>2) : - (TOPOLOGY =="MESH" || TOPOLOGY=="TORUS" || TOPOLOGY == "FMESH")? (SW_LOC == 0 || SW_LOC>4) : 0; - /* verilator lint_on WIDTH */ - - // does the route computation for the current router - conventional_routing #( - .NOC_ID (NOC_ID), - .TOPOLOGY (TOPOLOGY), - .ROUTE_NAME (ROUTE_NAME), - .ROUTE_TYPE (ROUTE_TYPE), - .T1 (T1), - .T2 (T2), - .T3 (T3), - .RAw (RAw), - .EAw (EAw), - .DSTPw (DSTPw), - .LOCATED_IN_NI (LOCATED_IN_NI) - ) routing ( - .reset (reset), - .clk (clk), - .current_r_addr (current_r_addr_i), - .src_e_addr ( ),// needed only for custom routing - .dest_e_addr (smart_chanel_i.dest_e_addr), - .destport (destport) - ); - - pronoc_register #(.W(DSTPw)) reg1 (.in(destport), .reset(reset), .clk(clk), .out(smart_destport_o)); - - check_straight_oport #( - .TOPOLOGY ( TOPOLOGY), - .ROUTE_NAME ( ROUTE_NAME), - .ROUTE_TYPE ( ROUTE_TYPE), - .DSTPw ( DSTPw), - .SS_PORT_LOC ( SS_PORT_LOC) - ) check_straight ( - .destport_coded_i (destport), - .goes_straight_o (goes_straight) - ); - - //look ahead routing. take straight next router address as input - conventional_routing #( - .NOC_ID(NOC_ID), - .TOPOLOGY (TOPOLOGY), - .ROUTE_NAME (ROUTE_NAME), - .ROUTE_TYPE (ROUTE_TYPE), - .T1 (T1), - .T2 (T2), - .T3 (T3), - .RAw (RAw), - .EAw (EAw), - .DSTPw (DSTPw), - .LOCATED_IN_NI (LOCATED_IN_NI) - ) lkrouting ( - .reset (reset), - .clk (clk), - .current_r_addr (neighbors_r_addr_i[SS_PORT_LOC]), - .src_e_addr ( ),// needed only for custom routing - .dest_e_addr (smart_chanel_i.dest_e_addr), - .destport (lkdestport) - ); - - pronoc_register #(.W(DSTPw)) reg2 (.in(lkdestport), .reset(reset), .clk(clk), .out(smart_lk_destport_o)); - - wire [V-1 : 0] ss_ovc_crossbar_wr;//If asserted, a flit will be injected to ovc at next clk cycle - assign ss_ovc_crossbar_wr = (ss_smart_chanel_new.requests[0]) ? ss_smart_chanel_new.ovc : {V{1'b0}}; - - - - //assign smart_ivc_num_getting_ovc_grant_o = smart_ss_ovc_is_allocated_o; - //assign smart_ivc_reset_o = smart_ss_ovc_is_released_o; - - genvar i,j; - generate - for (i=0;i2) : + (TOPOLOGY =="MESH" || TOPOLOGY=="TORUS" || TOPOLOGY == "FMESH")? (SW_LOC == 0 || SW_LOC>4) : 0; + /* verilator lint_on WIDTH */ + + // does the route computation for the current router + conventional_routing #( + .NOC_ID (NOC_ID), + .TOPOLOGY (TOPOLOGY), + .ROUTE_NAME (ROUTE_NAME), + .ROUTE_TYPE (ROUTE_TYPE), + .T1 (T1), + .T2 (T2), + .T3 (T3), + .RAw (RAw), + .EAw (EAw), + .DSTPw (DSTPw), + .LOCATED_IN_NI (LOCATED_IN_NI) + ) routing ( + .reset (reset), + .clk (clk), + .current_r_addr (current_r_addr_i), + .src_e_addr ( ),// needed only for custom routing + .dest_e_addr (smart_chanel_i.dest_e_addr), + .destport (destport) + ); + + pronoc_register #(.W(DSTPw)) reg1 (.in(destport), .reset(reset), .clk(clk), .out(smart_destport_o)); + + check_straight_oport #( + .TOPOLOGY ( TOPOLOGY), + .ROUTE_NAME ( ROUTE_NAME), + .ROUTE_TYPE ( ROUTE_TYPE), + .DSTPw ( DSTPw), + .SS_PORT_LOC ( SS_PORT_LOC) + ) check_straight ( + .destport_coded_i (destport), + .goes_straight_o (goes_straight) + ); + + //look ahead routing. take straight next router address as input + conventional_routing #( + .NOC_ID(NOC_ID), + .TOPOLOGY (TOPOLOGY), + .ROUTE_NAME (ROUTE_NAME), + .ROUTE_TYPE (ROUTE_TYPE), + .T1 (T1), + .T2 (T2), + .T3 (T3), + .RAw (RAw), + .EAw (EAw), + .DSTPw (DSTPw), + .LOCATED_IN_NI (LOCATED_IN_NI) + ) lkrouting ( + .reset (reset), + .clk (clk), + .current_r_addr (neighbors_r_addr_i[SS_PORT_LOC]), + .src_e_addr ( ),// needed only for custom routing + .dest_e_addr (smart_chanel_i.dest_e_addr), + .destport (lkdestport) + ); + + pronoc_register #(.W(DSTPw)) reg2 (.in(lkdestport), .reset(reset), .clk(clk), .out(smart_lk_destport_o)); + + wire [V-1 : 0] ss_ovc_crossbar_wr;//If asserted, a flit will be injected to ovc at next clk cycle + assign ss_ovc_crossbar_wr = (ss_smart_chanel_new.requests[0]) ? ss_smart_chanel_new.ovc : {V{1'b0}}; + + + + //assign smart_ivc_num_getting_ovc_grant_o = smart_ss_ovc_is_allocated_o; + //assign smart_ivc_reset_o = smart_ss_ovc_is_released_o; + + genvar i,j; + generate + for (i=0;i 0) counter_next = counter -1'b1; - end + logic [Bw : 0] counter, counter_next; + + always @(*) begin + counter_next=counter; + if(credit_in & smart_credit_in) counter_next = counter +1'b1; + else if(credit_in | smart_credit_in) counter_next=counter; + else if(counter > 0) counter_next = counter -1'b1; + end - assign credit_out = credit_in | smart_credit_in | (counter > 0); + assign credit_out = credit_in | smart_credit_in | (counter > 0); - pronoc_register #(.W(Bw+1)) reg1 (.in(counter_next), .reset(reset), .clk(clk), .out(counter)); - + pronoc_register #(.W(Bw+1)) reg1 (.in(counter_next), .reset(reset), .clk(clk), .out(counter)); + endmodule @@ -973,6 +964,6 @@ endmodule - + diff --git a/mpsoc/rtl/src_noc/routing.v b/mpsoc/rtl/src_noc/routing.v index b775a45..03f1d8a 100755 --- a/mpsoc/rtl/src_noc/routing.v +++ b/mpsoc/rtl/src_noc/routing.v @@ -1,4 +1,4 @@ -`timescale 1ns/1ps +`include "pronoc_def.v" /********************************************************************** ** File: routing.v ** diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index a219c8d..e2eb9d2 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -1,36 +1,35 @@ `include "pronoc_def.v" - /********************************************************************** -** File: ss_allocator.v -** Date:2016-06-19 +** File: ss_allocator.v +** Date:2016-06-19 ** -** Copyright (C) 2014-2019 Alireza Monemi +** Copyright (C) 2014-2019 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** static straight allocator : The incoming packet targeting output port located in same direction -** will be forwarded with one clock cycle latency if the following conditions met in current clock cycle: -** 1) If no ivc is granted in the input port -** 2) The ss output port is not granted for any other input port -** 3) Packet destination port match with ss port -** 4) The requested output VC is available in ss port -** The ss ports for each input potrt must be different with the rest -** This result in one clock cycle latency +** Description: +** static straight allocator : The incoming packet targeting output port located in same direction +** will be forwarded with one clock cycle latency if the following conditions met in current clock cycle: +** 1) If no ivc is granted in the input port +** 2) The ss output port is not granted for any other input port +** 3) Packet destination port match with ss port +** 4) The requested output VC is available in ss port +** The ss ports for each input potrt must be different with the rest +** This result in one clock cycle latency ***************************************/ @@ -38,9 +37,9 @@ module ss_allocator #( parameter NOC_ID=0, parameter P=5 )( - clk, - reset, - flit_in_wr_all, + clk, + reset, + flit_in_wr_all, flit_in_all, any_ovc_granted_in_outport_all , any_ivc_sw_request_granted_all , @@ -55,10 +54,10 @@ module ss_allocator #( ); - `NOC_CONF - + `NOC_CONF + localparam PV = V * P, - VV = V * V, + VV = V * V, PVV = PV * V, PVDSTPw= PV * DSTPw, PFw = P * Fw; @@ -104,7 +103,7 @@ module ss_allocator #( wire [PV-1 : 0] ovc_is_assigned_all; wire [MAX_P-1 : 0] destport_one_hot [PV-1 : 0]; - genvar i; + genvar i; // there is no ssa for local port in 5 and 3 port routers generate for (i=0; iSS_PORT) ? SS_PORT : SS_PORT-1; - always @(*)begin - destport_temp=destport_in; - if(destport_in=={P_1{1'b0}}) begin - destport_temp[SS_PORT_CODE]= 1'b1; - end - end - assign destport_out = destport_temp; - end + reg [P_1-1 : 0] destport_temp; + /* verilator lint_off WIDTH */ + if( SELF_LOOP_EN=="YES") begin : slp + /* verilator lint_on WIDTH */ + always @(*)begin + destport_temp=destport_in; + if(destport_in=={P_1{1'b0}}) destport_temp[SS_PORT]= 1'b1; + end + assign destport_out = destport_temp; + end else begin : nslp + localparam SS_PORT_CODE = (SW_LOC>SS_PORT) ? SS_PORT : SS_PORT-1; + always @(*)begin + destport_temp=destport_in; + if(destport_in=={P_1{1'b0}}) begin + destport_temp[SS_PORT_CODE]= 1'b1; + end + end + assign destport_out = destport_temp; + end end //ss endgenerate diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 8b33bdb..d4f51cc 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -1,3 +1,4 @@ +`include "pronoc_def.v" /************************************** * Module: localparameter * Date:2019-04-08 @@ -5,58 +6,57 @@ * * Description: ***************************************/ - `ifdef INCLUDE_TOPOLOGY_LOCALPARAM - +`ifdef INCLUDE_TOPOLOGY_LOCALPARAM //MESH, TORUS Topology p=5 - localparam LOCAL = 0, - EAST = 1, - NORTH = 2, - WEST = 3, - SOUTH = 4; - - - + localparam + LOCAL = 0, + EAST = 1, + NORTH = 2, + WEST = 3, + SOUTH = 4; + //LINE RING Topology p=3 - localparam FORWARD = 1, - BACKWARD= 2; - - - function automatic integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 4 ) port_buffer_size = LB; + if (router_port_num == 0 || router_port_num > 4 ) port_buffer_size = LB; end - end + end endfunction - - - - - -/******************* -* "RING" "LINE" "MESH" TORUS" "FMESH" -******************/ - - - -/* verilator lint_off WIDTH */ -//route type -localparam - NX = T1, - NY = T2, - NL = T3, - NXw = log2(NX), - NYw= log2(NY), - NLw= log2(NL), - PPSw_MESH_TORI =4, //port presel width for adaptive routing - - /* verilator lint_off WIDTH */ - ROUTE_TYPE_MESH_TORI = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : - (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", - - R2R_CHANELS_MESH_TORI= (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? 2 : 4, - R2E_CHANELS_MESH_TORI= NL, - RAw_MESH_TORI = ( TOPOLOGY == "RING" || TOPOLOGY == "LINE")? NXw : NXw + NYw, - EAw_MESH_TORI = (NL==1) ? RAw_MESH_TORI : RAw_MESH_TORI + NLw, - NR_MESH_TORI = (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? NX : NX*NY, - NE_MESH_TORI = NR_MESH_TORI * NL, - MAX_P_MESH_TORI = R2R_CHANELS_MESH_TORI + R2E_CHANELS_MESH_TORI, - DSTPw_MESH_TORI = R2R_CHANELS_MESH_TORI; // P-1 - - /* verilator lint_on WIDTH */ - -/**************** - * FMESH - * *************/ - localparam - NE_FMESH = NE_MESH_TORI + 2 * (NX+NY), - NR_FMESH = NR_MESH_TORI, - MAX_P_FMESH = 4 + NL, - EAw_FMESH = RAw_MESH_TORI + log2(MAX_P_FMESH); - - - /****************** - * FATTREE - * *****************/ -localparam - K=T1, - L=T2, - Lw=log2(L), - Kw=log2(K), - LKw=L*Kw, - RAw_FATTREE = LKw + Lw, - EAw_FATTREE = LKw, - NE_FATTREE = powi( K,L ), - NR_FATTREE = L * powi( K , L - 1 ), // total number of routers - ROUTE_TYPE_FATTREE = "DETERMINISTIC", - DSTPw_FATTREE = K+1, - MAX_P_FATTREE = 2*K, - DAw_MCAST_FATTREE= powi( K,L); - - - -/********************** - * TREE - * ********************/ -localparam - ROUTE_TYPE_TREE = "DETERMINISTIC", - NE_TREE = powi( K,L ), //total number of endpoints - NR_TREE = sum_powi ( K,L ), // total number of routers - RAw_TREE = LKw + Lw, - EAw_TREE = LKw, - DSTPw_TREE = log2(K+1), - MAX_P_TREE = K+1, - DAw_MCAST_TREE= DAw_MCAST_FATTREE; - - -/********************* - * STAR - * ******************/ - localparam - ROUTE_TYPE_STAR = "DETERMINISTIC", - NE_STAR = T1, //total number of endpoints - NR_STAR = 1, // total number of routers - RAw_STAR = 1, - EAw_STAR = log2(NE_STAR), - DSTPw_STAR = (CAST_TYPE!= "UNICAST")? NE_STAR :EAw_STAR, - MAX_P_STAR = NE_STAR, - DAw_MCAST_STAR= NE_STAR; - - /************************ - * CUSTOM - made by netmaker - * **********************/ - localparam - ROUTE_TYPE_CUSTOM = "DETERMINISTIC", - NE_CUSTOM = T1, //total number of endpoints - NR_CUSTOM = T2, // total number of routers - EAw_CUSTOM = log2(NE_CUSTOM), - RAw_CUSTOM = log2(NR_CUSTOM), - MAX_P_CUSTOM = T3, - DSTPw_CUSTOM = log2(MAX_P_CUSTOM); + /******************* + * "RING" "LINE" "MESH" TORUS" "FMESH" + ******************/ + /* verilator lint_off WIDTH */ + //route type + localparam + NX = T1, + NY = T2, + NL = T3, + NXw = log2(NX), + NYw= log2(NY), + NLw= log2(NL), + PPSw_MESH_TORI =4, //port presel width for adaptive routing + /* verilator lint_off WIDTH */ + ROUTE_TYPE_MESH_TORI = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : + (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", + R2R_CHANELS_MESH_TORI= (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? 2 : 4, + R2E_CHANELS_MESH_TORI= NL, + RAw_MESH_TORI = ( TOPOLOGY == "RING" || TOPOLOGY == "LINE")? NXw : NXw + NYw, + EAw_MESH_TORI = (NL==1) ? RAw_MESH_TORI : RAw_MESH_TORI + NLw, + NR_MESH_TORI = (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? NX : NX*NY, + NE_MESH_TORI = NR_MESH_TORI * NL, + MAX_P_MESH_TORI = R2R_CHANELS_MESH_TORI + R2E_CHANELS_MESH_TORI, + DSTPw_MESH_TORI = R2R_CHANELS_MESH_TORI; // P-1 + /* verilator lint_on WIDTH */ - - + /**************** + * FMESH + **************/ + localparam + NE_FMESH = NE_MESH_TORI + 2 * (NX+NY), + NR_FMESH = NR_MESH_TORI, + MAX_P_FMESH = 4 + NL, + EAw_FMESH = RAw_MESH_TORI + log2(MAX_P_FMESH); + /****************** + * FATTREE + * *****************/ + localparam + K=T1, + L=T2, + Lw=log2(L), + Kw=log2(K), + LKw=L*Kw, + RAw_FATTREE = LKw + Lw, + EAw_FATTREE = LKw, + NE_FATTREE = powi( K,L ), + NR_FATTREE = L * powi( K , L - 1 ), // total number of routers + ROUTE_TYPE_FATTREE = "DETERMINISTIC", + DSTPw_FATTREE = K+1, + MAX_P_FATTREE = 2*K, + DAw_MCAST_FATTREE= powi( K,L); + /********************** + * TREE + *********************/ + localparam + ROUTE_TYPE_TREE = "DETERMINISTIC", + NE_TREE = powi( K,L ), //total number of endpoints + NR_TREE = sum_powi ( K,L ), // total number of routers + RAw_TREE = LKw + Lw, + EAw_TREE = LKw, + DSTPw_TREE = log2(K+1), + MAX_P_TREE = K+1, + DAw_MCAST_TREE= DAw_MCAST_FATTREE; + /********************* + * STAR + *******************/ + localparam + ROUTE_TYPE_STAR = "DETERMINISTIC", + NE_STAR = T1, //total number of endpoints + NR_STAR = 1, // total number of routers + RAw_STAR = 1, + EAw_STAR = log2(NE_STAR), + DSTPw_STAR = (CAST_TYPE!= "UNICAST")? NE_STAR :EAw_STAR, + MAX_P_STAR = NE_STAR, + DAw_MCAST_STAR= NE_STAR; + /************************ + * CUSTOM - made by netmaker + ***********************/ + localparam + ROUTE_TYPE_CUSTOM = "DETERMINISTIC", + NE_CUSTOM = T1, //total number of endpoints + NR_CUSTOM = T2, // total number of routers + EAw_CUSTOM = log2(NE_CUSTOM), + RAw_CUSTOM = log2(NR_CUSTOM), + MAX_P_CUSTOM = T3, + DSTPw_CUSTOM = log2(MAX_P_CUSTOM); /* verilator lint_off WIDTH */ localparam PPSw = PPSw_MESH_TORI, @@ -227,7 +202,6 @@ localparam (TOPOLOGY == "FMESH")? MAX_P_MESH_TORI: (TOPOLOGY == "STAR") ? MAX_P_STAR: MAX_P_CUSTOM, - // destination port width in header flit DSTPw = // Each asserted bit indicats that the flit should be sent to that port @@ -264,25 +238,16 @@ localparam NE_CUSTOM, //Destination endpoint(s) address width - - DAw_OFFSETw = (TOPOLOGY=="MESH" || TOPOLOGY=="TORUS" || TOPOLOGY=="FMESH")? NX : 0, - MCAST_PRTLw = mcast_partial_width( MCAST_ENDP_LIST), - MCASTw = (CAST_TYPE == "MULTICAST_FULL") ? NE : (CAST_TYPE == "MULTICAST_PARTIAL" && EAw >= MCAST_PRTLw) ? EAw +1 : (CAST_TYPE == "MULTICAST_PARTIAL" && EAw < MCAST_PRTLw) ? MCAST_PRTLw +1 : EAw +1, //broadcast - DAw = (CAST_TYPE == "UNICAST") ? EAw: MCASTw + DAw_OFFSETw, - - - - //total number of routers NR = (TOPOLOGY == "FATTREE")? NR_FATTREE: @@ -299,19 +264,12 @@ localparam (TOPOLOGY == "FMESH")? ROUTE_TYPE_MESH_TORI: (TOPOLOGY == "STAR") ? ROUTE_TYPE_STAR: ROUTE_TYPE_CUSTOM; - /* verilator lint_on WIDTH */ - - - - - - function automatic integer mcast_id_to_endp_id; - input integer mcast_id; - reg [NE-1 : 0] mcast_list; - integer k; - begin + input integer mcast_id; + reg [NE-1 : 0] mcast_list; + integer k; + begin mcast_list =MCAST_ENDP_LIST; mcast_id_to_endp_id=0; k=0; @@ -322,19 +280,19 @@ localparam end else begin while( k!=mcast_id+1) begin if( mcast_list[mcast_id_to_endp_id]==1'b1) begin - k=k+1; + k=k+1; end mcast_id_to_endp_id= mcast_id_to_endp_id+1; end end - end + end endfunction - - function automatic integer endp_id_to_mcast_id; - input integer endp_id; - reg [NE-1 : 0] mcast_list; - integer i; - begin + + function automatic integer endp_id_to_mcast_id; + input integer endp_id; + reg [NE-1 : 0] mcast_list; + integer i; + begin /* verilator lint_off WIDTH */ if (CAST_TYPE == "MULTICAST_FULL") begin /* verilator lint_on WIDTH */ @@ -346,82 +304,73 @@ localparam if( mcast_list[i]==1'b1) endp_id_to_mcast_id=endp_id_to_mcast_id+1; end end - end + end endfunction - - function automatic integer mcast_partial_width; - input [NE-1 : 0] p; - integer i; - begin - - mcast_partial_width=0; - for (i=0;i Date: Fri, 14 Feb 2025 19:57:48 +0100 Subject: [PATCH 012/107] fix linting --- mpsoc/rtl/src_noc/mesh_torus.sv | 1451 ++++++++++---------------- mpsoc/rtl/src_noc/multicast.sv | 1425 ++++++++++++------------- mpsoc/rtl/src_noc/output_ports.sv | 288 ++--- mpsoc/rtl/src_noc/route_mesh.v | 677 +++++------- mpsoc/rtl/src_noc/route_torus.v | 531 ++++------ mpsoc/rtl/src_noc/router_bypass.sv | 685 +++++------- mpsoc/rtl/src_noc/traffic_gen_top.sv | 4 +- 7 files changed, 2025 insertions(+), 3036 deletions(-) diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 4f6f79c..c85e333 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -1,6 +1,6 @@ `include "pronoc_def.v" /********************************************************************** -** File: mesh_torus.v +** File: mesh_torus.v ** ** Copyright (C) 2014-2017 Alireza Monemi ** @@ -26,28 +26,20 @@ ***************************************/ - - -/***************************************** - -pre-sel[xy] - y -1 | 3 - | - -------x -0 | 2 - | - -*****************************************/ - - +/************************** +* pre-sel[xy] +* y +* 1 | 3 +* ---------x +* 0 | 2 +***************************/ module mesh_torus_vc_alloc_request_gen_adaptive #( - parameter ROUTE_TYPE = "FULL_ADAPTIVE", // "FULL_ADAPTIVE", "PAR_ADAPTIVE" + parameter ROUTE_TYPE = "FULL_ADAPTIVE", // "FULL_ADAPTIVE", "PAR_ADAPTIVE" parameter V = 4, parameter DSTPw=4, parameter SSA_EN ="NO", parameter PPSw=4, - parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000 // mask scape vc, valid only for full adaptive + parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000 // mask scape vc, valid only for full adaptive )( ovc_avalable_all, dest_port_coded_all, @@ -62,130 +54,110 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( ssa_ivc_num_getting_ovc_grant_all, sel, reset, - clk - + clk ); - localparam P = 5; - - localparam P_1 = P-1, - PV = V * P, - PVV = PV * V, - VP_1 = V * P_1, - PVDSTPw = PV * DSTPw; - - localparam LOCAL = 3'd0, - EAST = 3'd1, - NORTH = 3'd2, - WEST = 3'd3, - SOUTH = 3'd4; - - input [PV-1 : 0] ovc_avalable_all; - input [PVDSTPw-1 : 0] dest_port_coded_all; - input [PV-1 : 0] ivc_request_all; - input [PV-1 : 0] ovc_is_assigned_all; - output [PVV-1 : 0] masked_ovc_request_all; - input [PVV-1 : 0] candidate_ovc_all; - input [PPSw-1 : 0] port_pre_sel; - output [PV-1 : 0] swap_port_presel; - output [PV-1 : 0] sel; + localparam + P = 5, + P_1 = P-1, + PV = V * P, + PVV = PV * V, + VP_1 = V * P_1, + PVDSTPw = PV * DSTPw; + + localparam + LOCAL = 3'd0, + EAST = 3'd1, + NORTH = 3'd2, + WEST = 3'd3, + SOUTH = 3'd4; + + input [PV-1 : 0] ovc_avalable_all; + input [PVDSTPw-1 : 0] dest_port_coded_all; + input [PV-1 : 0] ivc_request_all; + input [PV-1 : 0] ovc_is_assigned_all; + output [PVV-1 : 0] masked_ovc_request_all; + input [PVV-1 : 0] candidate_ovc_all; + input [PPSw-1 : 0] port_pre_sel; + output [PV-1 : 0] swap_port_presel; + output [PV-1 : 0] sel; output [PVDSTPw-1 : 0] destport_clear_all; input [PV-1 : 0] ivc_num_getting_ovc_grant; input [PV-1 : 0] ssa_ivc_num_getting_ovc_grant_all; input reset,clk; - - wire [PV-1 : 0] non_assigned_ovc_request_all; - wire [PV-1 : 0] y_evc_forbiden,x_evc_forbiden; - wire [V-1 : 0] ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus,ovc_avb_local; - wire [VP_1-1 : 0] ovc_avalable_perport [P-1 : 0]; - wire [PPSw-1 : 0] port_pre_sel_perport [P-1 : 0]; - wire [PVV-1 : 0] candidate_ovc_x_all, candidate_ovc_y_all; - - - assign non_assigned_ovc_request_all = ivc_request_all & ~ovc_is_assigned_all; - assign {ovc_avb_y_minus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_x_plus,ovc_avb_local} = ovc_avalable_all; - - - - assign ovc_avalable_perport[LOCAL] = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus}; - assign ovc_avalable_perport[EAST] = {ovc_avb_local,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus}; - assign ovc_avalable_perport[NORTH] = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_local,ovc_avb_y_minus}; - assign ovc_avalable_perport[WEST] = {ovc_avb_x_plus,ovc_avb_local,ovc_avb_y_plus,ovc_avb_y_minus}; - assign ovc_avalable_perport[SOUTH] = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_local}; - + wire [PV-1 : 0] non_assigned_ovc_request_all; + wire [PV-1 : 0] y_evc_forbiden,x_evc_forbiden; + wire [V-1 : 0] ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus,ovc_avb_local; + wire [VP_1-1 : 0] ovc_avalable_perport [P-1 : 0]; + wire [PPSw-1 : 0] port_pre_sel_perport [P-1 : 0]; + wire [PVV-1 : 0] candidate_ovc_x_all, candidate_ovc_y_all; - assign port_pre_sel_perport[LOCAL] = port_pre_sel; - assign port_pre_sel_perport[EAST] = {2'b00,port_pre_sel[1:0]}; - assign port_pre_sel_perport[NORTH] = {1'b0,port_pre_sel[2],1'b0,port_pre_sel[0]}; - assign port_pre_sel_perport[WEST] = {port_pre_sel[3:2],2'b0}; - assign port_pre_sel_perport[SOUTH] = {port_pre_sel[3],1'b0,port_pre_sel[1],1'b0}; - - wire [PV-1 : 0] avc_unavailable; + assign non_assigned_ovc_request_all = ivc_request_all & ~ovc_is_assigned_all; + assign {ovc_avb_y_minus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_x_plus,ovc_avb_local} = ovc_avalable_all; + assign ovc_avalable_perport[LOCAL] = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus}; + assign ovc_avalable_perport[EAST] = {ovc_avb_local,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus}; + assign ovc_avalable_perport[NORTH] = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_local,ovc_avb_y_minus}; + assign ovc_avalable_perport[WEST] = {ovc_avb_x_plus,ovc_avb_local,ovc_avb_y_plus,ovc_avb_y_minus}; + assign ovc_avalable_perport[SOUTH] = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_local}; + assign port_pre_sel_perport[LOCAL] = port_pre_sel; + assign port_pre_sel_perport[EAST] = {2'b00,port_pre_sel[1:0]}; + assign port_pre_sel_perport[NORTH] = {1'b0,port_pre_sel[2],1'b0,port_pre_sel[0]}; + assign port_pre_sel_perport[WEST] = {port_pre_sel[3:2],2'b0}; + assign port_pre_sel_perport[SOUTH] = {port_pre_sel[3],1'b0,port_pre_sel[1],1'b0}; + + wire [PV-1 : 0] avc_unavailable; genvar i; generate - - - for(i=0;i< PV;i=i+1) begin :all_vc_loop + for(i=0;i< PV;i=i+1) begin : PV_ + mesh_torus_adaptive_avb_ovc_mux #( + .V(V) + ) ovc_mux ( + .ovc_avalable (ovc_avalable_perport [i/V]), + .sel (sel [i]), + .candidate_ovc_x (candidate_ovc_x_all [((i+1)*V)-1 : i*V]), + .candidate_ovc_y (candidate_ovc_y_all [((i+1)*V)-1 : i*V]), + .non_assigned_ovc_request (non_assigned_ovc_request_all[i]), + .xydir (dest_port_coded_all [((i+1)*DSTPw)-1 : ((i+1)*DSTPw)-2]), + .masked_ovc_request (masked_ovc_request_all [((i+1)*V)-1 : i*V]) + ); - mesh_torus_adaptive_avb_ovc_mux #( - .V(V) - ) - the_adaptive_avb_ovc_mux - ( - .ovc_avalable (ovc_avalable_perport [i/V]), - .sel (sel [i]), - .candidate_ovc_x (candidate_ovc_x_all [((i+1)*V)-1 : i*V]), - .candidate_ovc_y (candidate_ovc_y_all [((i+1)*V)-1 : i*V]), - .non_assigned_ovc_request (non_assigned_ovc_request_all[i]), - .xydir (dest_port_coded_all [((i+1)*DSTPw)-1 : ((i+1)*DSTPw)-2]), - .masked_ovc_request (masked_ovc_request_all [((i+1)*V)-1 : i*V]) - ); - mesh_torus_port_selector #( - .SW_LOC (i/V), - .PPSw(PPSw) - ) - the_portsel - ( - .port_pre_sel (port_pre_sel_perport[i/V]), - .swap_port_presel (swap_port_presel[i]), - .sel (sel[i]), - .dest_port_in (dest_port_coded_all[((i+1)*DSTPw)-1 : i*DSTPw]), - .y_evc_forbiden (y_evc_forbiden[i]), - .x_evc_forbiden (x_evc_forbiden[i]) - ); - + .SW_LOC (i/V), + .PPSw(PPSw) + ) the_portsel ( + .port_pre_sel (port_pre_sel_perport[i/V]), + .swap_port_presel (swap_port_presel[i]), + .sel (sel[i]), + .dest_port_in (dest_port_coded_all[((i+1)*DSTPw)-1 : i*DSTPw]), + .y_evc_forbiden (y_evc_forbiden[i]), + .x_evc_forbiden (x_evc_forbiden[i]) + ); + mesh_tori_dspt_clear_gen #( .SSA_EN(SSA_EN), .DSTPw(DSTPw), .SW_LOC(i/V) - ) - dspt_clear_gen - ( + ) dspt_clear_gen ( .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]), .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant[i]), .sel(sel[i]), .ssa_ivc_num_getting_ovc_grant(ssa_ivc_num_getting_ovc_grant_all[i]) ); - /* verilator lint_off WIDTH */ - if(ROUTE_TYPE == "FULL_ADAPTIVE") begin: full_adpt + if(ROUTE_TYPE == "FULL_ADAPTIVE") begin: full_adpt /* verilator lint_on WIDTH */ - assign candidate_ovc_y_all[((i+1)*V)-1 : i*V] = (y_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) : candidate_ovc_all[((i+1)*V)-1 : i*V]; - assign candidate_ovc_x_all[((i+1)*V)-1 : i*V] = (x_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) : candidate_ovc_all[((i+1)*V)-1 : i*V]; + assign candidate_ovc_y_all[((i+1)*V)-1 : i*V] = (y_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) : candidate_ovc_all[((i+1)*V)-1 : i*V]; + assign candidate_ovc_x_all[((i+1)*V)-1 : i*V] = (x_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) : candidate_ovc_all[((i+1)*V)-1 : i*V]; assign avc_unavailable[i] = (masked_ovc_request_all [((i+1)*V)-1 : i*V] & ~ESCAP_VC_MASK) == {V{1'b0}}; - mesh_torus_swap_port_presel_gen #( .V(V), .ESCAP_VC_MASK(ESCAP_VC_MASK), .VC_NUM(i) - ) - the_swap_port_presel - ( + ) swap_presel ( .avc_unavailable(avc_unavailable[i]), .y_evc_forbiden(y_evc_forbiden[i]), .x_evc_forbiden(x_evc_forbiden[i]), @@ -195,88 +167,79 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( .reset(reset), .swap_port_presel(swap_port_presel[i]) ); - - end else begin : partial_adpt - assign candidate_ovc_y_all[((i+1)*V)-1 : i*V] = candidate_ovc_all [((i+1)*V)-1 : i*V]; - assign candidate_ovc_x_all[((i+1)*V)-1 : i*V] = candidate_ovc_all [((i+1)*V)-1 : i*V]; + assign candidate_ovc_y_all[((i+1)*V)-1 : i*V] = candidate_ovc_all [((i+1)*V)-1 : i*V]; + assign candidate_ovc_x_all[((i+1)*V)-1 : i*V] = candidate_ovc_all [((i+1)*V)-1 : i*V]; assign swap_port_presel[i]=1'b0; assign avc_unavailable[i]=1'b0; - end// ROUTE_TYPE end//for - endgenerate endmodule - module mesh_tori_dspt_clear_gen #( parameter SSA_EN="YES", parameter DSTPw =4, parameter SW_LOC=0 - )( destport_clear, ivc_num_getting_ovc_grant, sel, ssa_ivc_num_getting_ovc_grant - ); - + output [DSTPw-1 : 0] destport_clear; input ivc_num_getting_ovc_grant; input sel; input ssa_ivc_num_getting_ovc_grant; - - localparam - LOCAL = 3'd0, - EAST = 3'd1, - WEST = 3'd3; - -generate + + localparam + LOCAL = 3'd0, + EAST = 3'd1, + WEST = 3'd3; + generate /* verilator lint_off WIDTH */ if ( SSA_EN=="YES" ) begin :predict_if /* verilator lint_on WIDTH */ if (SW_LOC == LOCAL ) begin :local_if assign destport_clear= (ivc_num_getting_ovc_grant)?{2'b00,sel,~sel} :{DSTPw{1'b0}}; end else if (SW_LOC == EAST || SW_LOC == WEST ) begin :xdir_if - assign destport_clear = (ivc_num_getting_ovc_grant)? {2'b00,sel,~sel} : - (ssa_ivc_num_getting_ovc_grant)? 4'b0001: //clear b - 4'b0000; + assign destport_clear = (ivc_num_getting_ovc_grant)? + {2'b00,sel,~sel} : + (ssa_ivc_num_getting_ovc_grant)? 4'b0001: //clear b + 4'b0000; end else begin : ydir_if - assign destport_clear = (ivc_num_getting_ovc_grant)? {2'b00,sel,~sel} : - (ssa_ivc_num_getting_ovc_grant)? 4'b0010: //clear a - 4'b0000; + assign destport_clear = (ivc_num_getting_ovc_grant)? + {2'b00,sel,~sel} : + (ssa_ivc_num_getting_ovc_grant)? 4'b0010: //clear a + 4'b0000; end end else begin :nopredict_if - assign destport_clear = (ivc_num_getting_ovc_grant )? {2'b00,sel,~sel} :{DSTPw{1'b0}}; + assign destport_clear = (ivc_num_getting_ovc_grant )? {2'b00,sel,~sel} :{DSTPw{1'b0}}; end// nopredict_if -endgenerate + endgenerate endmodule - module mesh_torus_mask_non_assignable_destport #( parameter TOPOLOGY="MESH", parameter ROUTE_NAME="XY", parameter SW_LOC=0, parameter P=5, parameter SELF_LOOP_EN="NO" -) -( - odd_column,// use only for odd even routing - dest_port_in, - dest_port_out +) ( + odd_column,// use only for odd even routing + dest_port_in, + dest_port_out ); - + localparam P_1 = (SELF_LOOP_EN=="NO") ? P-1 : P; input [P_1-1 : 0 ] dest_port_in; output [P_1-1 : 0 ] dest_port_out; input odd_column; - - wire [P-2 : 0] dest_port_in_tmp,dest_port_out_tmp; + wire [P-2 : 0] dest_port_in_tmp,dest_port_out_tmp; generate if(SELF_LOOP_EN == "NO") begin :nslp assign dest_port_in_tmp = dest_port_in; @@ -285,9 +248,7 @@ module mesh_torus_mask_non_assignable_destport #( remove_sw_loc_one_hot #( .P(P), .SW_LOC(SW_LOC) - ) - remove_sw_loc - ( + ) remove_sw_loc ( .destport_in(dest_port_in), .destport_out(dest_port_in_tmp) ); @@ -298,102 +259,83 @@ module mesh_torus_mask_non_assignable_destport #( add_sw_loc_one_hot_val #( .P(P), .SW_LOC(SW_LOC) - )add_sw_loc - ( + )add_sw_loc ( .sw_loc_val(sw_loc_val), .destport_in (dest_port_out_tmp), .destport_out(dest_port_out) ); - - - - end endgenerate - + mesh_torus_mask_non_assignable_destport_no_self_loop # ( .TOPOLOGY(TOPOLOGY), .ROUTE_NAME(ROUTE_NAME), .SW_LOC(SW_LOC), .P(P) - ) - mask_no_self_loop - ( + ) mask_no_self_loop ( .dest_port_in(dest_port_in_tmp), .dest_port_out(dest_port_out_tmp), .odd_column(odd_column) ); - - endmodule -module mesh_torus_mask_non_assignable_destport_no_self_loop #( +module mesh_torus_mask_non_assignable_destport_no_self_loop #( parameter TOPOLOGY="MESH", parameter ROUTE_NAME="XY", parameter SW_LOC=0, parameter P=5 -) -( - odd_column,// use only for odd even routing - dest_port_in, - dest_port_out +)( + odd_column,// use only for odd even routing + dest_port_in, + dest_port_out ); - -localparam - EAST = 1, - NORTH = 2, - WEST = 3, - SOUTH = 4; - -//port number in north port -localparam - N_LOCAL = 0, - N_EAST = 1, - N_WEST = 2, - N_SOUTH = 3; - - // port number in south port - localparam - S_LOCAL = 0, - S_EAST = 1, - S_NORTH = 2, - S_WEST = 3; - - // port number in east port - localparam - E_LOCAL = 0, - E_NORTH = 1, - E_WEST = 2, - E_SOUTH = 3; - // port number in east port - localparam - W_LOCAL = 0, - W_EAST = 1, - W_NORTH = 2, - W_SOUTH = 3; - - - localparam P_1 = P-1; - input [P_1-1 : 0 ] dest_port_in; + localparam + EAST = 1, + NORTH = 2, + WEST = 3, + SOUTH = 4; + //port number in north port + localparam + N_LOCAL = 0, + N_EAST = 1, + N_WEST = 2, + N_SOUTH = 3; + // port number in south port + localparam + S_LOCAL = 0, + S_EAST = 1, + S_NORTH = 2, + S_WEST = 3; + // port number in east port + localparam + E_LOCAL = 0, + E_NORTH = 1, + E_WEST = 2, + E_SOUTH = 3; + // port number in east port + localparam + W_LOCAL = 0, + W_EAST = 1, + W_NORTH = 2, + W_SOUTH = 3; + localparam + P_1 = P-1; + input [P_1-1 : 0 ] dest_port_in; output [P_1-1 : 0 ] dest_port_out; input odd_column; - generate if(P>5)begin :p5 - assign dest_port_out[P_1-1:4] = dest_port_in[P_1-1:4]; //other local ports - end - - + assign dest_port_out[P_1-1:4] = dest_port_in[P_1-1:4]; //other local ports + end /* verilator lint_off WIDTH */ if (TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin : oneD // A port can send packets to all other ports in these topologies /* verilator lint_on WIDTH */ assign dest_port_out = dest_port_in; end else begin : towD - /*XY*/ /* verilator lint_off WIDTH */ - if ( ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY") begin :xy + if ( ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY") begin :xy /* verilator lint_on WIDTH */ if (SW_LOC == NORTH ) begin : nort_p // The port located in y axsis does not send packets to x dimension assign dest_port_out[N_LOCAL]= dest_port_in[N_LOCAL]; @@ -406,13 +348,12 @@ localparam assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH]; assign dest_port_out[S_WEST]= 1'b0; // mask west port end else begin : non_vertical - assign dest_port_out[3:0] = dest_port_in[3:0]; + assign dest_port_out[3:0] = dest_port_in[3:0]; end - /*WEST-FIRST*/ /* verilator lint_off WIDTH */ - end else if ( ROUTE_NAME == "WEST_FIRST" || ROUTE_NAME == "TRANC_WEST_FIRST") begin :west_first + end else if ( ROUTE_NAME == "WEST_FIRST" || ROUTE_NAME == "TRANC_WEST_FIRST") begin :west_first /* verilator lint_on WIDTH */ - // SW & NW are forbidden + // SW & NW are forbidden if (SW_LOC == NORTH ) begin : nort_p // north port does not send packets to the west port. assign dest_port_out[N_LOCAL]= dest_port_in[N_LOCAL]; assign dest_port_out[N_EAST]= dest_port_in[N_EAST]; @@ -424,11 +365,10 @@ localparam assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH]; assign dest_port_out[S_WEST]= 1'b0; // mask west port end else begin : non_vertical - assign dest_port_out[3:0] = dest_port_in[3:0]; + assign dest_port_out[3:0] = dest_port_in[3:0]; end - /*NORTH_LAST*/ /* verilator lint_off WIDTH */ - end else if ( ROUTE_NAME == "NORTH_LAST" || ROUTE_NAME == "TRANC_NORTH_LAST") begin :north_last + end else if ( ROUTE_NAME == "NORTH_LAST" || ROUTE_NAME == "TRANC_NORTH_LAST") begin :north_last /* verilator lint_on WIDTH */ //NE & NW are forbidden if (SW_LOC == SOUTH ) begin : south_p // north port does not send packets to the east nor to the west port. @@ -437,13 +377,12 @@ localparam assign dest_port_out[S_WEST]= 1'b0; // mask west port assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH]; end else begin : other_p - assign dest_port_out[3:0] = dest_port_in[3:0]; + assign dest_port_out[3:0] = dest_port_in[3:0]; end - /*NEGETIVE_FIRST*/ /* verilator lint_off WIDTH */ - end else if ( ROUTE_NAME == "NEGETIVE_FIRST" || ROUTE_NAME == "TRANC_NEGETIVE_FIRST") begin :negetive_first + end else if ( ROUTE_NAME == "NEGETIVE_FIRST" || ROUTE_NAME == "TRANC_NEGETIVE_FIRST") begin :negetive_first /* verilator lint_on WIDTH */ - //ES & NW is forbiden + //ES & NW is forbiden if (SW_LOC == SOUTH ) begin : south_p // south port does not send packets to the west port. NW is forbiden assign dest_port_out[S_LOCAL]= dest_port_in[S_LOCAL]; assign dest_port_out[S_EAST]= dest_port_in[S_EAST]; @@ -455,15 +394,13 @@ localparam assign dest_port_out[W_EAST] = dest_port_in[W_EAST]; assign dest_port_out[W_SOUTH]= 1'b0; //mask south port end else begin : other_p - assign dest_port_out[3:0] = dest_port_in[3:0]; + assign dest_port_out[3:0] = dest_port_in[3:0]; end - /*ODD_EVEN*/ /* verilator lint_off WIDTH */ end else if ( ROUTE_NAME == "ODD_EVEN" ) begin : odd_even /* verilator lint_on WIDTH */ //Odd column : NW and SW turns are not allowed //Even column: EN and ES turns are not allowed - if (SW_LOC == NORTH ) begin : nort_p // north port does not send packets to the west port in odd columns. SW is forbiden assign dest_port_out[N_LOCAL]= dest_port_in[N_LOCAL]; assign dest_port_out[N_EAST]= dest_port_in[N_EAST]; @@ -474,8 +411,6 @@ localparam assign dest_port_out[S_EAST]= dest_port_in[S_EAST]; assign dest_port_out[S_NORTH]= dest_port_in[S_NORTH]; assign dest_port_out[S_WEST]= (odd_column)? 1'b0: dest_port_in[S_WEST]; // mask west port in odd columns - - end else if (SW_LOC == WEST) begin : west_p // WEST port does not sends packet to north and south ports in even columns //ES & EN forbiden assign dest_port_out[W_LOCAL]= dest_port_in[W_LOCAL]; @@ -485,8 +420,7 @@ localparam end else begin: other_p assign dest_port_out[3:0] = dest_port_in[3:0]; end - - end else begin : f_adptv + end else begin : f_adptv assign dest_port_out[3:0] = dest_port_in[3:0]; end end @@ -494,19 +428,10 @@ localparam endmodule - - -/********************** - - swap_port_presel_gen - -**********************/ - -module mesh_torus_swap_port_presel_gen #( +module mesh_torus_swap_port_presel_gen #( parameter V = 4, - parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000, // mask scape vc, valid only for full adaptive + parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000, // mask scape vc, valid only for full adaptive parameter VC_NUM=0 - )( avc_unavailable, swap_port_presel, @@ -516,73 +441,42 @@ module mesh_torus_swap_port_presel_gen #( sel, clk, reset - ); - - localparam LOCAL_VC_NUM= VC_NUM % V; - - - input avc_unavailable; - input y_evc_forbiden,x_evc_forbiden; - input non_assigned_ovc_request,sel; - input clk,reset; - output swap_port_presel; - wire swap_reg; + localparam LOCAL_VC_NUM= VC_NUM % V; + input avc_unavailable; + input y_evc_forbiden,x_evc_forbiden; + input non_assigned_ovc_request,sel; + input clk,reset; + output swap_port_presel; + wire swap_reg; wire swap_port_presel_next; - - wire evc_forbiden; - - /************************ - - destination-port_in - x: 1 EAST, 0 WEST - y: 1 NORTH, 0 SOUTH - ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir - sel: - 0: xdir - 1: ydir - port_pre_sel - 0: xdir - 1: ydir - -************************/ - - + * + * destination-port_in + * x: 1 EAST, 0 WEST + * y: 1 NORTH, 0 SOUTH + * ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir + * sel: + * 0: xdir + * 1: ydir + * port_pre_sel + * 0: xdir + * 1: ydir + ************************/ //For an EVC sender, if the use of EVC in destination port is restricted while the destination port has no available AVC, //the port pre selection must swap - - - // generate - // check if it is an evc sender - // if(ESCAP_VC_MASK[LOCAL_VC_NUM]== 1'b0)begin - //its not EVC - // assign swap_port_presel=1'b0; - - // end else begin // the sender is an EVC - - assign evc_forbiden = (sel)? y_evc_forbiden : x_evc_forbiden; - assign swap_port_presel_next= non_assigned_ovc_request & evc_forbiden & avc_unavailable; - assign swap_port_presel = swap_reg; - - pronoc_register #(.W(1)) reg2 (.in(swap_port_presel_next ), .out(swap_reg), .reset(reset), .clk(clk)); - - endmodule - - - - -/************************ - - adaptive_avb_ovc_mux + assign evc_forbiden = (sel)? y_evc_forbiden : x_evc_forbiden; + assign swap_port_presel_next= non_assigned_ovc_request & evc_forbiden & avc_unavailable; + assign swap_port_presel = swap_reg; + pronoc_register #(.W(1)) reg2 (.in(swap_port_presel_next ), .out(swap_reg), .reset(reset), .clk(clk)); +endmodule -************************/ module mesh_torus_adaptive_avb_ovc_mux #( - parameter V= 4 + parameter V= 4 )( ovc_avalable, sel, @@ -591,67 +485,48 @@ module mesh_torus_adaptive_avb_ovc_mux #( non_assigned_ovc_request, xydir, masked_ovc_request - - ); - localparam P = 5; - localparam P_1 = P-1, - VP_1 = V * P_1; - - input [VP_1-1 : 0] ovc_avalable; - input sel; - input [V-1 : 0] candidate_ovc_x; - input [V-1 : 0] candidate_ovc_y; - input non_assigned_ovc_request; - input [1 : 0] xydir; - output [V-1 : 0] masked_ovc_request; + localparam + P = 5, + P_1 = P-1, + VP_1 = V * P_1; + + input [VP_1-1 : 0] ovc_avalable; + input sel; + input [V-1 : 0] candidate_ovc_x; + input [V-1 : 0] candidate_ovc_y; + input non_assigned_ovc_request; + input [1 : 0] xydir; + output [V-1 : 0] masked_ovc_request; wire x,y; - wire [V-1 : 0] ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus; - wire [V-1 : 0] mux_out_x,mux_out_y; - wire [V-1 : 0] ovc_request_x,ovc_request_y,masked_ovc_request_x,masked_ovc_request_y; + wire [V-1 : 0] ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus; + wire [V-1 : 0] mux_out_x,mux_out_y; + wire [V-1 : 0] ovc_request_x,ovc_request_y,masked_ovc_request_x,masked_ovc_request_y; assign {x,y}= xydir; assign {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus}=ovc_avalable; //first level mux - //assign mux_out_x = (x)? ovc_avb_x_plus : ovc_avb_x_minus; - //assign mux_out_y = (y)? ovc_avb_y_plus : ovc_avb_y_minus; + //assign mux_out_x = (x)? ovc_avb_x_plus : ovc_avb_x_minus; + //assign mux_out_y = (y)? ovc_avb_y_plus : ovc_avb_y_minus; assign mux_out_x = (ovc_avb_x_plus &{V{x}}) | (ovc_avb_x_minus &{V{~x}}); assign mux_out_y = (ovc_avb_y_plus &{V{y}}) | (ovc_avb_y_minus &{V{~y}}); - - //assign ovc_request_x = (non_assigned_ovc_request)? candidate_ovc_x : {V{1'b0}}; //assign ovc_request_y = (non_assigned_ovc_request)? candidate_ovc_y : {V{1'b0}}; - assign ovc_request_x = candidate_ovc_x & {V{non_assigned_ovc_request}}; - assign ovc_request_y = candidate_ovc_y & {V{non_assigned_ovc_request}}; - + assign ovc_request_x = candidate_ovc_x & {V{non_assigned_ovc_request}}; + assign ovc_request_y = candidate_ovc_y & {V{non_assigned_ovc_request}}; //mask unavailble ovc assign masked_ovc_request_x = mux_out_x & ovc_request_x; assign masked_ovc_request_y = mux_out_y & ovc_request_y; - //second mux - // assign masked_ovc_request = (sel)? masked_ovc_request_y: masked_ovc_request_x; - assign masked_ovc_request = (masked_ovc_request_y & {V{sel}})| (masked_ovc_request_x & {V{~sel}}); - - + // assign masked_ovc_request = (sel)? masked_ovc_request_y: masked_ovc_request_x; + assign masked_ovc_request = (masked_ovc_request_y & {V{sel}})| (masked_ovc_request_x & {V{~sel}}); endmodule - - - -/***************************************************** - - port_selector - - -*****************************************************/ - - module mesh_torus_port_selector #( - parameter SW_LOC = 0, + parameter SW_LOC = 0, parameter PPSw=4 -) -( +)( port_pre_sel, dest_port_in, swap_port_presel, @@ -660,84 +535,67 @@ module mesh_torus_port_selector #( x_evc_forbiden ); -/************************ - - destination-port_in - x: 1 EAST, 0 WEST - y: 1 NORTH, 0 SOUTH - ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir - sel: - 0: xdir - 1: ydir - port_pre_sel - 0: xdir - 1: ydir - -************************/ - - + /************************ + * + * destination-port_in + * x: 1 EAST, 0 WEST + * y: 1 NORTH, 0 SOUTH + * ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir + * sel: + * 0: xdir + * 1: ydir + * port_pre_sel + * 0: xdir + * 1: ydir + ************************/ //input reset,clk; input [PPSw-1:0] port_pre_sel; - // input port_pre_sel_ld; + // input port_pre_sel_ld; output sel; input [3:0] dest_port_in; input swap_port_presel; - // output route_subfunc_violated; + // output route_subfunc_violated; output y_evc_forbiden, x_evc_forbiden; wire x,y,a,b; wire [PPSw-1:0] port_pre_sel_final; //reg [3:0] port_pre_sel_delayed , port_pre_sel_latched; - // wire o1,o2; - - - localparam LOCAL = 0, - EAST = 1, - NORTH = 2, - WEST = 3, - SOUTH = 4; - - localparam LOCAL_SEL = (SW_LOC == NORTH || SW_LOC == SOUTH )? 1'b1 : 1'b0; + // wire o1,o2; + localparam + LOCAL = 0, + EAST = 1, + NORTH = 2, + WEST = 3, + SOUTH = 4; + localparam + LOCAL_SEL = (SW_LOC == NORTH || SW_LOC == SOUTH )? 1'b1 : 1'b0; assign port_pre_sel_final= (swap_port_presel)? ~port_pre_sel: port_pre_sel; assign {x,y,a,b} = dest_port_in; - - - wire sel_in,sel_pre, overwrite; - wire [1:0] xy; - - assign xy={x,y}; - assign sel_pre= port_pre_sel_final[xy]; - - assign overwrite= a&b; - generate - if(LOCAL_SEL)begin :local_p - assign sel_in= b | ~a; - end else begin :nonlocal_p - assign sel_in= b ; - end - endgenerate - + wire sel_in,sel_pre, overwrite; + wire [1:0] xy; + assign xy={x,y}; + assign sel_pre= port_pre_sel_final[xy]; + assign overwrite= a&b; + generate + if(LOCAL_SEL)begin :local_p + assign sel_in= b | ~a; + end else begin :nonlocal_p + assign sel_in= b ; + end + endgenerate assign sel= (overwrite)? sel_pre : sel_in; - -// check if EVC is allowed to be used - - // Using of all EVCs located in y dimension are restricted when the packet can be sent into both x&y direction - assign y_evc_forbiden = a&b; - - //there is no restriction in using EVCs located in x dimension - assign x_evc_forbiden = 1'b0; - //assign route_subfunc_violated = a&b; - /* verilator lint_off WIDTH */ - endmodule - + // check if EVC is allowed to be used + // Using of all EVCs located in y dimension are restricted when the packet can be sent into both x&y direction + assign y_evc_forbiden = a&b; + //there is no restriction in using EVCs located in x dimension + assign x_evc_forbiden = 1'b0; + //assign route_subfunc_violated = a&b; +endmodule /******************* - mesh_torus_adaptive_lk_dest_encoder +* mesh_torus_adaptive_lk_dest_encoder ********************/ - - - module mesh_torus_adaptive_lk_dest_encoder #( parameter V=4, parameter P=5, @@ -745,7 +603,6 @@ module mesh_torus_adaptive_lk_dest_encoder #( parameter Fw=37, parameter DST_P_MSB=11, parameter DST_P_LSB=8 - )( sel, flit_in, @@ -759,30 +616,25 @@ module mesh_torus_adaptive_lk_dest_encoder #( input [V-1 : 0] vc_num_delayed; input [DSTPw-1 : 0] lk_dest; input [Fw-1 : 0] flit_in; - + wire [1 : 0] ab,xy; wire sel_muxed; - + onehot_mux_1D #( .W(1), .N(V) - ) - sel_mux - ( + ) sel_mux ( .in(sel), .out(sel_muxed), .sel(vc_num_delayed) ); - //lkdestport = {lkdestport_x[1:0],lkdestport_y[1:0]}; // sel: 0: xdir 1: ydir assign ab = (sel_muxed)? lk_dest[1:0] : lk_dest[3:2]; //if ab==00 change x and y direction - assign xy = (ab>0)? flit_in[DST_P_MSB : DST_P_LSB+2] : ~flit_in[DST_P_MSB : DST_P_LSB+2] ; - + assign xy = (ab>0)? flit_in[DST_P_MSB : DST_P_LSB+2] : ~flit_in[DST_P_MSB : DST_P_LSB+2] ; assign dest_coded_out={xy,ab}; - endmodule @@ -792,47 +644,33 @@ module mesh_torus_dtrmn_dest_encoder #( parameter Fw=37, parameter DST_P_MSB=11, parameter DST_P_LSB=8 - )( flit_in, dest_coded_out, lk_dest ); - - output [DSTPw-1 : 0]dest_coded_out; - input [DSTPw-1 : 0] lk_dest; input [Fw-1 : 0] flit_in; - wire [1 : 0] ab,xy; - - //lkdestport = {lkdestport_x[1:0],lkdestport_y[1:0]}; // sel: 0: xdir 1: ydir - assign ab = lk_dest[1:0]; + assign ab = lk_dest[1:0]; //if ab==00 change x and y direction - assign xy = (ab>0)? flit_in[DST_P_MSB : DST_P_LSB+2] : ~flit_in[DST_P_MSB : DST_P_LSB+2] ; - + assign xy = (ab>0)? flit_in[DST_P_MSB : DST_P_LSB+2] : ~flit_in[DST_P_MSB : DST_P_LSB+2] ; assign dest_coded_out={xy,ab}; - endmodule - /******************** - - distance_gen - +* distance_gen ********************/ - module mesh_torus_distance_gen #( parameter T1= 4, // number of node in x axis parameter T2= 4, // number of node in y axis parameter T3= 4, parameter EAw=4, parameter DISTw=4, - parameter TOPOLOGY = "MESH" - + parameter TOPOLOGY = "MESH" )( src_e_addr, dest_e_addr, @@ -840,38 +678,31 @@ module mesh_torus_distance_gen #( ); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 dest_x)? src_x - dest_x : dest_x - src_x; - y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; - end - - - + x_offset = (src_x> dest_x)? src_x - dest_x : dest_x - src_x; + y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; + end end else begin : twoD //torus ring - wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y; - /* verilator lint_off WIDTH */ always @ (*) begin x_offset= {Xw{1'b0}}; y_offset= {Yw{1'b0}}; - //x_offset if(same_x) x_offset= {Xw{1'b0}}; else if(tranc_x_plus) begin @@ -928,10 +749,8 @@ module mesh_torus_distance_gen #( else if(tranc_x_min) begin if(dest_x < src_x) x_offset= src_x-dest_x; else x_offset= src_x+(NX-dest_x); - end - - //y_offset + //y_offset if(same_y) y_offset= {Yw{1'b0}}; else if(tranc_y_plus) begin if(dest_y > src_y) y_offset= dest_y-src_y; @@ -940,20 +759,14 @@ module mesh_torus_distance_gen #( else if(tranc_y_min) begin if(dest_y < src_y) y_offset= src_y-dest_y; else y_offset= src_y+(NY-dest_y); - end - - end /* verilator lint_on WIDTH */ - - + tranc_dir #( .NX(NX), .NY(NY) - ) - tranc_dir - ( + ) tranc_dir ( .tranc_x_plus(tranc_x_plus), .tranc_x_min(tranc_x_min), .tranc_y_plus(tranc_y_plus), @@ -965,16 +778,14 @@ module mesh_torus_distance_gen #( .dest_x(dest_x), .dest_y(dest_y) ); - - end endgenerate /* verilator lint_off WIDTH */ - assign distance = x_offset+y_offset+1'b1; + assign distance = x_offset+y_offset+1'b1; /* verilator lint_on WIDTH */ endmodule - - + + module mesh_torus_ssa_check_destport #( parameter ROUTE_TYPE="DETERMINISTIC", parameter SW_LOC = 0, @@ -992,7 +803,6 @@ module mesh_torus_ssa_check_destport #( ivc_num_getting_sw_grant, hdr_flg `endif - ); input [DSTPw-1 : 0] destport_encoded, destport_in_encoded; @@ -1000,43 +810,40 @@ module mesh_torus_ssa_check_destport #( `ifdef SIMULATION input clk, ivc_num_getting_sw_grant,hdr_flg; `endif - -//MESH, TORUS Topology p=5 - localparam LOCAL = 0, - EAST = 1, - WEST = 3; - - -/************************ - destination port is coded - destination-port_in - x: 1 EAST, 0 WEST - y: 1 NORTH, 0 SOUTH - ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir - sel: - 0: xdir - 1: ydir - port_pre_sel - 0: xdir - 1: ydir - + //MESH, TORUS Topology p=5 + localparam + LOCAL = 0, + EAST = 1, + WEST = 3; + +/************************* +* destination port is coded +* destination-port_in +* x: 1 EAST, 0 WEST +* y: 1 NORTH, 0 SOUTH +* ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir +* sel: +* 0: xdir +* 1: ydir +* port_pre_sel +* 0: xdir +* 1: ydir +* ************************/ -wire a,b,aa,bb; -assign {a,b} = destport_in_encoded[1:0]; -assign {aa,bb} = destport_encoded[1:0]; - -generate + wire a,b,aa,bb; + assign {a,b} = destport_in_encoded[1:0]; + assign {aa,bb} = destport_encoded[1:0]; + generate if( SS_PORT == LOCAL) begin :local_p - assign ss_port_hdr_flit = 1'b0; - assign ss_port_nonhdr_flit = 1'b0; + assign ss_port_hdr_flit = 1'b0; + assign ss_port_nonhdr_flit = 1'b0; end else if ((SS_PORT == EAST) || SS_PORT == WEST )begin :xdir - assign ss_port_hdr_flit = a; - assign ss_port_nonhdr_flit = aa; + assign ss_port_hdr_flit = a; + assign ss_port_nonhdr_flit = aa; end else begin :ydir assign ss_port_hdr_flit = b; - assign ss_port_nonhdr_flit = bb; + assign ss_port_nonhdr_flit = bb; end - `ifdef SIMULATION if(DEBUG_EN) begin :dbg always @(posedge clk) begin @@ -1066,86 +873,25 @@ module line_ring_ssa_check_destport #( ss_port_hdr_flit, ss_port_nonhdr_flit ); - input [DSTPw-1 : 0] destport_encoded, destport_in_encoded; output ss_port_hdr_flit, ss_port_nonhdr_flit; - - - -wire [P-1 : 0] dest_port_num,assigned_dest_port_num; + wire [P-1 : 0] dest_port_num,assigned_dest_port_num; - - - line_ring_decode_dstport cnv1( - .dstport_one_hot(dest_port_num), - .dstport_encoded(destport_in_encoded) - ); - - line_ring_decode_dstport cnv2( - .dstport_one_hot(assigned_dest_port_num), - .dstport_encoded(destport_encoded) - ); - - assign ss_port_hdr_flit = dest_port_num [SS_PORT]; - - assign ss_port_nonhdr_flit = assigned_dest_port_num[SS_PORT]; - -endmodule - - -/* -module mesh_torus_add_ss_port #( - parameter SW_LOC=1, - parameter P=5, - parameter SELF_LOOP_EN="NO" -)( - destport_in, - destport_out -); - localparam - P_1 = (SELF_LOOP_EN == "NO") ? P-1 : P, - LOCAL = 0, - EAST = 1, - NORTH = 2, - WEST = 3, - SOUTH = 4; - - - localparam NO_SELF_LOOP = (SELF_LOOP_EN == "NO") ? 1 : 0; - localparam SS_PORT_P5 = (SW_LOC== EAST )? WEST- NO_SELF_LOOP : // the sender port must be removed from destination port code - (SW_LOC== NORTH )? SOUTH- NO_SELF_LOOP: // the sender port must be removed from destination port code - (SW_LOC== WEST )? EAST : - NORTH ; - - localparam SS_PORT_P3 = (SELF_LOOP_EN == "NO") ? 1 : - - - localparam SS_PORT = (P==5) ? SS_PORT_P5: SS_PORT_P3; - - + line_ring_decode_dstport cnv1( + .dstport_one_hot(dest_port_num), + .dstport_encoded(destport_in_encoded) + ); + line_ring_decode_dstport cnv2( + .dstport_one_hot(assigned_dest_port_num), + .dstport_encoded(destport_encoded) + ); - - input [P_1-1 : 0] destport_in; - output reg [P_1-1 : 0] destport_out; - - - - always @(*)begin - destport_out=destport_in; - if( SW_LOC != LOCAL ) begin - if(destport_in=={P_1{1'b0}}) destport_out[SS_PORT]= 1'b1; - end - end - - + assign ss_port_hdr_flit = dest_port_num [SS_PORT]; + assign ss_port_nonhdr_flit = assigned_dest_port_num[SS_PORT]; endmodule -*/ -/************** - * - * ************/ - - module mesh_tori_router_addr_decode #( + +module mesh_tori_router_addr_decode #( parameter TOPOLOGY = "MESH", parameter T1=4, parameter T2=4, @@ -1157,28 +903,26 @@ endmodule ry, valid ); - + function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 i); - /* verilator lint_off UNSIGNED */ - assign x_minus[i] = (current_rx < i); - /* verilator lint_on UNSIGNED */ - end - - //get all endp addresses located in the same x - for(i=0; i< NE; i=i+1) begin : endpoints - //Endpoint decoded address - - localparam - Y_LOC = ((i/NL) / NX ), - X_LOC = ((i/NL) % NX ), - LL = (i % NL); - localparam [RYw-1 : 0] YY = Y_LOC [RYw-1 : 0]; - localparam [RXw-1 : 0] XX = X_LOC [RXw-1 : 0]; - - /* verilator lint_off CMPCONST */ - assign y_plus[i] = (current_rx == XX) && (current_ry > YY); - /* verilator lint_on CMPCONST */ - - /* verilator lint_off UNSIGNED */ - assign y_min[i] = (current_rx == XX) && (current_ry < YY); - /* verilator lint_on UNSIGNED */ - for(j=0;j SOUTH) begin - destport_tmp [NORTH] = goto_north; - destport_tmp [SOUTH] = goto_south; - destport_tmp [EAST] = goto_east; - destport_tmp [WEST] = goto_west; - end - end - - localparam MSB_DSTP = (DSTPw-1 < SOUTH)? DSTPw-1: SOUTH; - - assign destport [MSB_DSTP : 0] =destport_tmp; - for(i=1;i i); + /* verilator lint_off UNSIGNED */ + assign x_minus[i] = (current_rx < i); + /* verilator lint_on UNSIGNED */ + end + //get all endp addresses located in the same x + for(i=0; i< NE; i=i+1) begin : endpoints + //Endpoint decoded address + localparam + Y_LOC = ((i/NL) / NX ), + X_LOC = ((i/NL) % NX ), + LL = (i % NL); + localparam [RYw-1 : 0] YY = Y_LOC [RYw-1 : 0]; + localparam [RXw-1 : 0] XX = X_LOC [RXw-1 : 0]; + /* verilator lint_off CMPCONST */ + assign y_plus[i] = (current_rx == XX) && (current_ry > YY); + /* verilator lint_on CMPCONST */ + /* verilator lint_off UNSIGNED */ + assign y_min[i] = (current_rx == XX) && (current_ry < YY); + /* verilator lint_on UNSIGNED */ + for(j=0;j SOUTH) begin + destport_tmp [NORTH] = goto_north; + destport_tmp [SOUTH] = goto_south; + destport_tmp [EAST] = goto_east; + destport_tmp [WEST] = goto_west; + end + end + localparam MSB_DSTP = (DSTPw-1 < SOUTH)? DSTPw-1: SOUTH; + assign destport [MSB_DSTP : 0] =destport_tmp; + for(i=1;i i); - /* verilator lint_off UNSIGNED */ - assign x_minus[i] = (current_rx < i); - /* verilator lint_on UNSIGNED */ - end - - //get all endp addresses located in the same x - for(i=0; i< NE; i=i+1) begin : endpoints - //Endpoint decoded address - localparam - ADR = fmesh_addrencode(i), - XX = ADR [NXw -1 : 0], - YY = ADR [NXw+NYw-1 : NXw], - PP = ADR [NXw+NYw+Pw-1 : NXw+NYw]; - - /* verilator lint_off CMPCONST */ - assign y_plus[i] = (current_rx == XX) && (current_ry > YY); - /* verilator lint_on CMPCONST */ - - /* verilator lint_off UNSIGNED */ - assign y_min[i] = (current_rx == XX) && (current_ry < YY); - /* verilator lint_on UNSIGNED */ - - for(j=0;j SOUTH) begin - destport_tmp [NORTH] = goto_north; - destport_tmp [SOUTH] = goto_south; - destport_tmp [EAST] = goto_east; - destport_tmp [WEST] = goto_west; - end - end - - localparam MSB_DSTP = (DSTPw-1 < SOUTH)? DSTPw-1: SOUTH; - - assign destport [MSB_DSTP : 0] =destport_tmp; - for(i=1;i i); + /* verilator lint_off UNSIGNED */ + assign x_minus[i] = (current_rx < i); + /* verilator lint_on UNSIGNED */ + end + //get all endp addresses located in the same x + for(i=0; i< NE; i=i+1) begin : endpoints + //Endpoint decoded address + localparam + ADR = fmesh_addrencode(i), + XX = ADR [NXw -1 : 0], + YY = ADR [NXw+NYw-1 : NXw], + PP = ADR [NXw+NYw+Pw-1 : NXw+NYw]; + /* verilator lint_off CMPCONST */ + assign y_plus[i] = (current_rx == XX) && (current_ry > YY); + /* verilator lint_on CMPCONST */ + /* verilator lint_off UNSIGNED */ + assign y_min[i] = (current_rx == XX) && (current_ry < YY); + /* verilator lint_on UNSIGNED */ + for(j=0;j SOUTH) begin + destport_tmp [NORTH] = goto_north; + destport_tmp [SOUTH] = goto_south; + destport_tmp [EAST] = goto_east; + destport_tmp [WEST] = goto_west; + end + end + localparam MSB_DSTP = (DSTPw-1 < SOUTH)? DSTPw-1: SOUTH; + assign destport [MSB_DSTP : 0] =destport_tmp; + for(i=1;i SOUTH) begin :endp - - wire [NE/NX-1 : 0] endp_mask [NX-1 : 0]; - for(i=0; i< NE; i=i+1) begin : endpoints - //Endpoint decoded address - localparam - MCAST_ID = endp_id_to_mcast_id(i), - YY = ((i/NL) / NX ), - XX = ((i/NL) % NX ), - LL = (i % NL), - PP = YY*NL + LL; - assign endp_mask [XX] [PP] = dest_mcast_all_endp [i]; - end - - for(i=0;i SOUTH) begin - localparam MM = (PP==LOCAL) ? YY*NL : (YY*NL) + PP - SOUTH; - assign endp_mask [XX] [MM] = dest_mcast_all_endp [i]; - end - end - - wire [NX-1 : 0] north_endps; - wire [NY-1 : 0] west_endps; - wire [NX-1 : 0] south_endps; - wire [NY-1 : 0] east_endps; - - assign { east_endps, west_endps ,south_endps ,north_endps} = dest_mcast_all_endp [NE-1 : NY*NL*NX]; - - - for(i=0;i SOUTH) begin :endp + wire [NE/NX-1 : 0] endp_mask [NX-1 : 0]; + for(i=0; i< NE; i=i+1) begin : endpoints + //Endpoint decoded address + localparam + MCAST_ID = endp_id_to_mcast_id(i), + YY = ((i/NL) / NX ), + XX = ((i/NL) % NX ), + LL = (i % NL), + PP = YY*NL + LL; + assign endp_mask [XX] [PP] = dest_mcast_all_endp [i]; + end + for(i=0;i SOUTH) begin + localparam MM = (PP==LOCAL) ? YY*NL : (YY*NL) + PP - SOUTH; + assign endp_mask [XX] [MM] = dest_mcast_all_endp [i]; + end + end + wire [NX-1 : 0] north_endps; + wire [NY-1 : 0] west_endps; + wire [NX-1 : 0] south_endps; + wire [NY-1 : 0] east_endps; + assign { east_endps, west_endps ,south_endps ,north_endps} = dest_mcast_all_endp [NE-1 : NY*NL*NX]; + + for(i=0;i. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** Different routing algorithms (determinstic,partially adaptive and fully adaptive) -** for 2D mesh-based topology +** Description: +** Different routing algorithms (determinstic,partially adaptive and fully adaptive) +** for 2D mesh-based topology ** **************************************************************/ /******************************************** - Deterministic +* Deterministic *********************************************/ - - /***************************************************** - xy_mesh_routing - - *****************************************************/ - - - +/***************************************************** +* xy_mesh_routing +*****************************************************/ module xy_mesh_routing #( parameter NX = 4, parameter NY = 3 -) -( +)( current_x, // current router x address current_y, // current router y address dest_x, // destination x address dest_y, // destination y address dstport_encoded // router output port - ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 current_x) dstport_one_hot = EAST [P-1 :0]; - else if (dest_x < current_x) dstport_one_hot = WEST [P-1 :0]; - else begin - if (dest_y > current_y) dstport_one_hot = SOUTH [P-1 :0]; - else if (dest_y < current_y) dstport_one_hot = NORTH [P-1 :0]; - end + dstport_one_hot = LOCAL [P-1 :0]; + if (dest_x > current_x) dstport_one_hot = EAST [P-1 :0]; + else if (dest_x < current_x) dstport_one_hot = WEST [P-1 :0]; + else begin + if (dest_y > current_y) dstport_one_hot = SOUTH [P-1 :0]; + else if (dest_y < current_y) dstport_one_hot = NORTH [P-1 :0]; + end end mesh_tori_encode_dstport conv( - .dstport_one_hot(dstport_one_hot), - .dstport_encoded(dstport_encoded) + .dstport_one_hot(dstport_one_hot), + .dstport_encoded(dstport_encoded) ); - - endmodule /******************************************** - Partial adaptive -The west-first routing algorithm does not allow turns from north to west or from south to west. -The north last routing algorithm does not allow turns from north to east or from north to west. -The negetive fist routing algorithm does net allow turns from north to west or from east to south. - - +* Partial adaptive +*The west-first routing algorithm does not allow turns from north to west or from south to west. +*The north last routing algorithm does not allow turns from north to east or from north to west. +*The negetive fist routing algorithm does net allow turns from north to west or from east to south. *********************************************/ /************************************ - - west-first - +* west-first +* *************************************/ module west_first_routing #( - parameter NX = 4, - parameter NY = 4 - ) - ( - current_x, // current router x address - current_y, // current router y address - dest_x, // destination x address - dest_y, // destination y address - destport // router output port - + parameter NX = 4, + parameter NY = 4 + ) ( + current_x, // current router x address + current_y, // current router y address + dest_x, // destination x address + dest_y, // destination y address + destport // router output port ); - - + function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 0); @@ -597,79 +517,63 @@ module odd_even_routing #( assign a = possible_out_port[EAST] | possible_out_port[WEST]; assign b = possible_out_port[NORTH]| possible_out_port[SOUTH]; assign destport = {x,y,a,b}; - - - - endmodule - -/*********************************** - fully adaptive + +/*********************************** +* fully adaptive ***********************************/ - - - /************************************ - Duato’s Fully Adaptive -The packet which can travel in both x & y dimension can not use the reserved VC in y axies - *************************************/ - - - +/************************************ +* Duato’s Fully Adaptive +* The packet which can travel in both x & y dimension +* can not use the reserved VC in y axies +**************************************/ module duato_mesh_routing #( - parameter NX = 4, - parameter NY = 4 - ) - ( - current_x, // current router x address - current_y, // current router y address - dest_x, // destination x address - dest_y, // destination y address - destport // router output port - - ); + parameter NX = 4, + parameter NY = 4 +)( + current_x, // current router x address + current_y, // current router y address + dest_x, // destination x address + dest_y, // destination y address + destport // router output port +); - - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 current_x); assign x_min = (dest_x < current_x); assign y_plus = (dest_y > current_y); assign y_min = (dest_y < current_y); - - - endmodule - - module mesh_tori_encode_dstport ( dstport_one_hot, dstport_encoded ); - input [4 : 0] dstport_one_hot; output [3 : 0] dstport_encoded; - - localparam + localparam //LOCAL= 3'd0, EAST = 3'd1, NORTH= 3'd2, WEST = 3'd3, SOUTH= 3'd4; - /************************ - destination-port_in - x: 1 EAST, 0 WEST - y: 1 NORTH, 0 SOUTH - ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir + * destination-port_in + * x: 1 EAST, 0 WEST + * y: 1 NORTH, 0 SOUTH + * ab: 00 : LOCAL, 10: xdir, 01: ydir, 11 x&y dir *******************/ -// code the destination port + // code the destination port wire x,y,a,b; assign x = dstport_one_hot[EAST]; assign y = dstport_one_hot[NORTH]; assign a = dstport_one_hot[EAST] | dstport_one_hot[WEST]; assign b = dstport_one_hot[NORTH]| dstport_one_hot[SOUTH]; assign dstport_encoded = {x,y,a,b}; - -endmodule - - - - +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/route_torus.v b/mpsoc/rtl/src_noc/route_torus.v index 540c9a5..f567dbf 100755 --- a/mpsoc/rtl/src_noc/route_torus.v +++ b/mpsoc/rtl/src_noc/route_torus.v @@ -1,75 +1,71 @@ `include "pronoc_def.v" /********************************************************************** -** File: route_torus.v +** File: route_torus.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** Different routing algorithms (determinstic,partially adaptive and fully adaptive) -** for 2D torus-based topology +** Description: +** Different routing algorithms (determinstic,partially adaptive and fully adaptive) +** for 2D torus-based topology ** **************************************************************/ /******************************************** - Deterministic +* Deterministic *********************************************/ - /******************************************** - TRANC - *********************************************/ +/******************************************** +* TRANC +*********************************************/ module tranc_xy_routing #( parameter NX = 4, parameter NY = 4 -) -( +)( current_x, current_y, dest_x, dest_y, destport_encoded - ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2= (NX-2)) && (xd <= (NX-4))) || - ((xdiff> 0) && (xd<= (NX-3)))) + (xdiff == (-NX+1)) || + ((xc == (NX-4)) && (xd == (NX-2))) || + ((xc >= (NX-2)) && (xd <= (NX-4))) || + ((xdiff> 0) && (xd<= (NX-3)))) tranc_x_plus = 1'b1; else tranc_x_min = 1'b1; end @@ -728,9 +621,5 @@ module tranc_dir #( assign same_x = (xdiff == 0); assign same_y = (ydiff == 0); - /* verilator lint_on WIDTH */ - -endmodule - - +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index 7c7f31b..79f53f3 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -1,5 +1,4 @@ `include "pronoc_def.v" - /************************************** * Module: router_bypass * Date:2020-11-24 @@ -20,9 +19,7 @@ * lk-ahead routing, The packet can by-pass the next router once the bypassing condition are met ***************************/ -`include "pronoc_def.v" - module reduction_or #( parameter W = 5,//out width parameter N = 4 //array lenght @@ -39,76 +36,65 @@ module reduction_or #( for (int i = 0; i < N; i++) out |= in[i]; end - - endmodule module onehot_mux_2D #( - parameter W = 5,//out width - parameter N = 4 //sel width - )( - in, - sel, - out - ); - - input [W-1 : 0] in [N-1 : 0]; + parameter W = 5,//out width + parameter N = 4 //sel width +)( + in, + sel, + out + ); + input [W-1 : 0] in [N-1 : 0]; input [N-1 : 0] sel; output reg [W-1 : 0] out; - always_comb begin out = {W{1'b0}}; for (int i = 0; i < N; i++) out |= (sel[i]) ? in[i] : {W{1'b0}}; end - - endmodule module onehot_mux_1D #( - parameter W = 5,//out width - parameter N = 4 //sel width - )( - input [W*N-1 : 0] in, - input [N-1 : 0] sel, - output [W-1 : 0] out - ); - -wire [W-1 : 0] in_array [N-1 : 0]; + parameter W = 5,//out width + parameter N = 4 //sel width +)( + input [W*N-1 : 0] in, + input [N-1 : 0] sel, + output [W-1 : 0] out +); -genvar i; -generate -for (i=0;i1)begin : have_class - assign hdr_flit.message_class = flit.payload [CLASS_MSB : CLASS_LSB]; - end else begin : no_class - assign hdr_flit.message_class = {Cw{1'b0}}; - end - - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra_b - /* verilator lint_on WIDTH */ - assign hdr_flit.weight = flit.payload [WEIGHT_MSB : WEIGHT_LSB]; - end else begin : rra_b - assign hdr_flit.weight = {WEIGHTw{1'bX}}; - end - - if( BYTE_EN) begin : be_1 - assign hdr_flit.be = flit.payload [BE_MSB : BE_LSB]; - end else begin : be_0 - assign hdr_flit.be = {BEw{1'bX}}; - end - - - assign offset = flit.payload [DATA_MSB : DATA_LSB]; - - - if(Dw > OFFSETw) begin : if1 - assign data_o={{(Dw-OFFSETw){1'b0}},offset}; - end else begin : if2 - assign data_o=offset[Dw-1 : 0]; - end + assign hdr_flit.message_class = (C>1)? + flit.payload [CLASS_MSB : CLASS_LSB] : + {Cw{1'b0}}; + /* verilator lint_off WIDTH */ + assign hdr_flit.weight = (SWA_ARBITER_TYPE != "RRA")? + /* verilator lint_on WIDTH */ + flit.payload [WEIGHT_MSB : WEIGHT_LSB]: + {WEIGHTw{1'bX}}; + assign hdr_flit.be = (BYTE_EN)? + flit.payload [BE_MSB : BE_LSB]: + {BEw{1'bX}}; + assign offset = flit.payload [DATA_MSB : DATA_LSB]; + generate + if(Dw > OFFSETw) begin : if1 + assign data_o={{(Dw-OFFSETw){1'b0}},offset}; + end else begin : if2 + assign data_o=offset[Dw-1 : 0]; + end endgenerate endmodule @@ -206,7 +176,6 @@ module smart_chanel_check #( reset, clk ); - `NOC_CONF input flit_chanel_t flit_chanel; @@ -256,7 +225,6 @@ module smart_forward_ivc_info #( ovc_locally_requested, reset,clk ); - `NOC_CONF //ivc info @@ -266,7 +234,7 @@ module smart_forward_ivc_info #( input oport_info_t oport_info [P-1 : 0]; output smart_chanel_t smart_chanel [P-1 : 0]; output [V-1 : 0] ovc_locally_requested [P-1 : 0]; - + smart_ivc_info_t smart_ivc_info [P-1 : 0][V-1 : 0]; smart_ivc_info_t smart_ivc_mux [P-1 : 0]; @@ -286,35 +254,28 @@ module smart_forward_ivc_info #( non_assigned_vc_req[2][0] destport_one_hot[3]--> | [3][0] [2] */ - smart_chanel_t smart_chanel_next [P-1 : 0]; - + smart_chanel_t smart_chanel_next [P-1 : 0]; genvar i,j,z; generate - for (i=0;i 4) begin : local_ports - assign goes_straight_o = 1'b0; // There is not a next router in this case at all - end - else begin :non_local - - wire [4 : 0 ] destport_one_hot; - mesh_tori_decode_dstport decoder( - .dstport_encoded(destport_coded_i), - .dstport_one_hot(destport_one_hot) - ); - - assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; - end//else - end//mesh_tori - /* verilator lint_off WIDTH */ - else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :oneD - /* verilator lint_on WIDTH */ - if (SS_PORT_LOC == 0 || SS_PORT_LOC > 2) begin : local_ports - assign goes_straight_o = 1'b0; // There is not a next router in this case at all - end - else begin :non_local - - wire [2: 0 ] destport_one_hot; - - line_ring_decode_dstport decoder( - .dstport_encoded(destport_coded_i), - .dstport_one_hot(destport_one_hot) - - ); - assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; - - end //non_local - end// oneD - - //TODO Add fattree & custom + if(TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY =="FMESH") begin :twoD + /* verilator lint_on WIDTH */ + if (SS_PORT_LOC == 0 || SS_PORT_LOC > 4) begin : local_ports + assign goes_straight_o = 1'b0; // There is not a next router in this case at all + end else begin :non_local + wire [4 : 0 ] destport_one_hot; + mesh_tori_decode_dstport decoder( + .dstport_encoded(destport_coded_i), + .dstport_one_hot(destport_one_hot) + ); - endgenerate - + assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; + end//else + end//mesh_tori + /* verilator lint_off WIDTH */ + else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :oneD + /* verilator lint_on WIDTH */ + if (SS_PORT_LOC == 0 || SS_PORT_LOC > 2) begin : local_ports + assign goes_straight_o = 1'b0; // There is not a next router in this case at all + end else begin :non_local + wire [2: 0 ] destport_one_hot; + line_ring_decode_dstport decoder( + .dstport_encoded(destport_coded_i), + .dstport_one_hot(destport_one_hot) + ); + assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; + end //non_local + end// oneD + + //TODO Add fattree & custom +endgenerate endmodule - - + module smart_validity_check_per_ivc #( parameter NOC_ID=0, parameter IVC_NUM = 0 @@ -578,10 +472,7 @@ module smart_validity_check_per_ivc #( smart_ivc_reset_o, smart_ivc_granted_ovc_num_o ); - - `NOC_CONF - input reset, clk; //smart channel @@ -603,8 +494,8 @@ module smart_validity_check_per_ivc #( ss_ovc_avalable_in_ss_port, ss_ovc_crossbar_wr, ss_port_link_reg_flit_wr; -//output -output + //output + output smart_single_flit_pck_o , smart_ivc_smart_en_o, smart_credit_o, @@ -615,79 +506,54 @@ output smart_ivc_reset_o, smart_mask_available_ss_ovc_o; -output reg [V-1 : 0] smart_ivc_granted_ovc_num_o; - -always @(*) begin - smart_ivc_granted_ovc_num_o={V{1'b0}}; - smart_ivc_granted_ovc_num_o[IVC_NUM]=smart_ivc_num_getting_ovc_grant_o; -end - - - -wire smart_req_valid_next = smart_requests_i & smart_ivc_i & goes_straight; -logic smart_req_valid; -wire smart_hdr_flit_req_next = smart_req_valid_next & smart_hdr_flit; -logic smart_hdr_flit_req; - -pronoc_register #(.W(1)) req1 (.in(smart_req_valid_next), .reset(reset), .clk(clk), .out(smart_req_valid)); -pronoc_register #(.W(1)) req2 (.in(smart_hdr_flit_req_next), .reset(reset), .clk(clk), .out(smart_hdr_flit_req)); - + output reg [V-1 : 0] smart_ivc_granted_ovc_num_o; - - -// condition1: new smart vc allocation condition -wire hdr_flit_condition = ~ovc_locally_requested & ss_ovc_avalable_in_ss_port; -wire nonhdr_flit_condition = assigned_to_ss_ovc & assigned_ovc_not_full; -wire condition1 = - /* verilator lint_off WIDTH */ - (PCK_TYPE == "SINGLE_FLIT")? hdr_flit_condition : - /* verilator lint_on WIDTH */ - (ovc_is_assigned)? nonhdr_flit_condition : hdr_flit_condition; -wire condition2; -generate - -/* verilator lint_off WIDTH */ -wire non_empty_ivc_condition =(PCK_TYPE == "SINGLE_FLIT")? 1'b0 :ivc_request; -/* verilator lint_on WIDTH */ - - -if( ADD_PIPREG_AFTER_CROSSBAR == 1) begin :link_reg - assign condition2= ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr| ss_ovc_crossbar_wr); -end else begin : no_link_reg - assign condition2= ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr); // ss_port_link_reg_flit_wr are identical with ss_ovc_crossbar_wr when there is no link reg -end - -endgenerate -wire conditions_met = condition1 & condition2; -assign smart_ivc_smart_en_o = conditions_met & smart_req_valid; + always @(*) begin + smart_ivc_granted_ovc_num_o={V{1'b0}}; + smart_ivc_granted_ovc_num_o[IVC_NUM]=smart_ivc_num_getting_ovc_grant_o; + end - - -assign smart_single_flit_pck_o = + wire smart_req_valid_next = smart_requests_i & smart_ivc_i & goes_straight; + logic smart_req_valid; + wire smart_hdr_flit_req_next = smart_req_valid_next & smart_hdr_flit; + logic smart_hdr_flit_req; + + pronoc_register #(.W(1)) req1 (.in(smart_req_valid_next), .reset(reset), .clk(clk), .out(smart_req_valid)); + pronoc_register #(.W(1)) req2 (.in(smart_hdr_flit_req_next), .reset(reset), .clk(clk), .out(smart_hdr_flit_req)); + // condition1: new smart vc allocation condition + wire hdr_flit_condition = ~ovc_locally_requested & ss_ovc_avalable_in_ss_port; + wire nonhdr_flit_condition = assigned_to_ss_ovc & assigned_ovc_not_full; + wire condition1 = + /* verilator lint_off WIDTH */ + (PCK_TYPE == "SINGLE_FLIT")? hdr_flit_condition : + /* verilator lint_on WIDTH */ + (ovc_is_assigned)? nonhdr_flit_condition : hdr_flit_condition; + wire condition2; /* verilator lint_off WIDTH */ - (PCK_TYPE == "SINGLE_FLIT")? 1'b1 : + wire non_empty_ivc_condition =(PCK_TYPE == "SINGLE_FLIT")? 1'b0 :ivc_request; /* verilator lint_on WIDTH */ - (MIN_PCK_SIZE==1)? flit_tail_flag_i & flit_hdr_flag_i : 1'b0; - -assign smart_buff_space_decreased_o = smart_ivc_smart_en_o & flit_wr_i ; -assign smart_ivc_num_getting_ovc_grant_o = smart_buff_space_decreased_o & !ovc_is_assigned & flit_hdr_flag_i; -assign smart_ivc_reset_o = smart_buff_space_decreased_o & flit_tail_flag_i; -assign smart_ss_ovc_is_released_o = smart_ivc_reset_o & ~smart_single_flit_pck_o; -assign smart_ss_ovc_is_allocated_o = smart_ivc_num_getting_ovc_grant_o & ~smart_single_flit_pck_o; + assign condition2=( ADD_PIPREG_AFTER_CROSSBAR == 1)? + ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr| ss_ovc_crossbar_wr): + ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr); // ss_port_link_reg_flit_wr are identical with ss_ovc_crossbar_wr when there is no link reg + wire conditions_met = condition1 & condition2; + assign smart_ivc_smart_en_o = conditions_met & smart_req_valid; + assign smart_single_flit_pck_o = + /* verilator lint_off WIDTH */ + (PCK_TYPE == "SINGLE_FLIT")? 1'b1 : + /* verilator lint_on WIDTH */ + (MIN_PCK_SIZE==1)? flit_tail_flag_i & flit_hdr_flag_i : 1'b0; + assign smart_buff_space_decreased_o = smart_ivc_smart_en_o & flit_wr_i ; + assign smart_ivc_num_getting_ovc_grant_o = smart_buff_space_decreased_o & !ovc_is_assigned & flit_hdr_flag_i; + assign smart_ivc_reset_o = smart_buff_space_decreased_o & flit_tail_flag_i; + assign smart_ss_ovc_is_released_o = smart_ivc_reset_o & ~smart_single_flit_pck_o; + assign smart_ss_ovc_is_allocated_o = smart_ivc_num_getting_ovc_grant_o & ~smart_single_flit_pck_o; + //mask the available SS OVC for local requests allocation if the following conditions met + assign smart_mask_available_ss_ovc_o = smart_hdr_flit_req & ~ovc_locally_requested & condition2; + pronoc_register #(.W(1)) credit(.in(smart_buff_space_decreased_o), .reset(reset), .clk(clk), .out(smart_credit_o)); +endmodule - -//mask the available SS OVC for local requests allocation if the following conditions met -assign smart_mask_available_ss_ovc_o = smart_hdr_flit_req & ~ovc_locally_requested & condition2; - - -pronoc_register #(.W(1)) credit(.in(smart_buff_space_decreased_o), .reset(reset), .clk(clk), .out(smart_credit_o)); - -endmodule - - - module smart_allocator_per_iport # ( parameter NOC_ID=0, parameter P=5, @@ -724,13 +590,11 @@ module smart_allocator_per_iport # ( smart_ivc_single_flit_pck_o, smart_ovc_single_flit_pck_o ); - `NOC_CONF - //general - input clk, reset; - input [RAw-1 :0] current_r_addr_i; - input [RAw-1: 0] neighbors_r_addr_i [P-1 : 0]; + input clk, reset; + input [RAw-1 :0] current_r_addr_i; + input [RAw-1: 0] neighbors_r_addr_i [P-1 : 0]; //channels input smart_chanel_t smart_chanel_i; input flit_chanel_t flit_chanel_i; @@ -761,8 +625,6 @@ module smart_allocator_per_iport # ( wire [DSTPw-1 : 0] destport,lkdestport; wire goes_straight; - - /* verilator lint_off WIDTH */ localparam LOCATED_IN_NI= (TOPOLOGY=="RING" || TOPOLOGY=="LINE") ? (SW_LOC == 0 || SW_LOC>2) : @@ -806,90 +668,74 @@ module smart_allocator_per_iport # ( //look ahead routing. take straight next router address as input conventional_routing #( - .NOC_ID(NOC_ID), - .TOPOLOGY (TOPOLOGY), - .ROUTE_NAME (ROUTE_NAME), - .ROUTE_TYPE (ROUTE_TYPE), - .T1 (T1), - .T2 (T2), - .T3 (T3), - .RAw (RAw), - .EAw (EAw), - .DSTPw (DSTPw), - .LOCATED_IN_NI (LOCATED_IN_NI) - ) lkrouting ( - .reset (reset), - .clk (clk), - .current_r_addr (neighbors_r_addr_i[SS_PORT_LOC]), - .src_e_addr ( ),// needed only for custom routing - .dest_e_addr (smart_chanel_i.dest_e_addr), - .destport (lkdestport) - ); + .NOC_ID(NOC_ID), + .TOPOLOGY (TOPOLOGY), + .ROUTE_NAME (ROUTE_NAME), + .ROUTE_TYPE (ROUTE_TYPE), + .T1 (T1), + .T2 (T2), + .T3 (T3), + .RAw (RAw), + .EAw (EAw), + .DSTPw (DSTPw), + .LOCATED_IN_NI (LOCATED_IN_NI) + ) lkrouting ( + .reset (reset), + .clk (clk), + .current_r_addr (neighbors_r_addr_i[SS_PORT_LOC]), + .src_e_addr ( ),// needed only for custom routing + .dest_e_addr (smart_chanel_i.dest_e_addr), + .destport (lkdestport) + ); pronoc_register #(.W(DSTPw)) reg2 (.in(lkdestport), .reset(reset), .clk(clk), .out(smart_lk_destport_o)); wire [V-1 : 0] ss_ovc_crossbar_wr;//If asserted, a flit will be injected to ovc at next clk cycle assign ss_ovc_crossbar_wr = (ss_smart_chanel_new.requests[0]) ? ss_smart_chanel_new.ovc : {V{1'b0}}; - - - //assign smart_ivc_num_getting_ovc_grant_o = smart_ss_ovc_is_allocated_o; //assign smart_ivc_reset_o = smart_ss_ovc_is_released_o; genvar i,j; generate - for (i=0;i 0) counter_next = counter -1'b1; - end - - assign credit_out = credit_in | smart_credit_in | (counter > 0); - - pronoc_register #(.W(Bw+1)) reg1 (.in(counter_next), .reset(reset), .clk(clk), .out(counter)); - - -endmodule - - - - - - - - - - - - - - - - - - + input credit_in, smart_credit_in, reset, clk; + output credit_out; + logic [Bw : 0] counter, counter_next; + + always @(*) begin + counter_next=counter; + if(credit_in & smart_credit_in) counter_next = counter +1'b1; + else if(credit_in | smart_credit_in) counter_next=counter; + else if(counter > 0) counter_next = counter -1'b1; + end + assign credit_out = credit_in | smart_credit_in | (counter > 0); + pronoc_register #(.W(Bw+1)) reg1 (.in(counter_next), .reset(reset), .clk(clk), .out(counter)); +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index 1806b38..5ed49f2 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -980,11 +980,11 @@ module distance_gen #( generate /* verilator lint_off WIDTH */ if (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE")begin : tori_noc + localparam NY =(TOPOLOGY == "RING" || TOPOLOGY == "LINE")? 1 : T2; /* verilator lint_on WIDTH */ - mesh_torus_distance_gen #( .T1(T1), - .T2(T2), + .T2(NY), .T3(T3), .TOPOLOGY(TOPOLOGY), .DISTw(DISTw), From 96e030d7bce5742308a6dcede3b3dd9d570b247b Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 17 Feb 2025 23:51:06 +0100 Subject: [PATCH 013/107] fix indent --- mpsoc/rtl/arbiter.v | 691 ++++-------- mpsoc/rtl/main_comp.v | 1003 +++++------------ mpsoc/rtl/src_noc/congestion_analyzer.v | 47 - mpsoc/rtl/src_noc/routing.v | 447 +++----- mpsoc/rtl/src_noc/ss_allocator.sv | 578 ++++------ mpsoc/rtl/src_noc/star_noc.sv | 15 +- mpsoc/rtl/src_noc/topology_localparam.v | 14 +- mpsoc/rtl/src_noc/tree_noc_top.sv | 1 - mpsoc/rtl/src_noc/tree_route.v | 301 ++--- mpsoc/rtl/src_noc/wrra.v | 550 +++------ mpsoc/rtl/src_openpiton/custom_include.v | 9 +- mpsoc/rtl/src_openpiton/noc_localparam.v | 64 +- mpsoc/rtl/src_openpiton/piton_mesh.sv | 749 ++++++------ mpsoc/rtl/src_openpiton/piton_pkg.sv | 24 +- mpsoc/rtl/src_openpiton/wrapper.sv | 258 ++--- mpsoc/rtl/src_synfull/dpi_int_pkg.sv | 26 +- mpsoc/rtl/src_synfull/dpi_interface.sv | 311 +++-- mpsoc/rtl/src_synfull/synfull_top.sv | 220 ++-- .../jtag_ram_test/src_verilog/lib/main_comp.v | 15 +- 19 files changed, 1882 insertions(+), 3441 deletions(-) diff --git a/mpsoc/rtl/arbiter.v b/mpsoc/rtl/arbiter.v index c2caeb2..87a34f3 100755 --- a/mpsoc/rtl/arbiter.v +++ b/mpsoc/rtl/arbiter.v @@ -1,68 +1,54 @@ - `timescale 1ns/1ps +`include "pronoc_def.v" /********************************************************************** -** File: arbiter.v +** File: arbiter.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** ** -** Description: -** This file contains several Fixed prority and round robin -** arbiters +** Description: +** This file contains several Fixed prority and round robin +** arbiters ** ******************************************************************************/ /***************************************** -* * general round robin arbiter -* -* ******************************************/ - `ifndef PRONOC_ARBITER `define PRONOC_ARBITER -`include "pronoc_def.v" - - - module arbiter #( parameter ARBITER_WIDTH =8 - -) -( - clk, - reset, - request, - grant, - any_grant +)( + clk, + reset, + request, + grant, + any_grant ); - - input [ARBITER_WIDTH-1 : 0] request; output [ARBITER_WIDTH-1 : 0] grant; output any_grant; input clk; input reset; - - - + generate if(ARBITER_WIDTH==1) begin: w1 assign grant= request; @@ -71,23 +57,18 @@ module arbiter #( //my own arbiter my_one_hot_arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), .grant (grant), .any_grant (any_grant) ); - end else begin : wb4 thermo_arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), @@ -104,23 +85,16 @@ endmodule * RRA with external priority enable signal * ******************************************/ - module arbiter_priority_en #( - parameter ARBITER_WIDTH =8 - -) -( - clk, - reset, - request, - grant, - any_grant, - priority_en + parameter ARBITER_WIDTH =8 +)( + clk, + reset, + request, + grant, + any_grant, + priority_en ); - - - - input [ARBITER_WIDTH-1 : 0] request; output [ARBITER_WIDTH-1 : 0] grant; output any_grant; @@ -128,7 +102,6 @@ module arbiter_priority_en #( input reset; input priority_en; - generate if(ARBITER_WIDTH==1) begin: w1 assign grant= request; @@ -137,25 +110,19 @@ module arbiter_priority_en #( //my own arbiter my_one_hot_arbiter_priority_en #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), .grant (grant), .any_grant (any_grant), .priority_en (priority_en) - ); - end else begin :wb4 thermo_arbiter_priority_en #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), @@ -168,37 +135,30 @@ endgenerate endmodule - /****************************************************** -* my_one_hot_arbiter +* my_one_hot_arbiter * RRA with binary-coded priority register. Binary-coded * Priority results in less area cost and CPD for arbire * width of 4 and smaller only. * ******************************************************/ - - - module my_one_hot_arbiter #( parameter ARBITER_WIDTH =4 - - -) -( +)( input [ARBITER_WIDTH-1 : 0] request, output [ARBITER_WIDTH-1 : 0] grant, output any_grant, input clk, input reset ); - + function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** This file contains several general RTL modules such as -** different types of multiplexors, converters and counters ... +** Description: +** This file contains several general RTL modules such as +** different types of multiplexors, converters and counters ... ** **************************************************************/ `ifndef PRONOC_COMMON `define PRONOC_COMMON -`include "pronoc_def.v" - -module pronoc_register - #( - parameter W=1, - parameter RESET_TO={W{1'b0}} - - )( - input [W-1:0] in, - input reset, - input clk, - output [W-1:0] out - ); +module pronoc_register #( + parameter W=1, + parameter RESET_TO={W{1'b0}} +)( + input [W-1: 0] in, + input reset, + input clk, + output [W-1: 0] out +); pronoc_register_reset_init #( .W(W) )reg1( @@ -55,59 +49,49 @@ module pronoc_register endmodule - -module pronoc_register_reset_init - #( - parameter W=1 - )( - input [W-1:0] in, - input reset, - input clk, - output reg [W-1:0] out, - input [W-1 : 0] reset_to - ); - - - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) out<=reset_to; - else out<=in; - end - +module pronoc_register_reset_init #( + parameter W=1 +)( + input [W-1: 0] in, + input reset, + input clk, + output reg [W-1: 0] out, + input [W-1 : 0] reset_to +); + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) out<=reset_to; + else out<=in; + end endmodule -module pronoc_register_reset_init_ld_en - #( - parameter W=1 - )( - input [W-1:0] in, - input reset, - input clk, - input ld, - output reg [W-1:0] out, - input [W-1 : 0] reset_to - ); - - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) out<=reset_to; - else if(ld) out<=in; - end +module pronoc_register_reset_init_ld_en #( + parameter W=1 +)( + input [W-1: 0] in, + input reset, + input clk, + input ld, + output reg [W-1: 0] out, + input [W-1 : 0] reset_to +); + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) out<=reset_to; + else if(ld) out<=in; + end endmodule -module pronoc_register_ld_en - #( - parameter W=1, - parameter RESET_TO={W{1'b0}} - - )( - input [W-1:0] in, - input reset, - input clk, - input ld, - output [W-1:0] out - ); - +module pronoc_register_ld_en #( + parameter W=1, + parameter RESET_TO={W{1'b0}} +)( + input [W-1: 0] in, + input reset, + input clk, + input ld, + output [W-1: 0] out +); pronoc_register_reset_init_ld_en #( .W(W) )reg1( @@ -123,111 +107,76 @@ endmodule /********************************* - - - - multiplexer - - - +* multiplexer ********************************/ - module one_hot_mux #( - parameter IN_WIDTH = 20, - parameter SEL_WIDTH = 5, - parameter OUT_WIDTH = IN_WIDTH/SEL_WIDTH - - ) - ( - input [IN_WIDTH-1 :0] mux_in, - output[OUT_WIDTH-1 :0] mux_out, - input[SEL_WIDTH-1 :0] sel - - ); - - wire [IN_WIDTH-1 :0] mask; - wire [IN_WIDTH-1 :0] masked_mux_in; - wire [SEL_WIDTH-1:0] mux_out_gen [OUT_WIDTH-1:0]; + parameter IN_WIDTH = 20, + parameter SEL_WIDTH = 5, + parameter OUT_WIDTH = IN_WIDTH/SEL_WIDTH +)( + input [IN_WIDTH-1 : 0] mux_in, + output[OUT_WIDTH-1 : 0] mux_out, + input[SEL_WIDTH-1 : 0] sel +); + wire [IN_WIDTH-1 : 0] mask; + wire [IN_WIDTH-1 : 0] masked_mux_in; + wire [SEL_WIDTH-1: 0] mux_out_gen [OUT_WIDTH-1: 0]; genvar i,j; - //first selector masking generate // first_mask = {sel[0],sel[0],sel[0],....,sel[n],sel[n],sel[n]} for(i=0; i1)? log2(ONE_HOT_WIDTH):1 -) -( - input [ONE_HOT_WIDTH-1 : 0] one_hot_code, - output [BIN_WIDTH-1 : 0] bin_code - + parameter ONE_HOT_WIDTH = 4, + parameter BIN_WIDTH = (ONE_HOT_WIDTH>1)? log2(ONE_HOT_WIDTH):1 +)( + input [ONE_HOT_WIDTH-1 : 0] one_hot_code, + output [BIN_WIDTH-1 : 0] bin_code ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21)begin :if1 - for(i=0; i1)begin :if1 + for(i=0; i1)? log2(IN_NUM): 1; - - - input [IN_WIDTH-1 :0] mux_in; - output [OUT_WIDTH-1 :0] mux_out; - input [SEL_WIDTH_BIN-1 :0] sel; - genvar i; - - - generate - if(IN_NUM>1) begin :if1 - wire [OUT_WIDTH-1 :0] mux_in_2d [IN_NUM -1 :0]; - for (i=0; i< IN_NUM; i=i+1) begin : loop - assign mux_in_2d[i] =mux_in[((i+1)*OUT_WIDTH)-1 : i*OUT_WIDTH]; - end - assign mux_out = mux_in_2d[sel]; - end else begin :els - assign mux_out = mux_in; - end - endgenerate + localparam + IN_NUM = IN_WIDTH/OUT_WIDTH, + SEL_WIDTH_BIN = (IN_NUM>1) ? log2(IN_NUM): 1; + input [IN_WIDTH-1 : 0] mux_in; + output [OUT_WIDTH-1 : 0] mux_out; + input [SEL_WIDTH_BIN-1 : 0] sel; + genvar i; + generate + if(IN_NUM>1) begin :if1 + wire [OUT_WIDTH-1 : 0] mux_in_2d [IN_NUM -1 : 0]; + for (i=0; i< IN_NUM; i=i+1) begin : loop + assign mux_in_2d[i] =mux_in[((i+1)*OUT_WIDTH)-1 : i*OUT_WIDTH]; + end + assign mux_out = mux_in_2d[sel]; + end else begin :els + assign mux_out = mux_in; + end + endgenerate endmodule - module accumulator #( parameter INw= 20, parameter OUTw=4, parameter NUM =5 -) -( +)( in_all, out ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 OUTw) begin : bigger - assign out = (sum[SUMw-1 : OUTw] > 0 ) ? {OUTw{1'b1}} : sum[OUTw-1 : 0] ; + assign out = (sum[SUMw-1 : OUTw] > 0 ) ? {OUTw{1'b1}} : sum[OUTw-1 : 0] ; end else begin : less - assign out = {{(OUTw-SUMw){1'b0}}, sum} ; + assign out = {{(OUTw-SUMw){1'b0}}, sum} ; end - - - endgenerate - - // This is supposed to be synyhesized as "sum=in[0]+in[1]+...in[Num-1]"; - // It works with Quartus, Verilator and Modelsim compilers + // This is supposed to be synyhesized as "sum=in[0]+in[1]+...in[Num-1]"; + // It works with Quartus, Verilator and Modelsim compilers integer k; always @(*)begin sum=0; for (k=0;k1) for(i=0; ij) begin :if1 assign comp_array [i][j] = ~ comp_array [j][i-1]; end else begin :els assign comp_array [i] [j] = numbers[i]<= numbers[j+1]; end end//for j - assign min_out[i]= & comp_array[i]; + assign min_out[i]= & comp_array[i]; end//for i end//else endgenerate - endmodule - - -/******************************************** - - Carry-based reduction parallel counter - - -********************************************/ -module parallel_counter #( - parameter IN_WIDTH =120 // max 127 -) -( - in, - out -); - - - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 IN_WIDTH ) begin :w1 - assign pc_in = {{(PCIw-IN_WIDTH){1'b0}},in}; - end else begin:els - assign pc_in=in; - end // if - - if(PCIw == 7) begin :w7 - - PC_7_3 pc ( - .in(pc_in), - .out(pc_out) - ); - - end else if(PCIw == 15) begin :w15 - PC_15_4 pc ( - .in(pc_in), - .out(pc_out) - ); - - end else if(PCIw == 31) begin :w31 - PC_31_5 pc ( - .in(pc_in), - .out(pc_out) - ); - end else if(PCIw == 63) begin :w63 - PC_63_6 pc ( - .in(pc_in), - .out(pc_out) - ); - - end else begin :w127 - PC_127_7 pc ( - .in(pc_in), - .out(pc_out) - ); - end - - endgenerate - - assign out = pc_out[OUT_WIDTH-1 : 0]; - -endmodule - - - -//carry-sum generation blocks -module CS_GEN ( - in, - abc, - s -); - input [6 : 0] in; - output s; - output [2 : 0] abc; - - wire a,b,c,s; - wire [3 : 0] in1; - wire [2 : 0] in2; - wire [2 : 0] j1; - wire [1 : 0] j2; - - assign {in2,in1} = in; -/* verilator lint_off WIDTH */ - assign j1= in1[3]+in1[2]+in1[1]+in1[0]; - assign j2= in2[2]+in2[1]+in2[0]; -/* verilator lint_on WIDTH */ - - //s is asserted when both in1 and in2 have odd number of ones. - assign s = j1[0] ^ j2[0]; - // a is asserted when there are at least two ones in in1 (i.e., j1 >= 2); - assign a = (j1 > 3'd1); - - //b is asserted when there are at least two ones in in2 (i.e., j2 >= 2); - assign b = (j2 > 2'd1); - - // C is asserted when when j1 equals 4 or when s is asserted - assign c = (j1==4) | (j1[0] & j2[0]); - - assign abc = {a,b,c}; -endmodule - -/************************* - - (7,3) parallel counter - -*************************/ - -module PC_7_3 ( - in, - out - -); - input [6 : 0] in; - output [2 : 0] out; - - wire [2 : 0] abc; - - CS_GEN cs( - .in(in), - .abc(abc), - .s(out[0]) - ); - - assign out[2:1] = abc[2]+abc[1]+abc[0]; - - - - -endmodule - -/************************* - - (15,4) parallel counter - -*************************/ - -module PC_15_4 ( - in, - out - -); - input [14 : 0] in; - output [3 : 0] out; - - wire [2:0] abc0,abc1; - wire s0,s1,b2; - - CS_GEN cs0( - .in (in [6 : 0]), - .abc (abc0), - .s (s0) - ); - - CS_GEN cs1( - .in (in [13 : 7]), - .abc (abc1), - .s (s1) - ); - - assign {b2,out[0]} =in [14] + s0 +s1; - - PC_7_3 pc_sub( - .in({abc0,abc1,b2}), - .out(out[3:1]) - ); - - - - -endmodule - - -// (31,5) parallel counter -module PC_31_5 ( - in, - out - -); - localparam CS_NUM = 5; - - input [30 : 0] in; - output [4 : 0] out; - - - wire [CS_NUM-1 : 0] s; - wire [(CS_NUM*7)-1 : 0] cs_in; - wire [14 : 0] pc_15_in; - - assign cs_in ={s[3:0] ,in }; - - genvar i; - generate - for (i=0;i 2) begin :l1 - always @(*)begin - if(NC[0]==1'b0)begin // odd - start_o_next={start_o[NC-3:0],start_o[NC-2],start}; - end else begin //even - start_o_next={start_o[NC-3:0],start_o[NC-1],start}; - - end + generate + if(NC > 2) begin :l1 + always @(*)begin + if(NC[0]==1'b0)begin // odd + start_o_next={start_o[NC-3: 0],start_o[NC-2],start}; + end else begin //even + start_o_next={start_o[NC-3: 0],start_o[NC-1],start}; + end + end + end else begin :l2 + always @(*) start_o_next = {NC{start}}; end - end -else begin :l2 - always @(*) start_o_next = {NC{start}}; -end - -endgenerate - - reg [2:0] counter; + endgenerate + + reg [2: 0] counter; assign cnt_increase=(counter==3'd0); always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin @@ -1037,12 +546,8 @@ endgenerate start_i_reg <= start_i; if(cnt_increase | start) start_o_reg <= start_o_next; - end//reset end //always - assign start_o=(cnt_increase | start)? start_o_reg : {NC{1'b0}}; - endmodule - -`endif +`endif \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.v b/mpsoc/rtl/src_noc/congestion_analyzer.v index 544fabb..1674660 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.v +++ b/mpsoc/rtl/src_noc/congestion_analyzer.v @@ -76,15 +76,6 @@ module port_presel_based_dst_ports_vc #( .in_all(ovc_status_per_port[i]), .out(vc_counter[i]) ); - - /* - parallel_counter #( - .IN_WIDTH(V) - )counter ( - .in (ovc_status_per_port[i]), - .out (vc_counter[i]) - ); - */ end//for endgenerate /******************* @@ -510,16 +501,6 @@ module congestion_out_based_ivc_notgrant #( .in_all(ivc_request_not_granted), .out(ivc_req_num) ); - /* - parallel_counter #( - .IN_WIDTH(PV) - ) - ivc_req_counter - ( - .in(ivc_request_not_granted), - .out(ivc_req_num) - ); - */ generate if(CONGw==2)begin :w2 @@ -844,14 +825,6 @@ module congestion_out_based_avb_ovc_not_granted_ivc #( genvar i; generate for (i=0;i<4;i=i+1) begin :lp - /* - parallel_counter #( - .IN_WIDTH(CNT_Iw) - ) ovc_counter ( - .in(counter_in[i]), - .out(counter_o[i]) - ); - */ accumulator #( .INw(CNT_Iw), .OUTw(CNT_Ow), @@ -860,15 +833,6 @@ module congestion_out_based_avb_ovc_not_granted_ivc #( .in_all(counter_in[i]), .out(counter_o[i]) ); - /* - parallel_counter #( - .IN_WIDTH(V) - - ) ivc_counter ( - .in(ivc_not_grnt[i]), - .out(ivc_not_grnt_num[i]) - ); - */ accumulator #( .INw(V), .OUTw(CNT_Vw), @@ -915,17 +879,6 @@ module parallel_count_normalize #( output [OUTw-1 : 0] out; localparam CNTw = log2(INw+1); wire [CNTw-1 : 0] counter; -/* - parallel_counter #( - .IN_WIDTH(INw) - ) - ovc_avb_cnt - ( - .in(in), - .out(counter) - ); - */ - accumulator #( .INw(INw), .OUTw(CNTw), diff --git a/mpsoc/rtl/src_noc/routing.v b/mpsoc/rtl/src_noc/routing.v index 03f1d8a..6a7cdad 100755 --- a/mpsoc/rtl/src_noc/routing.v +++ b/mpsoc/rtl/src_noc/routing.v @@ -1,28 +1,28 @@ `include "pronoc_def.v" /********************************************************************** -** File: routing.v +** File: routing.v ** -** Copyright (C) 2014-2017 Alireza Monemi +** Copyright (C) 2014-2017 Alireza Monemi ** -** This file is part of ProNoC +** This file is part of ProNoC ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** look-ahead and conventional routing algorithms for Mesh and Torus NoC -** +** Description: +** look-ahead and conventional routing algorithms for Mesh and Torus NoC +** ** **************************************************************/ @@ -39,8 +39,7 @@ module conventional_routing #( parameter EAw = 3, parameter DSTPw = 4, parameter LOCATED_IN_NI = 1 // only needed for mesh and odd-even routing -) -( +)( reset, clk, current_r_addr, @@ -51,122 +50,103 @@ module conventional_routing #( function integer log2; input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 P-T3) ? 0 : SW_LOC; //single_local - mesh_tori_router_addr_decode #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .RAw(RAw) - ) - router_addr_decode - ( + ) router_addr_decode ( .r_addr(current_r_addr), .rx(current_rx), .ry(current_ry), @@ -359,14 +302,12 @@ module look_ahead_routing #( /* verilator lint_off WIDTH */ if(TOPOLOGY == "FMESH") begin :fmesh /* verilator lint_on WIDTH */ - fmesh_endp_addr_decode #( + fmesh_endp_addr_decode #( .T1(T1), .T2(T2), .T3(T3), .EAw(EAw) - ) - end_addr_decode - ( + ) end_addr_decode ( .e_addr(dest_e_addr), .ex(dest_ex), .ey(dest_ey), @@ -380,105 +321,83 @@ module look_ahead_routing #( .T2(T2), .T3(T3), .EAw(EAw) - ) - end_addr_decode - ( + ) end_addr_decode ( .e_addr(dest_e_addr), .ex(dest_ex), .ey(dest_ey), .el( ), .valid() ); - - end - mesh_torus_look_ahead_routing #( - .NX(T1), - .NY(T2), - .SW_LOC(SL_SW_LOC), - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE) - ) - look_ahead_route - ( - .current_x(current_rx), - .current_y(current_ry), - .dest_x(dest_ex), - .dest_y(dest_ey), - .destport_encoded(destport_encoded), - .lkdestport_encoded(lkdestport_encoded), - .reset(reset), - .clk(clk) + .NX(T1), + .NY(T2), + .SW_LOC(SL_SW_LOC), + .TOPOLOGY(TOPOLOGY), + .ROUTE_NAME(ROUTE_NAME), + .ROUTE_TYPE(ROUTE_TYPE) + ) look_ahead_route ( + .current_x(current_rx), + .current_y(current_ry), + .dest_x(dest_ex), + .dest_y(dest_ey), + .destport_encoded(destport_encoded), + .lkdestport_encoded(lkdestport_encoded), + .reset(reset), + .clk(clk) ); /* verilator lint_off WIDTH */ end else if (TOPOLOGY == "FATTREE") begin: fat /* verilator lint_on WIDTH */ - wire [PLKw-1 : 0] neighbors_rx; wire [PLw-1 : 0] neighbors_ry; - for (i=0; i=i)? current_addr_encoded[(i+1)*Kw-1 : i*Kw] : {Kw{1'b0}}; - + // assign current_addr [i] = (current_level >=i)? current_addr_encoded[(i+1)*Kw-1 : i*Kw] : {Kw{1'b0}}; assign dest_addr [i] = dest_addr_encoded[(i+1)*Kw-1 : i*Kw]; assign parrents_node_missmatch[i]= current_addr [i] != parrent_dest_addr [i]; end//for @@ -83,71 +74,57 @@ module tree_nca_routing #( assign current_node_dest_port = {1'b0,dest_addr[current_level]}; end endgenerate - - assign destport_encoded = (parrents_node_missmatch != {L{1'b0}}) ? /*go up*/ K[DSPw-1: 0] : /*go down*/current_node_dest_port; - + assign destport_encoded = (parrents_node_missmatch != {L{1'b0}}) ? /*go up*/ K[DSPw-1: 0] : /*go down*/current_node_dest_port; endmodule /************************* - * tree_conventional_routing - * **********************/ - - +* tree_conventional_routing +***********************/ module tree_conventional_routing #( parameter ROUTE_NAME = "NCA", parameter K = 2, // number of last level individual router`s endpoints. parameter L = 2 // Fattree layer number (The height of FT) - ) -( - +)( current_addr_encoded, // connected to current router x address current_level, //connected to current router y address dest_addr_encoded, // destination address destport_encoded // router output port - ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 weight_sum [j]) ? weight_sum [j] : limited_oport_weight [j]; end - - - end else begin : eq_or_actual + end else begin : eq_or_actual for (j=0;j= (piton_nx * piton_ny) && diff <= dim_max_diff && size < min ) begin min = size; - get_pronoc_X = x; + get_pronoc_X = x; end end end @@ -31,7 +30,7 @@ function integer get_pronoc_Y; input integer piton_ny; // openpiton y input integer concent; //concentration value input integer dim_max_diff; // max allowable diff between pronoc_x and pronoc_y - integer min , x , y, size, diff; + integer min , x , y, size, diff; begin if (concent == 1) get_pronoc_Y = piton_ny; else begin @@ -43,7 +42,7 @@ function integer get_pronoc_Y; diff = (x= (piton_nx * piton_ny) && diff <= dim_max_diff && size < min ) begin min = size; - get_pronoc_Y = y; + get_pronoc_Y = y; end end end diff --git a/mpsoc/rtl/src_openpiton/noc_localparam.v b/mpsoc/rtl/src_openpiton/noc_localparam.v index 8f5b70b..bbc8a25 100644 --- a/mpsoc/rtl/src_openpiton/noc_localparam.v +++ b/mpsoc/rtl/src_openpiton/noc_localparam.v @@ -5,42 +5,42 @@ localparam NOC_ID=0; //NoC parameters - localparam TOPOLOGY="FMESH"; - localparam T1=`PITON_X_TILES; - localparam T2=`PITON_Y_TILES; - localparam T3=1; - localparam V=1; - localparam C=0; - localparam B=4; - localparam LB=16; + localparam TOPOLOGY="FMESH"; + localparam T1=`PITON_X_TILES; + localparam T2=`PITON_Y_TILES; + localparam T3=1; + localparam V=1; + localparam C=0; + localparam B=4; + localparam LB=16; - localparam ROUTE_NAME="XY"; - localparam PCK_TYPE="MULTI_FLIT"; - localparam MIN_PCK_SIZE=1; - localparam BYTE_EN=0; - localparam CAST_TYPE="UNICAST"; - localparam MCAST_ENDP_LIST=10'h3ff; - localparam SSA_EN="YES"; - localparam SMART_MAX=0; - localparam CONGESTION_INDEX=3; - localparam ESCAP_VC_MASK=1'b1; - localparam VC_REALLOCATION_TYPE="NONATOMIC"; - localparam COMBINATION_TYPE="COMB_NONSPEC"; - localparam MUX_TYPE="BINARY"; - localparam DEBUG_EN=1; - localparam ADD_PIPREG_AFTER_CROSSBAR=1'b0; - localparam FIRST_ARBITER_EXT_P_EN=0; - localparam SWA_ARBITER_TYPE="RRA"; - localparam WEIGHTw=4; - localparam SELF_LOOP_EN="YES"; - localparam AVC_ATOMIC_EN=0; - localparam CLASS_SETTING={V{1'b1}}; - localparam CVw=(C==0)? V : C * V; + localparam ROUTE_NAME="XY"; + localparam PCK_TYPE="MULTI_FLIT"; + localparam MIN_PCK_SIZE=1; + localparam BYTE_EN=0; + localparam CAST_TYPE="UNICAST"; + localparam MCAST_ENDP_LIST=10'h3ff; + localparam SSA_EN="YES"; + localparam SMART_MAX=0; + localparam CONGESTION_INDEX=3; + localparam ESCAP_VC_MASK=1'b1; + localparam VC_REALLOCATION_TYPE="NONATOMIC"; + localparam COMBINATION_TYPE="COMB_NONSPEC"; + localparam MUX_TYPE="BINARY"; + localparam DEBUG_EN=1; + localparam ADD_PIPREG_AFTER_CROSSBAR=1'b0; + localparam FIRST_ARBITER_EXT_P_EN=0; + localparam SWA_ARBITER_TYPE="RRA"; + localparam WEIGHTw=4; + localparam SELF_LOOP_EN="YES"; + localparam AVC_ATOMIC_EN=0; + localparam CLASS_SETTING={V{1'b1}}; + localparam CVw=(C==0)? V : C * V; - localparam Fpay= + localparam Fpay= (NOC_ID=="N1") ? `PITON_NOC1_WIDTH : (NOC_ID=="N2") ? `PITON_NOC2_WIDTH : - `PITON_NOC3_WIDTH; + `PITON_NOC3_WIDTH; //simulation parameter //localparam MAX_RATIO = 1000; diff --git a/mpsoc/rtl/src_openpiton/piton_mesh.sv b/mpsoc/rtl/src_openpiton/piton_mesh.sv index a0c0961..707309c 100644 --- a/mpsoc/rtl/src_openpiton/piton_mesh.sv +++ b/mpsoc/rtl/src_openpiton/piton_mesh.sv @@ -1,440 +1,359 @@ `timescale 1ns/1ps `include "define.tmp.h" - /********************************* - * - * pack openpiton routers ports - * - * ******************************/ - + * pack openpiton routers ports + *******************************/ module piton_router_top - ( - - clk, - reset, - - current_r_addr, - - chan_in, - chan_out + clk, + reset, + current_r_addr, + chan_in, + chan_out ); - - import piton_pkg::*; - import pronoc_pkg::*; - - localparam P=5; - - - input clk, reset; - input [RAw-1 : 0] current_r_addr; - - - input piton_chan_t chan_in [P-1 : 0]; - output piton_chan_t chan_out [P-1 : 0]; - - - wire [`NOC_X_WIDTH-1:0] myLocX; // thi - wire [`NOC_Y_WIDTH-1:0] myLocY; - wire [`NOC_CHIPID_WIDTH-1:0] myChipID; - - - assign myLocY = (current_r_addr / `PITON_X_TILES ) % `PITON_Y_TILES ; - assign myLocX = (current_r_addr % `PITON_X_TILES ); - assign myChipID =0; - - dynamic_node_top_wrap router - ( - .clk(clk), - .reset_in(reset), - // dataIn (to input blocks) - .dataIn_N(chan_in[NORTH].data), - .dataIn_E(chan_in[EAST ].data), - .dataIn_S(chan_in[SOUTH].data), - .dataIn_W(chan_in[WEST ].data), - .dataIn_P(chan_in[LOCAL].data), - // validIn (to input blocks) - .validIn_N(chan_in[NORTH].valid), - .validIn_E(chan_in[EAST ].valid), - .validIn_S(chan_in[SOUTH].valid), - .validIn_W(chan_in[WEST ].valid), - .validIn_P(chan_in[LOCAL].valid), - // yummy (from nighboring inputlocks) - .yummyIn_N(chan_in[NORTH].yummy), - .yummyIn_E(chan_in[EAST ].yummy), - .yummyIn_S(chan_in[SOUTH].yummy), - .yummyIn_W(chan_in[WEST ].yummy), - .yummyIn_P(chan_in[LOCAL].yummy), - // My Absolute Address - .myLocX(myLocX), - .myLocY(myLocY), - .myChipID(myChipID), - //.ec_cfg(15'b0),//ec_dyn_cfg[14:0]), - //.store_meter_partner_address_X(5'b0) - //.store_meter_partner_address_Y(5'b0) - // DataOut (from crossbar) - .dataOut_N(chan_out[NORTH].data), - .dataOut_E(chan_out[EAST ].data), - .dataOut_S(chan_out[SOUTH].data), - .dataOut_W(chan_out[WEST ].data), - .dataOut_P(chan_out[LOCAL].data), - // validOut (from crossbar) - .validOut_N(chan_out[NORTH].valid), - .validOut_E(chan_out[EAST ].valid), - .validOut_S(chan_out[SOUTH].valid), - .validOut_W(chan_out[WEST ].valid), - .validOut_P(chan_out[LOCAL].valid), - // yummyOut (to neighboring outpu - .yummyOut_N(chan_out[NORTH].yummy), - .yummyOut_E(chan_out[EAST ].yummy), - .yummyOut_W(chan_out[WEST].yummy), - .yummyOut_S(chan_out[SOUTH ].yummy), - .yummyOut_P(chan_out[LOCAL].yummy), - // thanksIn (to CGNO) - .thanksIn_P()//? - ); - -endmodule + + import piton_pkg::*; + import pronoc_pkg::*; + + localparam P=5; + input clk, reset; + input [RAw-1 : 0] current_r_addr; + + input piton_chan_t chan_in [P-1 : 0]; + output piton_chan_t chan_out [P-1 : 0]; + + wire [`NOC_X_WIDTH-1:0] myLocX; // thi + wire [`NOC_Y_WIDTH-1:0] myLocY; + wire [`NOC_CHIPID_WIDTH-1:0] myChipID; + + assign myLocY = (current_r_addr / `PITON_X_TILES ) % `PITON_Y_TILES ; + assign myLocX = (current_r_addr % `PITON_X_TILES ); + assign myChipID =0; + + dynamic_node_top_wrap router ( + .clk(clk), + .reset_in(reset), + // dataIn (to input blocks) + .dataIn_N(chan_in[NORTH].data), + .dataIn_E(chan_in[EAST ].data), + .dataIn_S(chan_in[SOUTH].data), + .dataIn_W(chan_in[WEST ].data), + .dataIn_P(chan_in[LOCAL].data), + // validIn (to input blocks) + .validIn_N(chan_in[NORTH].valid), + .validIn_E(chan_in[EAST ].valid), + .validIn_S(chan_in[SOUTH].valid), + .validIn_W(chan_in[WEST ].valid), + .validIn_P(chan_in[LOCAL].valid), + // yummy (from nighboring inputlocks) + .yummyIn_N(chan_in[NORTH].yummy), + .yummyIn_E(chan_in[EAST ].yummy), + .yummyIn_S(chan_in[SOUTH].yummy), + .yummyIn_W(chan_in[WEST ].yummy), + .yummyIn_P(chan_in[LOCAL].yummy), + // My Absolute Address + .myLocX(myLocX), + .myLocY(myLocY), + .myChipID(myChipID), + //.ec_cfg(15'b0),//ec_dyn_cfg[14:0]), + //.store_meter_partner_address_X(5'b0) + //.store_meter_partner_address_Y(5'b0) + // DataOut (from crossbar) + .dataOut_N(chan_out[NORTH].data), + .dataOut_E(chan_out[EAST ].data), + .dataOut_S(chan_out[SOUTH].data), + .dataOut_W(chan_out[WEST ].data), + .dataOut_P(chan_out[LOCAL].data), + // validOut (from crossbar) + .validOut_N(chan_out[NORTH].valid), + .validOut_E(chan_out[EAST ].valid), + .validOut_S(chan_out[SOUTH].valid), + .validOut_W(chan_out[WEST ].valid), + .validOut_P(chan_out[LOCAL].valid), + // yummyOut (to neighboring outpu + .yummyOut_N(chan_out[NORTH].yummy), + .yummyOut_E(chan_out[EAST ].yummy), + .yummyOut_W(chan_out[WEST].yummy), + .yummyOut_S(chan_out[SOUTH ].yummy), + .yummyOut_P(chan_out[LOCAL].yummy), + // thanksIn (to CGNO) + .thanksIn_P()//? + ); +endmodule /********************* * piton_mesh - * * ********************/ - -`define router_id(x,y) ((y * NX) + x) -`define endp_id(x,y,l) ((y * NX) + x) * NL + l - - +`define router_id(x,y) ((y * NX) + x) +`define endp_id(x,y,l) ((y * NX) + x) * NL + l module piton_mesh - ( - - clk, - reset, - - chan_in_all, - chan_out_all + clk, + reset, + chan_in_all, + chan_out_all ); - - - import piton_pkg::*; - import pronoc_pkg::*; - - input clk, reset; - - - //local ports - input piton_chan_t chan_in_all [NE-1 : 0]; - output piton_chan_t chan_out_all [NE-1 : 0]; - - //all routers port - piton_chan_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; - piton_chan_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; - - wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; - - - // mesh torus - localparam - EAST = 3'd1, - NORTH = 3'd2, - WEST = 3'd3, - SOUTH = 3'd4; - //ring line - localparam - FORWARD = 2'd1, - BACKWARD= 2'd2; - - - genvar x,y,l; - generate - /* verilator lint_off WIDTH */ - if( TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin : ring_line - /* verilator lint_on WIDTH */ - for (x=0; x0)begin :not_first_x - assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; - end else begin :first_x - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "LINE") begin : line_first_x - /* verilator lint_on WIDTH */ - assign router_chan_in[x][BACKWARD]={PITON_CHANEL_w{1'b0}}; - end else begin : ring_first_x - assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; - end - end - - // connect other local ports - for (l=0; l0)begin :not_first_x + assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; + end else begin :first_x + /* verilator lint_off WIDTH */ + if(TOPOLOGY == "LINE") begin : line_first_x + /* verilator lint_on WIDTH */ + assign router_chan_in[x][BACKWARD]={PITON_CHANEL_w{1'b0}}; + end else begin : ring_first_x + assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; + end + end + // connect other local ports + for (l=0; l0) begin : not_first_y - assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; - end else begin :first_y - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin : first_y_mesh - /* verilator lint_on WIDTH */ - assign router_chan_in[`router_id(x,y)][NORTH] = {PITON_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :first_y_torus - /* verilator lint_on WIDTH */ - assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(NY-1))][SOUTH]; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FMESH") begin : first_y_fmesh //connect to endp - /* verilator lint_on WIDTH */ - localparam NORTH_ID = NX*NY*NL + x; - assign router_chan_in [`router_id(x,y)][NORTH] = chan_in_all [NORTH_ID]; - assign chan_out_all [NORTH_ID] = router_chan_out [`router_id(x,y)][NORTH]; - end//topology - end//y>0 - - - if(x>0)begin :not_first_x - assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; - end else begin :first_x - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin :first_x_mesh - /* verilator lint_on WIDTH */ - assign router_chan_in[`router_id(x,y)][WEST] = {PITON_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :first_x_torus - /* verilator lint_on WIDTH */ - assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FMESH") begin : first_x_fmesh //connect to endp - /* verilator lint_on WIDTH */ - localparam WEST_ID = NX*NY*NL +2*NX + y; - assign router_chan_in [`router_id(x,y)][WEST] = chan_in_all [WEST_ID]; - assign chan_out_all [WEST_ID] = router_chan_out [`router_id(x,y)][WEST]; - end//topology - end - - if(y < NY-1) begin : firsty - assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; - end else begin : lasty - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin :ly_mesh - /* verilator lint_on WIDTH */ - assign router_chan_in[`router_id(x,y)][SOUTH]= {PITON_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :ly_torus - /* verilator lint_on WIDTH */ - assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; - end else if(TOPOLOGY == "FMESH") begin : ly_fmesh //connect to endp - /* verilator lint_on WIDTH */ - localparam SOUTH_ID = NX*NY*NL + NX + x; - assign router_chan_in [`router_id(x,y)][SOUTH] = chan_in_all [SOUTH_ID]; - assign chan_out_all [SOUTH_ID] = router_chan_out [`router_id(x,y)][SOUTH]; - end//topology - end - - - // endpoint(s) connection - // connect other local ports - for (l=0; l0) begin : not_first_y + assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; + end else begin :first_y + /* verilator lint_off WIDTH */ + if(TOPOLOGY == "MESH") begin : first_y_mesh + /* verilator lint_on WIDTH */ + assign router_chan_in[`router_id(x,y)][NORTH] = {PITON_CHANEL_w{1'b0}}; + /* verilator lint_off WIDTH */ + end else if(TOPOLOGY == "TORUS") begin :first_y_torus + /* verilator lint_on WIDTH */ + assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(NY-1))][SOUTH]; + /* verilator lint_off WIDTH */ + end else if(TOPOLOGY == "FMESH") begin : first_y_fmesh //connect to endp + /* verilator lint_on WIDTH */ + localparam NORTH_ID = NX*NY*NL + x; + assign router_chan_in [`router_id(x,y)][NORTH] = chan_in_all [NORTH_ID]; + assign chan_out_all [NORTH_ID] = router_chan_out [`router_id(x,y)][NORTH]; + end//topology + end//y>0 + if(x>0)begin :not_first_x + assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; + end else begin :first_x + /* verilator lint_off WIDTH */ + if(TOPOLOGY == "MESH") begin :first_x_mesh + /* verilator lint_on WIDTH */ + assign router_chan_in[`router_id(x,y)][WEST] = {PITON_CHANEL_w{1'b0}}; + /* verilator lint_off WIDTH */ + end else if(TOPOLOGY == "TORUS") begin :first_x_torus + /* verilator lint_on WIDTH */ + assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; + /* verilator lint_off WIDTH */ + end else if(TOPOLOGY == "FMESH") begin : first_x_fmesh //connect to endp + /* verilator lint_on WIDTH */ + localparam WEST_ID = NX*NY*NL +2*NX + y; + assign router_chan_in [`router_id(x,y)][WEST] = chan_in_all [WEST_ID]; + assign chan_out_all [WEST_ID] = router_chan_out [`router_id(x,y)][WEST]; + end//topology + end + if(y < NY-1) begin : firsty + assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; + end else begin : lasty + /* verilator lint_off WIDTH */ + if(TOPOLOGY == "MESH") begin :ly_mesh + /* verilator lint_on WIDTH */ + assign router_chan_in[`router_id(x,y)][SOUTH]= {PITON_CHANEL_w{1'b0}}; + /* verilator lint_off WIDTH */ + end else if(TOPOLOGY == "TORUS") begin :ly_torus + /* verilator lint_on WIDTH */ + assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; + end else if(TOPOLOGY == "FMESH") begin : ly_fmesh //connect to endp + /* verilator lint_on WIDTH */ + localparam SOUTH_ID = NX*NY*NL + NX + x; + assign router_chan_in [`router_id(x,y)][SOUTH] = chan_in_all [SOUTH_ID]; + assign chan_out_all [SOUTH_ID] = router_chan_out [`router_id(x,y)][SOUTH]; + end//topology + end + // endpoint(s) connection + // connect other local ports + for (l=0; l= DATA_w + CTRL_BITS_w + .DATA_w(DATA_w) // header flit can carry Optional data. The data will be placed after control data. Fpay >= DATA_w + CTRL_BITS_w )head_gen( .flit_out(header_flit), .src_e_addr_in(src_e_addr), @@ -473,7 +425,6 @@ module piton_to_pronoc_wrapper ); assign chan_out.ctrl_chanel.credit_init_val = 4; - assign chan_out.flit_chanel.flit.hdr_flag =head; assign chan_out.flit_chanel.flit.tail_flag=tail; assign chan_out.flit_chanel.flit.vc=1'b1; @@ -482,7 +433,6 @@ module piton_to_pronoc_wrapper assign chan_out.flit_chanel.flit.payload = (head)? header_flit[Fpay-1 : 0] : dataIn; assign chan_out.smart_chanel = {SMART_CHANEL_w{1'b0}}; assign chan_out.flit_chanel.congestion = {CONGw{1'b0}}; - /* always @ (posedge clk) begin if(validIn==1'b1 && flit_type== HEADER)begin @@ -508,14 +458,12 @@ module piton_to_pronoc_wrapper //synthesis translate_on */ endmodule + + /******************************** * pronoc_to_piton_wrapper * ***************************/ - - - -module pronoc_to_piton_wrapper -#( +module pronoc_to_piton_wrapper #( parameter NOC_ID=0, parameter PORT_NUM=0, parameter TILE_NUM =0, @@ -527,45 +475,34 @@ module pronoc_to_piton_wrapper current_r_addr_o, chan_in ); - `NOC_CONF localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH ), HEAD_DATw = (64-MSB_BE-1), ADDR_CODED = (HEAD_DATw - PRESERVED_DATw); - //piton out input [`NOC_CHIPID_WIDTH-1:0] default_chipid; input [`NOC_X_WIDTH-1:0] default_coreid_x; input [`NOC_Y_WIDTH-1:0] default_coreid_y; input [FLATID_WIDTH-1:0] flat_tileid; - output [Fpay-1:0] dataOut; output validOut; output yummyOut; - output [RAw-1 : 0] current_r_addr_o; - //pronoc in input smartflit_chanel_t chan_in; - input reset,clk; - assign current_r_addr_o = chan_in.ctrl_chanel.neighbors_r_addr; - localparam Xw = log2(NX), // number of node in x axis Yw = log2(NY); // number of node in y axis - enum bit [1:0] {HEADER, BODY,TAIL} flit_type,flit_type_next; - localparam DATA_w = HEAD_DATw + Fpay - 64; hdr_flit_t hdr_flit; wire [DATA_w-1 : 0] head_dat; - //extract ProNoC header flit data header_flit_info #( .NOC_ID(NOC_ID), @@ -577,7 +514,6 @@ module pronoc_to_piton_wrapper ); wire [Fpay-1:0] header_flit; - wire [`MSG_DST_CHIPID_WIDTH-1 :0] dest_chipid; reg [`MSG_DST_X_WIDTH-1 :0] dest_x ; reg [`MSG_DST_Y_WIDTH-1 :0] dest_y ; @@ -586,25 +522,18 @@ module pronoc_to_piton_wrapper wire [`MSG_TYPE_WIDTH-1 :0] msg_type ; wire [`MSG_MSHRID_WIDTH-1 :0] mshrid ; wire [`MSG_OPTIONS_1_WIDTH-1 :0] option1 ; - wire [ADDR_CODED-1 : 0] dest_coded; - assign {dest_coded, length, msg_type, mshrid, option1} = head_dat [HEAD_DATw-1 : 0]; - pronoc_to_piton_endp_addr_converter#( - .NOC_ID(NOC_ID) - )addr_conv ( + .NOC_ID(NOC_ID) + )addr_conv ( .piton_end_addr_coded_i(dest_coded), .piton_chipid_o (dest_chipid), .piton_coreid_x_o(dest_x), .piton_coreid_y_o(dest_y) ); - - wire [MAX_P-1:0] destport_one_hot; - - // FBITS coding localparam [3: 0] FBITS_WEST = 4'b0010, @@ -631,7 +560,6 @@ module pronoc_to_piton_wrapper end end */ - assign dest_fbits = (destport_one_hot [LOCAL]) ? FBITS_PROCESSOR: (destport_one_hot [EAST ]) ? FBITS_EAST: @@ -640,14 +568,10 @@ module pronoc_to_piton_wrapper (destport_one_hot [SOUTH ]) ? FBITS_SOUTH: FBITS_PROCESSOR; wire [DSTPw-1 : 0] dstp_encoded = hdr_flit.destport; - - - localparam ELw = log2(T3), Pw = log2(MAX_P), PLw = (TOPOLOGY == "FMESH") ? Pw : ELw; - wire [PLw-1 : 0] endp_p_in; generate if(TOPOLOGY == "FMESH") begin : fmesh @@ -656,9 +580,7 @@ module pronoc_to_piton_wrapper .T2(T2), .T3(T3), .EAw(EAw) - ) - endp_addr_decode - ( + ) endp_addr_decode ( .e_addr(hdr_flit.dest_e_addr), .ex(), .ey(), @@ -672,42 +594,35 @@ module pronoc_to_piton_wrapper .T2(T2), .T3(T3), .EAw(EAw) - ) - endp_addr_decode - ( + ) endp_addr_decode ( .e_addr(hdr_flit.dest_e_addr), .ex( ), .ey( ), .el(endp_p_in), .valid( ) ); - end endgenerate destp_generator #( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .T1(T1), - .NL(T3), - .P(MAX_P), - .PLw(PLw), - .DSTPw(DSTPw), - .SELF_LOOP_EN (SELF_LOOP_EN), - .SW_LOC(PORT_NUM) - ) - decoder - ( - .destport_one_hot (destport_one_hot), - .dest_port_encoded(dstp_encoded), - .dest_port_out(), - .endp_localp_num(endp_p_in), - .swap_port_presel(), - .port_pre_sel(), - .odd_column(1'b0) - ); - - + .TOPOLOGY(TOPOLOGY), + .ROUTE_NAME(ROUTE_NAME), + .ROUTE_TYPE(ROUTE_TYPE), + .T1(T1), + .NL(T3), + .P(MAX_P), + .PLw(PLw), + .DSTPw(DSTPw), + .SELF_LOOP_EN (SELF_LOOP_EN), + .SW_LOC(PORT_NUM) + ) decoder ( + .destport_one_hot (destport_one_hot), + .dest_port_encoded(dstp_encoded), + .dest_port_out(), + .endp_localp_num(endp_p_in), + .swap_port_presel(), + .port_pre_sel(), + .odd_column(1'b0) + ); assign header_flit [ `MSG_DST_CHIPID] = dest_chipid; assign header_flit [ `MSG_DST_X] = dest_x; @@ -723,7 +638,6 @@ module pronoc_to_piton_wrapper assign header_flit [Fpay - 1 : 64] = head_dat[Fpay + HEAD_DATw -65 :HEAD_DATw]; end endgenerate - wire head = chan_in.flit_chanel.flit.hdr_flag; wire tail = chan_in.flit_chanel.flit.tail_flag; @@ -731,43 +645,33 @@ module pronoc_to_piton_wrapper assign validOut = chan_in.flit_chanel.flit_wr; assign yummyOut = chan_in.flit_chanel.credit; assign dataOut = (head)? header_flit[Fpay-1 : 0] : chan_in.flit_chanel.flit.payload; - - endmodule - + /********************* * pack noc_top ports - * * ******************/ - module noc_top_packed #( - parameter NOC_ID=0 -) -( + parameter NOC_ID=0 +)( reset, clk, chan_in_all, chan_out_all ); - `NOC_CONF localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH ), HEAD_DATw = (64-MSB_BE-1), ADDR_CODED = (HEAD_DATw - PRESERVED_DATw); - input clk,reset; //local ports input smartflit_chanel_t [NE-1 : 0] chan_in_all ; output smartflit_chanel_t [NE-1 : 0] chan_out_all ; - smartflit_chanel_t chan_in_all_unpacked [NE-1 : 0]; smartflit_chanel_t chan_out_all_unpacked [NE-1 : 0]; - genvar i; - generate for (i=0;i Date: Mon, 3 Mar 2025 17:01:31 +0100 Subject: [PATCH 014/107] fix indent --- mpsoc/perl_gui/lib/perl/ColorButton.pm | 69 +- mpsoc/perl_gui/lib/perl/common.pl | 1909 +++++++------- mpsoc/perl_gui/lib/perl/compile.pl | 13 +- mpsoc/perl_gui/lib/perl/diagram.pl | 2212 ++++++++--------- mpsoc/perl_gui/lib/perl/drag_drop.pl | 315 +-- mpsoc/perl_gui/lib/perl/emulator.pl | 1933 +++++++------- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 86 +- mpsoc/perl_gui/lib/perl/simulator.pl | 903 ++----- .../perl_gui/lib/perl/topology_verilog_gen.pl | 1254 ++++------ mpsoc/rtl/src_noc/debug.v | 5 +- mpsoc/rtl/src_noc/packet_injector.sv | 1 + mpsoc/rtl/src_noc/router_bypass.sv | 4 +- mpsoc/rtl/src_noc/routing.v | 5 +- mpsoc/rtl/src_noc/topology_localparam.v | 171 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 3 +- mpsoc/rtl/src_openpiton/wrapper.sv | 3 +- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 691 ++--- .../src_topology/common/custom_ni_routing.v | 63 +- 18 files changed, 3883 insertions(+), 5757 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/ColorButton.pm b/mpsoc/perl_gui/lib/perl/ColorButton.pm index a5e52ab..1d38a6b 100644 --- a/mpsoc/perl_gui/lib/perl/ColorButton.pm +++ b/mpsoc/perl_gui/lib/perl/ColorButton.pm @@ -39,48 +39,46 @@ use Glib::Object::Subclass 0xffff, [qw/readable writable/] ), - Glib::ParamSpec->string ( + Glib::ParamSpec->string ( 'label', 'Label', 'The lable of button', "BBB", [qw/readable writable/] ), - ] ; sub INIT_INSTANCE { - my $self = shift; - $self->{red} = 0xffff; - $self->{green} = 0xffff; - $self->{blue} = 0xffff; - $self->{label} = "Colored_button"; - - - my $frame = Gtk2::Frame->new; - $frame->set_border_width (0); - $frame->set_shadow_type ('etched-in'); - $self->add ($frame); - $frame->show; - my $event_box = Gtk2::EventBox->new; - # $event_box->set_size_request (140, 140); - my $label = Gtk2::Label->new($self->{label}); - $event_box->add($label); - - $frame->add ($event_box); - $event_box->show; - $self->{colorbox} = $event_box; - $self->{labelbox} = $label; + my $self = shift; + $self->{red} = 0xffff; + $self->{green} = 0xffff; + $self->{blue} = 0xffff; + $self->{label} = "Colored_button"; + + my $frame = Gtk2::Frame->new; + $frame->set_border_width (0); + $frame->set_shadow_type ('etched-in'); + $self->add ($frame); + $frame->show; + my $event_box = Gtk2::EventBox->new; + # $event_box->set_size_request (140, 140); + my $label = Gtk2::Label->new($self->{label}); + $event_box->add($label); + + $frame->add ($event_box); + $event_box->show; + $self->{colorbox} = $event_box; + $self->{labelbox} = $label; } sub on_show { - my $self = shift; - $self->set_color (red => $self->{red}, - green => $self->{green}, - blue => $self->{blue}); - $self->{labelbox}->set_label ($self->{label}); - + my $self = shift; + $self->set_color ( + red => $self->{red}, + green => $self->{green}, + blue => $self->{blue}); + $self->{labelbox}->set_label ($self->{label}); $self->signal_chain_from_overridden; } @@ -88,16 +86,15 @@ sub set_color { my $self = shift; my %params = @_; my $color = Gtk2::Gdk::Color->new ($params{red}, - $params{green}, - $params{blue}); - # $self->{colorbox}->get_colormap->alloc_color ($color, 0, 1); + $params{green}, + $params{blue}); + #$self->{colorbox}->get_colormap->alloc_color ($color, 0, 1); $self->{colorbox}->modify_bg ('normal', $color); - # $self->{colorbox}->modify_bg ('active', $color); - # $self->{colorbox}->modify_bg ('prelight', $color); + #$self->{colorbox}->modify_bg ('active', $color); + #$self->{colorbox}->modify_bg ('prelight', $color); $self->{red} = $params{red}; $self->{green} = $params{green}; $self->{blue} = $params{blue}; $self->signal_emit ('color-changed'); } - -1 +1 \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/common.pl b/mpsoc/perl_gui/lib/perl/common.pl index b7331c9..1814c3e 100644 --- a/mpsoc/perl_gui/lib/perl/common.pl +++ b/mpsoc/perl_gui/lib/perl/common.pl @@ -13,203 +13,168 @@ use Cwd 'abs_path'; use Term::ANSIColor qw(:constants); use IPC::Run qw(start pump finish timeout pumpable); - + use FindBin; use lib $FindBin::Bin; use constant::boolean; use IO::CaptureOutput qw(capture qxx qxy); - our %glob_setting; $glob_setting{'FONT_SIZE'}='default'; $glob_setting{'ICON_SIZE'}='default'; $glob_setting{'DSPLY_X'} ='default'; $glob_setting{'DSPLY_Y'} ='default'; - - - sub log2{ - my $num=shift; - my $log=($num <=1) ? 1: 0; - while( (1<< $log) < $num) { - $log++; - } - return $log; + my $num=shift; + my $log=($num <=1) ? 1: 0; + while( (1<< $log) < $num) { + $log++; + } + return $log; } sub find_the_most_similar_position{ - my ($item ,@list)=@_; - my $most_similar_pos=0; - my $lastsim=0; - my $i=0; - # convert item to lowercase - $item = lc $item; - foreach my $p(@list){ - my $similarity= similarity $item, $p; - if ($similarity > $lastsim){ - $lastsim=$similarity; - $most_similar_pos=$i; - } - $i++; - } - return $most_similar_pos; + my ($item ,@list)=@_; + my $most_similar_pos=0; + my $lastsim=0; + my $i=0; + # convert item to lowercase + $item = lc $item; + foreach my $p(@list){ + my $similarity= similarity $item, $p; + if ($similarity > $lastsim){ + $lastsim=$similarity; + $most_similar_pos=$i; + } + $i++; + } + return $most_similar_pos; } sub is_integer { - defined $_[0] && $_[0] =~ /^[+-]?\d+$/; + defined $_[0] && $_[0] =~ /^[+-]?\d+$/; } - #################### -# verilog file +# verilog file ################## - - sub read_verilog_file{ - my @files = @_; - my %cmd_line_defines = (); - my $quiet = 1; - my @inc_dirs = (); - my @lib_dirs = (); - my @lib_exts = (); - my $vdb = rvp->read_verilog(\@files,[],\%cmd_line_defines, - $quiet,\@inc_dirs,\@lib_dirs,\@lib_exts); - - my @problems = $vdb->get_problems(); - if (@problems) { - foreach my $problem ($vdb->get_problems()) { - print STDERR "$problem.\n" unless ( $problem =~ /smartflit_chanel_t/); - } - # die "Warnings parsing files!"; - } - return $vdb; + my @files = @_; + my %cmd_line_defines = (); + my $quiet = 1; + my @inc_dirs = (); + my @lib_dirs = (); + my @lib_exts = (); + my $vdb = rvp->read_verilog( + \@files,[],\%cmd_line_defines, + $quiet,\@inc_dirs,\@lib_dirs,\@lib_exts); + my @problems = $vdb->get_problems(); + if (@problems) { + foreach my $problem ($vdb->get_problems()) { + print STDERR "$problem.\n" unless ( $problem =~ /smartflit_chanel_t/); + } + # die "Warnings parsing files!"; + } + return $vdb; } - sub verilog_file_get_ports_list{ - my ($vdb,$top_module)=@_; - my @ports; - - foreach my $sig (sort $vdb->get_modules_signals($top_module)) { - my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, - $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = - $vdb->get_module_signal($top_module,$sig); - - if($type eq "input" or $type eq "inout" or $type eq "output" ){ - push(@ports, $sig); - - } - } - return @ports; + my ($vdb,$top_module)=@_; + my @ports; + foreach my $sig (sort $vdb->get_modules_signals($top_module)) { + my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, + $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = + $vdb->get_module_signal($top_module,$sig); + if($type eq "input" or $type eq "inout" or $type eq "output" ){ + push(@ports, $sig); + } + } + return @ports; } - - sub get_ports_type{ - my ($vdb,$top_module)=@_; - my %ports; - - foreach my $sig (sort $vdb->get_modules_signals($top_module)) { - my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, - $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = - $vdb->get_module_signal($top_module,$sig); - - if($type eq "input" or $type eq "inout" or $type eq "output" ){ - $ports{$sig}=$type; - - } - } - return %ports; + my ($vdb,$top_module)=@_; + my %ports; + foreach my $sig (sort $vdb->get_modules_signals($top_module)) { + my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, + $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = + $vdb->get_module_signal($top_module,$sig); + if($type eq "input" or $type eq "inout" or $type eq "output" ){ + $ports{$sig}=$type; + } + } + return %ports; } - sub get_ports_rang{ - my ($vdb,$top_module)=@_; - my %ports; - - foreach my $sig (sort $vdb->get_modules_signals($top_module)) { - my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, - $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = - $vdb->get_module_signal($top_module,$sig); - - if($type eq "input" or $type eq "inout" or $type eq "output" ){ - - - - $ports{$sig}=remove_all_white_spaces($range); - - } - } - return %ports; + my ($vdb,$top_module)=@_; + my %ports; + foreach my $sig (sort $vdb->get_modules_signals($top_module)) { + my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, + $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = + $vdb->get_module_signal($top_module,$sig); + if($type eq "input" or $type eq "inout" or $type eq "output" ){ + $ports{$sig}=remove_all_white_spaces($range); + } + } + return %ports; } - - sub get_param_list_in_order { - my $ref =shift; - return undef if (!defined $ref); - my %param=%{$ref}; - my @array = sort keys %param; - my $l= scalar @array; - SCAN: { - foreach my $i (0..($l-2)) { - my $str1=$array[$i]; - foreach my $j ($i+1..($l-1)) { - my $str2=$array[$j]; - if ($param{$str1} =~ /\b$str2\b/ ) { - - my $tmp = $array[$i]; - $array[$i] =$array[$j]; - $array[$j]=$tmp; - - redo SCAN; - } + my $ref =shift; + return undef if (!defined $ref); + my %param=%{$ref}; + my @array = sort keys %param; + my $l= scalar @array; + SCAN: { + foreach my $i (0..($l-2)) { + my $str1=$array[$i]; + foreach my $j ($i+1..($l-1)) { + my $str2=$array[$j]; + if ($param{$str1} =~ /\b$str2\b/ ) { + my $tmp = $array[$i]; + $array[$i] =$array[$j]; + $array[$j]=$tmp; + redo SCAN; + } + } + } } - } - } - - return @array; + return @array; } sub gen_verilator_makefile{ - my ($top_ref,$target_dir) =@_; - my %tops = %{$top_ref}; - my $p=''; - my $q=''; - my $h=''; - my $l; - my $lib_num=0; - my $all_lib=""; - foreach my $top (sort keys %tops) { - $p = "$p ${top}__ALL.a "; - $q = $q."lib$lib_num:\n\t\$(MAKE) -f ${top}.mk\n"; - $h = "$h ${top}.h "; - $l = $top; - $all_lib=$all_lib." lib$lib_num"; - $lib_num++; - } - - my $make= " - + my ($top_ref,$target_dir) =@_; + my %tops = %{$top_ref}; + my $p=''; + my $q=''; + my $h=''; + my $l; + my $lib_num=0; + my $all_lib=""; + foreach my $top (sort keys %tops) { + $p = "$p ${top}__ALL.a "; + $q = $q."lib$lib_num:\n\t\$(MAKE) -f ${top}.mk\n"; + $h = "$h ${top}.h "; + $l = $top; + $all_lib=$all_lib." lib$lib_num"; + $lib_num++; + } + my $make= " default: sim - - - include $l.mk lib: $all_lib - $q - ####################################################################### # Compile flags CPPFLAGS += -DVL_DEBUG=1 -ifeq (\$(CFG_WITH_CCWARN),yes) # Local... Else don't burden users +ifeq (\$(CFG_WITH_CCWARN),yes) # Local... Else don't burden users CPPFLAGS += -DVL_THREADED=1 CPPFLAGS += -W -Werror -Wall endif @@ -225,135 +190,112 @@ sub gen_verilator_makefile{ # Linking final exe -- presumes have a sim_main.cpp -sim: testbench.o \$(VK_GLOBAL_OBJS) $p \$(SLIB) - \$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 -lpthread 2>&1 | c++filt +sim: testbench.o \$(VK_GLOBAL_OBJS) $p \$(SLIB) +\t\$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 -lpthread 2>&1 | c++filt testbench.o: testbench.cpp $h \$(HLIB) clean: - rm *.o *.a testbench +\trm *.o *.a testbench "; save_file ($target_dir,$make); - -} +} #################### -# file +# file ################## - - sub append_text_to_file { - my ($file_path,$text)=@_; - open(my $fd, ">>$file_path") or die "could not open $file_path: $!"; - print $fd $text; - close $fd; + my ($file_path,$text)=@_; + open(my $fd, ">>$file_path") or die "could not open $file_path: $!"; + print $fd $text; + close $fd; } - - - sub save_file { - my ($file_path,$text)=@_; - open my $fd, ">$file_path" or die "could not open $file_path: $!"; - print $fd $text; - close $fd; + my ($file_path,$text)=@_; + open my $fd, ">$file_path" or die "could not open $file_path: $!"; + print $fd $text; + close $fd; } sub load_file { - my $file_path=shift; - my $str; - if (-f "$file_path") { - - $str = do { - local $/ = undef; - open my $fh, "<", $file_path - or die "could not open $file_path: $!"; - <$fh>; - }; - - } - return $str; + my $file_path=shift; + my $str; + if (-f "$file_path") { + $str = do { + local $/ = undef; + open my $fh, "<", $file_path or die "could not open $file_path: $!"; + <$fh>; + }; + } + return $str; } sub merg_files { - my ($source_file_path,$dest_file_path)=@_; - local $/=undef; - open FILE, $source_file_path or die "Couldn't open file: $!"; - my $string = ; - close FILE; - append_text_to_file ($dest_file_path,$string); + my ($source_file_path,$dest_file_path)=@_; + local $/=undef; + open FILE, $source_file_path or die "Couldn't open file: $!"; + my $string = ; + close FILE; + append_text_to_file ($dest_file_path,$string); } - - sub copy_file_and_folders{ - my ($file_ref,$project_dir,$target_dir)=@_; - - foreach my $f(@{$file_ref}){ - my $name= basename($f); - - my $n="$project_dir$f"; - if (-f "$n") { #copy file - copy ("$n","$target_dir/$name"); - }elsif(-f "$f" ){ - copy ("$f","$target_dir/$name"); - }elsif (-d "$n") {#copy folder - dircopy ("$n","$target_dir/$name"); - }elsif(-d "$f" ){ - dircopy ("$f","$target_dir/$name"); - - } - } - + my ($file_ref,$project_dir,$target_dir)=@_; + foreach my $f(@{$file_ref}){ + my $name= basename($f); + my $n="$project_dir$f"; + if (-f "$n") { #copy file + copy ("$n","$target_dir/$name"); + }elsif(-f "$f" ){ + copy ("$f","$target_dir/$name"); + }elsif (-d "$n") {#copy folder + dircopy ("$n","$target_dir/$name"); + }elsif(-d "$f" ){ + dircopy ("$f","$target_dir/$name"); + } + } } - sub remove_file_and_folders{ - my ($file_ref,$project_dir)=@_; - - foreach my $f(@{$file_ref}){ - my $name= basename($f); - my $n="$project_dir$f"; - if (-f "$n") { #copy file - unlink ("$n"); - }elsif(-f "$f" ){ - unlink ("$f"); - }elsif (-d "$n") {#copy folder - rmtree ("$n"); - }elsif(-d "$f" ){ - rmtree ("$f"); - } - } - + my ($file_ref,$project_dir)=@_; + foreach my $f(@{$file_ref}){ + my $name= basename($f); + my $n="$project_dir$f"; + if (-f "$n") { #copy file + unlink ("$n"); + }elsif(-f "$f" ){ + unlink ("$f"); + }elsif (-d "$n") {#copy folder + rmtree ("$n"); + }elsif(-d "$f" ){ + rmtree ("$f"); + } + } } sub read_file_cntent { - my ($f,$project_dir)=@_; - my $n="$project_dir$f"; - my $str; - if (-f "$n") { - - $str = do { - local $/ = undef; - open my $fh, "<", $n - or die "could not open $n: $!"; - <$fh>; - }; - - }elsif(-f "$f" ){ - $str = do { - local $/ = undef; - open my $fh, "<", $f - or die "could not open $f: $!"; - <$fh>; - }; - - - } - return $str; - + my ($f,$project_dir)=@_; + my $n="$project_dir$f"; + my $str; + if (-f "$n") { + $str = do { + local $/ = undef; + open my $fh, "<", $n + or die "could not open $n: $!"; + <$fh>; + }; + }elsif(-f "$f" ){ + $str = do { + local $/ = undef; + open my $fh, "<", $f + or die "could not open $f: $!"; + <$fh>; + }; + } + return $str; } @@ -362,9 +304,9 @@ sub check_file_has_string { my $r; open(FILE,$file); if (grep{/$string/} ){ - $r= 1; #print "word found\n"; + $r= 1; #print "word found\n"; }else{ - $r= 0; #print "word not found\n"; + $r= 0; #print "word not found\n"; } close FILE; return $r; @@ -372,11 +314,11 @@ sub check_file_has_string { #return lines containig pattern in a givn file sub unix_grep { - my ($file,$pattern)=@_; + my ($file,$pattern)=@_; open(FILE,$file); my @arr = ; my @lines = grep /$pattern/, @arr; - return @lines; + return @lines; } @@ -385,74 +327,61 @@ sub count_file_line_num { open(FILE,$file); my $n=0; while (my $line = ) { - $n++; - } + $n++; + } close FILE; return $n; } sub set_path_env{ - my $project_dir = get_project_dir(); #mpsoc dir addr - my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; - #print "$paths_file\n"; - my $paths= do $paths_file; - my $pronoc_work =object_get_attribute($paths,"PATH","PRONOC_WORK"); - my $quartus = object_get_attribute($paths,"PATH","QUARTUS_BIN"); - my $vivado = object_get_attribute($paths,"PATH","VIVADO_BIN"); - my $sdk = object_get_attribute($paths,"PATH","SDK_BIN"); - - my $modelsim = object_get_attribute($paths,"PATH","MODELSIM_BIN"); - $ENV{'PRONOC_WORK'}= $pronoc_work if( defined $pronoc_work); - $ENV{'QUARTUS_BIN'}= $quartus if( defined $quartus); - $ENV{'VIVADO_BIN'}= $vivado if( defined $vivado); - $ENV{'SDK_BIN'}= $vivado if( defined $sdk); - $ENV{'MODELSIM_BIN'}= $modelsim if( defined $modelsim); - - if( defined $pronoc_work){if(-d $pronoc_work ){ - mkpath("$pronoc_work/emulate",1,01777) unless -d "$pronoc_work/emulate"; - mkpath("$pronoc_work/simulate",1,01777) unless -d "$pronoc_work/simulate"; - mkpath("$pronoc_work/tmp",1,01777) unless -d "$pronoc_work/tmp"; - }} - - #add quartus_bin to PATH linux environment if it does not exist in PATH - my $add; - if( defined $quartus){ - my @q =split (/:/,$ENV{'PATH'}); - my $p=get_scolar_pos ($quartus,@q); - $ENV{'PATH'}= $ENV{'PATH'}.":$quartus" unless ( defined $p); - $add=(defined $add)? $add.":$quartus" : $quartus unless ( defined $p); - - } - - if( defined $vivado){ - my @q =split (/:/,$ENV{'PATH'}); - my $p=get_scolar_pos ($vivado,@q); - $ENV{'PATH'}= $ENV{'PATH'}.":$vivado" unless ( defined $p); - $add=(defined $add)? $add.":$vivado" : $vivado unless ( defined $p); - - } - - if( defined $sdk){ - my @q =split (/:/,$ENV{'PATH'}); - my $p=get_scolar_pos ($sdk,@q); - $ENV{'PATH'}= $ENV{'PATH'}.":$sdk" unless ( defined $p); - $add=(defined $add)? $add.":$sdk" : $sdk unless ( defined $p); - - } - if(defined $add){ - print GREEN, "Info: $add has been added to linux PATH envirement.\n",RESET,"\n"; - - } - - + my $project_dir = get_project_dir(); #mpsoc dir addr + my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; + #print "$paths_file\n"; + my $paths= do $paths_file; + my $pronoc_work =object_get_attribute($paths,"PATH","PRONOC_WORK"); + my $quartus = object_get_attribute($paths,"PATH","QUARTUS_BIN"); + my $vivado = object_get_attribute($paths,"PATH","VIVADO_BIN"); + my $sdk = object_get_attribute($paths,"PATH","SDK_BIN"); + my $modelsim = object_get_attribute($paths,"PATH","MODELSIM_BIN"); + $ENV{'PRONOC_WORK'}= $pronoc_work if( defined $pronoc_work); + $ENV{'QUARTUS_BIN'}= $quartus if( defined $quartus); + $ENV{'VIVADO_BIN'}= $vivado if( defined $vivado); + $ENV{'SDK_BIN'}= $vivado if( defined $sdk); + $ENV{'MODELSIM_BIN'}= $modelsim if( defined $modelsim); + if( defined $pronoc_work){if(-d $pronoc_work ){ + mkpath("$pronoc_work/emulate",1,01777) unless -d "$pronoc_work/emulate"; + mkpath("$pronoc_work/simulate",1,01777) unless -d "$pronoc_work/simulate"; + mkpath("$pronoc_work/tmp",1,01777) unless -d "$pronoc_work/tmp"; + }} + #add quartus_bin to PATH linux environment if it does not exist in PATH + my $add; + if( defined $quartus){ + my @q =split (/:/,$ENV{'PATH'}); + my $p=get_scolar_pos ($quartus,@q); + $ENV{'PATH'}= $ENV{'PATH'}.":$quartus" unless ( defined $p); + $add=(defined $add)? $add.":$quartus" : $quartus unless ( defined $p); + } + if( defined $vivado){ + my @q =split (/:/,$ENV{'PATH'}); + my $p=get_scolar_pos ($vivado,@q); + $ENV{'PATH'}= $ENV{'PATH'}.":$vivado" unless ( defined $p); + $add=(defined $add)? $add.":$vivado" : $vivado unless ( defined $p); + } + if( defined $sdk){ + my @q =split (/:/,$ENV{'PATH'}); + my $p=get_scolar_pos ($sdk,@q); + $ENV{'PATH'}= $ENV{'PATH'}.":$sdk" unless ( defined $p); + $add=(defined $add)? $add.":$sdk" : $sdk unless ( defined $p); + } + if(defined $add){ + print GREEN, "Info: $add has been added to linux PATH envirement.\n",RESET,"\n"; + } } - sub source_file { my $file = shift; open my $fh, "<", $file or return "could not open $file: $!"; - while (<$fh>) { chomp; #FIXME: this regex isn't quite good enough @@ -462,176 +391,119 @@ sub source_file { return undef; } - -############## -# clone_obj -############# - -sub clone_obj{ - my ($self,$clone)=@_; - - foreach my $p (keys %$self){ - delete ($self->{$p}); - } - foreach my $p (keys %$clone){ - $self->{$p}= $clone->{$p}; - my $ref= ref ($clone->{$p}); - if( $ref eq 'HASH' ){ - - foreach my $q (keys %{$clone->{$p}}){ - $self->{$p}{$q}= $clone->{$p}{$q}; - my $ref= ref ($self->{$p}{$q}); - if( $ref eq 'HASH' ){ - - foreach my $z (keys %{$clone->{$p}{$q}}){ - $self->{$p}{$q}{$z}= $clone->{$p}{$q}{$z}; - my $ref= ref ($self->{$p}{$q}{$z}); - if( $ref eq 'HASH' ){ - - foreach my $w (keys %{$clone->{$p}{$q}{$z}}){ - $self->{$p}{$q}{$z}{$w}= $clone->{$p}{$q}{$z}{$w}; - my $ref= ref ($self->{$p}{$q}{$z}{$w}); - if( $ref eq 'HASH' ){ - - - foreach my $m (keys %{$clone->{$p}{$q}{$z}{$w}}){ - $self->{$p}{$q}{$z}{$w}{$m}= $clone->{$p}{$q}{$z}{$w}{$m}; - my $ref= ref ($self->{$p}{$q}{$z}{$w}{$m}); - if( $ref eq 'HASH' ){ - - foreach my $n (keys %{$clone->{$p}{$q}{$z}{$w}{$m}}){ - $self->{$p}{$q}{$z}{$w}{$m}{$n}= $clone->{$p}{$q}{$z}{$w}{$m}{$n}; - my $ref= ref ($self->{$p}{$q}{$z}{$w}{$m}{$n}); - if( $ref eq 'HASH' ){ - - foreach my $l (keys %{$clone->{$p}{$q}{$z}{$w}{$m}{$n}}){ - $self->{$p}{$q}{$z}{$w}{$m}{$n}{$l}= $clone->{$p}{$q}{$z}{$w}{$m}{$n}{$l}; - my $ref= ref ($self->{$p}{$q}{$z}{$w}{$m}{$n}{$l}); - if( $ref eq 'HASH' ){ - } - } - - }#if - }#n - }#if - }#m - }#if - }#w - }#if - }#z - }#if - }#q - }#if - }#p -}#sub - +sub clone_obj { + my ($self, $clone) = @_; + # Clear the object + %$self = (); + # Recursively copy the structure + sub deep_clone { + my $src = shift; + return { map { $_ => (ref $src->{$_} eq 'HASH' ? deep_clone($src->{$_}) : $src->{$_}) } keys %$src }; + } + %$self = %{ deep_clone($clone) }; +} sub get_project_dir{ #mpsoc directory address - my $dir = Cwd::getcwd(); - my @p= split('/perl_gui',$dir); - @p= split('/Integration_test',$p[0]); - my $d = abs_path("$p[0]/../"); - - return $d; + my $dir = Cwd::getcwd(); + my @p= split('/perl_gui',$dir); + @p= split('/Integration_test',$p[0]); + my $d = abs_path("$p[0]/../"); + return $d; } sub cut_dir_path{ - my ($dir,$folder_name) = @_; - my @p= split (/\/$folder_name\//,$dir); - return $p[-1]; + my ($dir,$folder_name) = @_; + my @p= split (/\/$folder_name\//,$dir); + return $p[-1]; } - sub remove_project_dir_from_addr{ - my $file=shift; - my $project_dir = get_project_dir(); - $file =~ s/$project_dir//; - return $file; + my $file=shift; + my $project_dir = get_project_dir(); + $file =~ s/$project_dir//; + return $file; } sub add_project_dir_to_addr{ - my $file=shift; - my $project_dir = get_project_dir(); - return $file if(-f $file ); - return "$project_dir/$file"; - + my $file=shift; + my $project_dir = get_project_dir(); + return $file if(-f $file ); + return "$project_dir/$file"; + } sub get_full_path_addr{ - my $file=shift; - my $dir = Cwd::getcwd(); - my $full_path = "$dir/$file"; - return $full_path if -f ($full_path ); - return $file; + my $file=shift; + my $dir = Cwd::getcwd(); + my $full_path = "$dir/$file"; + return $full_path if -f ($full_path ); + return $file; } sub regen_object { - my $path=shift; - $path = get_full_path_addr($path); - my $pp= eval { do $path }; - my $r= ($@ || !defined $pp); - return ($pp,$r,$@); + my $path=shift; + $path = get_full_path_addr($path); + my $pp= eval { do $path }; + my $r= ($@ || !defined $pp); + return ($pp,$r,$@); } ################ -# general +# general ################# - sub remove_not_hex { - my $s=shift; - $s =~ s/[^0-9a-fA-F]//g; - return $s; + my $s=shift; + $s =~ s/[^0-9a-fA-F]//g; + return $s; } sub remove_not_number { - my $s=shift; - $s =~ s/[^0-9]//g; - return $s; - + my $s=shift; + $s =~ s/[^0-9]//g; + return $s; } sub trim { my $s = shift; $s=~s/[\n]//gs; return $s }; sub remove_all_white_spaces($) { - my $string = shift; - $string =~ s/\s+//g; - return $string; + my $string = shift; + $string =~ s/\s+//g; + return $string; } sub check_scolar_exist_in_array{ - my ($value,$ref)=@_; - my @array= @{$ref}; - if ( grep( /^\Q$value\E$/, @array ) ) { - return 1; - } - return 0 + my ($value,$ref)=@_; + my @array= @{$ref}; + if ( grep( /^\Q$value\E$/, @array ) ) { + return 1; + } + return 0 } sub get_item_pos{#if not in return 0 - my ($item,@list)=@_; - my $pos=0; - foreach my $p (@list){ - #print "$p eq $item\n"; - if ($p eq $item){return $pos;} - $pos++; - } - return 0; - -} + my ($item,@list)=@_; + my $pos=0; + foreach my $p (@list){ + #print "$p eq $item\n"; + if ($p eq $item){return $pos;} + $pos++; + } + return 0; +} sub get_scolar_pos{ - my ($item,@list)=@_; - my $pos; - my $i=0; - foreach my $c (@list) - { - if( $c eq $item) {$pos=$i} - $i++; - } - return $pos; + my ($item,@list)=@_; + my $pos; + my $i=0; + foreach my $c (@list) + { + if( $c eq $item) {$pos=$i} + $i++; + } + return $pos; } sub get_pos{ @@ -641,738 +513,658 @@ sub get_pos{ #print "$p eq $item\n"; if ($p eq $item){return $pos;} $pos++; - } + } return undef; -} +} sub remove_scolar_from_array{ - my ($array_ref,$item)=@_; - my @array=@{$array_ref}; - my @new; - foreach my $p (@array){ - if($p ne $item ){ - push(@new,$p); - } - } - return @new; + my ($array_ref,$item)=@_; + my @array=@{$array_ref}; + my @new; + foreach my $p (@array){ + if($p ne $item ){ + push(@new,$p); + } + } + return @new; } sub replace_in_array{ - my ($array_ref,$item1,$item2)=@_; - my @array=@{$array_ref}; - my @new; - foreach my $p (@array){ - if($p eq $item1 ){ - push(@new,$item2); - }else{ - push(@new,$p); - } - } - return @new; + my ($array_ref,$item1,$item2)=@_; + my @array=@{$array_ref}; + my @new; + foreach my $p (@array){ + if($p eq $item1 ){ + push(@new,$item2); + }else{ + push(@new,$p); + } + } + return @new; } - - # return an array of common elemnts between two input arays sub get_common_array{ - my ($a_ref,$b_ref)=@_; - my @A=@{$a_ref}; - my @B=@{$b_ref}; - my @C; - foreach my $p (@A){ - if( grep (/^\Q$p\E$/,@B)){push(@C,$p)}; - } - return @C; + my ($a_ref,$b_ref)=@_; + my @A=@{$a_ref}; + my @B=@{$b_ref}; + my @C; + foreach my $p (@A){ + if( grep (/^\Q$p\E$/,@B)){push(@C,$p)}; + } + return @C; } #a-b sub get_diff_array{ - my ($a_ref,$b_ref)=@_; - my @A=@{$a_ref}; - my @B=@{$b_ref}; - my @C; - foreach my $p (@A){ - if( !grep (/^\Q$p\E$/,@B)){push(@C,$p)}; - } - return @C; - + my ($a_ref,$b_ref)=@_; + my @A=@{$a_ref}; + my @B=@{$b_ref}; + my @C; + foreach my $p (@A){ + if( !grep (/^\Q$p\E$/,@B)){push(@C,$p)}; + } + return @C; + } sub return_not_unique_names_in_array{ - my @array = @_; - my %seen; - my @r; - foreach my $value (@array) { - if (! $seen{$value}) { - $seen{$value} = 1; - }else{ - push(@r,$value); - } - } - return @r; + my @array = @_; + my %seen; + my @r; + foreach my $value (@array) { + if (! $seen{$value}) { + $seen{$value} = 1; + }else{ + push(@r,$value); + } + } + return @r; } - sub compress_nums{ - my @nums=@_; - my @f=sort { $a <=> $b } @nums; - my $s; - my $ls; - my $range=0; - my $x; - - - foreach my $p (@f){ - if(!defined $x) { - $s="$p"; - $ls=$p; - - } - else{ - if($p-$x>1){ #gap exist - if( $range){ - $s=($x-$ls>1 )? "$s:$x,$p": "$s,$x,$p"; - $ls=$p; - $range=0; - }else{ - $s= "$s,$p"; - $ls=$p; - - } - - }else {$range=1;} - - - - } - - $x=$p - } - if($range==1){ $s= ($x-$ls>1 )? "$s:$x": "$s,$x";} - #update $s($ls,$hs); - - return $s; - + my @nums=@_; + my @f=sort { $a <=> $b } @nums; + my $s; + my $ls; + my $range=0; + my $x; + foreach my $p (@f){ + if(!defined $x) { + $s="$p"; + $ls=$p; + } + else{ + if($p-$x>1){ #gap exist + if( $range){ + $s=($x-$ls>1 )? "$s:$x,$p": "$s,$x,$p"; + $ls=$p; + $range=0; + }else{ + $s= "$s,$p"; + $ls=$p; + } + }else {$range=1;} + } + $x=$p + } + if($range==1){ $s= ($x-$ls>1 )? "$s:$x": "$s,$x";} + #update $s($ls,$hs); + return $s; } - - sub metric_conversion{ - my $size=shift; - my $size_text= $size<=0 ? 'Error ': - $size<(1 << 10)? $size: - $size<(1 << 20)? join (' ', ($size>>10,"K")) : - $size<(1 << 30)? join (' ', ($size>>20,"M")) : - join (' ', ($size>>30,"G")) ; + my $size=shift; + my $size_text= $size<=0 ? 'Error ': + $size<(1 << 10)? $size: + $size<(1 << 20)? join (' ', ($size>>10,"K")) : + $size<(1 << 30)? join (' ', ($size>>20,"M")) : + join (' ', ($size>>30,"G")) ; return $size_text; } - - - - ###### # state ##### sub set_gui_status{ - my ($object,$status,$timeout)=@_; - $object->object_add_attribute('gui_status','status',$status); - $object->object_add_attribute('gui_status','timeout',$timeout); -} - + my ($object,$status,$timeout)=@_; + $object->object_add_attribute('gui_status','status',$status); + $object->object_add_attribute('gui_status','timeout',$timeout); +} sub get_gui_status{ - my ($object)=@_; - my $status= $object->object_get_attribute('gui_status','status'); - my $timeout=$object->object_get_attribute('gui_status','timeout'); - return ($status,$timeout); + my ($object)=@_; + my $status= $object->object_get_attribute('gui_status','status'); + my $timeout=$object->object_get_attribute('gui_status','timeout'); + return ($status,$timeout); } - - ########### # color ######### - - - sub get_color { - my $num=shift; - - my @colors=( - 0x6495ED,#Cornflower Blue - 0xFAEBD7,#Antiquewhite - 0xC71585,#Violet Red - 0xC0C0C0,#silver - 0xADD8E6,#Lightblue - 0x6A5ACD,#Slate Blue - 0x00CED1,#Dark Turquoise - 0x008080,#Teal - 0x2E8B57,#SeaGreen - 0xFFB6C1,#Light Pink - 0x008000,#Green - 0xFF0000,#red - 0x808080,#Gray - 0x808000,#Olive - 0xFF69B4,#Hot Pink - 0xFFD700,#Gold - 0xDAA520,#Goldenrod - 0xFFA500,#Orange - 0x32CD32,#LimeGreen - 0x0000FF,#Blue - 0xFF8C00,#DarkOrange - 0xA0522D,#Sienna - 0xFF6347,#Tomato - 0x0000CD,#Medium Blue - 0xFF4500,#OrangeRed - 0xDC143C,#Crimson - 0x9932CC,#Dark Orchid - 0x800000,#marron - 0x800080,#Purple - 0x4B0082,#Indigo - 0xFFFFFF,#white - 0x000000, #Black - #heatmap - 0xbdff00, # (189,255,0) - 0xe3f018, # (227,240,24) - 0xffce00, # (255,206,0) - 0xff6612, # (255,102,18) - 0xc12424, # (193,36,36) - ); - - my $color= ($num< scalar (@colors))? $colors[$num]: 0xFFFFFF; - my $red= ($color & 0xFF0000) >> 8; - my $green= ($color & 0x00FF00); - my $blue= ($color & 0x0000FF) << 8; - - return ($red,$green,$blue); - + my $num=shift; + my @colors=( + 0x6495ED,#Cornflower Blue + 0xFAEBD7,#Antiquewhite + 0xC71585,#Violet Red + 0xC0C0C0,#silver + 0xADD8E6,#Lightblue + 0x6A5ACD,#Slate Blue + 0x00CED1,#Dark Turquoise + 0x008080,#Teal + 0x2E8B57,#SeaGreen + 0xFFB6C1,#Light Pink + 0x008000,#Green + 0xFF0000,#red + 0x808080,#Gray + 0x808000,#Olive + 0xFF69B4,#Hot Pink + 0xFFD700,#Gold + 0xDAA520,#Goldenrod + 0xFFA500,#Orange + 0x32CD32,#LimeGreen + 0x0000FF,#Blue + 0xFF8C00,#DarkOrange + 0xA0522D,#Sienna + 0xFF6347,#Tomato + 0x0000CD,#Medium Blue + 0xFF4500,#OrangeRed + 0xDC143C,#Crimson + 0x9932CC,#Dark Orchid + 0x800000,#marron + 0x800080,#Purple + 0x4B0082,#Indigo + 0xFFFFFF,#white + 0x000000, #Black + #heatmap + 0xbdff00, # (189,255,0) + 0xe3f018, # (227,240,24) + 0xffce00, # (255,206,0) + 0xff6612, # (255,102,18) + 0xc12424, # (193,36,36) + ); + + my $color= ($num< scalar (@colors))? $colors[$num]: 0xFFFFFF; + my $red= ($color & 0xFF0000) >> 8; + my $green= ($color & 0x00FF00); + my $blue= ($color & 0x0000FF) << 8; + return ($red,$green,$blue); } - sub get_color_hex_string { - my $num=shift; - - my @colors=( - "6495ED",#Cornflower Blue - "FAEBD7",#Antiquewhite - "C71585",#Violet Red - "C0C0C0",#silver - "ADD8E6",#Lightblue - "6A5ACD",#Slate Blue - "00CED1",#Dark Turquoise - "008080",#Teal - "2E8B57",#SeaGreen - "FFB6C1",#Light Pink - "008000",#Green - "FF0000",#red - "808080",#Gray - "808000",#Olive - "FF69B4",#Hot Pink - "FFD700",#Gold - "DAA520",#Goldenrod - "FFA500",#Orange - "32CD32",#LimeGreen - "0000FF",#Blue - "FF8C00",#DarkOrange - "A0522D",#Sienna - "FF6347",#Tomato - "0000CD",#Medium Blue - "FF4500",#OrangeRed - "DC143C",#Crimson - "9932CC",#Dark Orchid - "800000",#marron - "800080",#Purple - "4B0082",#Indigo - "FFFFFF",#white - "000000", #Black - #heatmap - "bdff00", # (189,255,0) - "e3f018", # (227,240,24) - "ffce00", # (255,206,0) - "ff6612", # (255,102,18) - "c12424", # (193,36,36) - - - ); - - my $color= ($num< scalar (@colors))? $colors[$num]: "FFFFFF"; - return $color; - + my $num=shift; + my @colors=( + "6495ED",#Cornflower Blue + "FAEBD7",#Antiquewhite + "C71585",#Violet Red + "C0C0C0",#silver + "ADD8E6",#Lightblue + "6A5ACD",#Slate Blue + "00CED1",#Dark Turquoise + "008080",#Teal + "2E8B57",#SeaGreen + "FFB6C1",#Light Pink + "008000",#Green + "FF0000",#red + "808080",#Gray + "808000",#Olive + "FF69B4",#Hot Pink + "FFD700",#Gold + "DAA520",#Goldenrod + "FFA500",#Orange + "32CD32",#LimeGreen + "0000FF",#Blue + "FF8C00",#DarkOrange + "A0522D",#Sienna + "FF6347",#Tomato + "0000CD",#Medium Blue + "FF4500",#OrangeRed + "DC143C",#Crimson + "9932CC",#Dark Orchid + "800000",#marron + "800080",#Purple + "4B0082",#Indigo + "FFFFFF",#white + "000000", #Black + #heatmap + "bdff00", # (189,255,0) + "e3f018", # (227,240,24) + "ffce00", # (255,206,0) + "ff6612", # (255,102,18) + "c12424", # (193,36,36) + ); + my $color= ($num< scalar (@colors))? $colors[$num]: "FFFFFF"; + return $color; } - - - sub check_verilog_identifier_syntax { - my $in=shift; - my $error=0; - my $message=''; + my $in=shift; + my $error=0; + my $message=''; #check if $in is defined - if(!defined $in){ - return "Identifier is not defined! An Identifier must begin with an alphabetic character.\n"; - } + if(!defined $in){ + return "Identifier is not defined! An Identifier must begin with an alphabetic character.\n"; + } - if(length $in ==0){ - return "Identifier length is zero! An Identifier must begin with an alphabetic character.\n"; - } + if(length $in ==0){ + return "Identifier length is zero! An Identifier must begin with an alphabetic character.\n"; + } # an Identifiers must begin with an alphabetic character or the underscore character - if ($in =~ /^[0-9\$]/){ - return "An Identifier must begin with an alphabetic character or the underscore character.\n"; - } - - -# Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ $ ) - if ($in =~ /[^a-zA-Z0-9_\$]+/){ - #print "use of illegal character after\n" ; - my @w= split /([^a-zA-Z0-9_\$]+)/, $in; - return "Contain illegal character of \"$w[1]\" after $w[0]. Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ \$ )\n"; - - } + if ($in =~ /^[0-9\$]/){ + return "An Identifier must begin with an alphabetic character or the underscore character.\n"; + } + +# Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ $ ) + if ($in =~ /[^a-zA-Z0-9_\$]+/){ + #print "use of illegal character after\n" ; + my @w= split /([^a-zA-Z0-9_\$]+)/, $in; + return "Contain illegal character of \"$w[1]\" after $w[0]. Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ \$ )\n"; + } # check Verilog reserved words - my @keys = ("always","and","assign","automatic","begin","buf","bufif0","bufif1","case","casex","casez","cell","cmos","config","deassign","default","defparam","design","disable","edge","else","end","endcase","endconfig","endfunction","endgenerate","endmodule","endprimitive","endspecify","endtable","endtask","event","for","force","forever","fork","function","generate","genvar","highz0","highz1","if","ifnone","incdir","include","initial","inout","input","instance","integer","join","large","liblist","library","localparam","macromodule","medium","module","nand","negedge","nmos","nor","noshowcancelled","not","notif0","notif1","or","output","parameter","pmos","posedge","primitive","pull0","pull1","pulldown","pullup","pulsestyle_onevent","pulsestyle_ondetect","remos","real","realtime","reg","release","repeat","rnmos","rpmos","rtran","rtranif0","rtranif1","scalared","showcancelled","signed","small","specify","specparam","strong0","strong1","supply0","supply1","table","task","time","tran","tranif0","tranif1","tri","tri0","tri1","triand","trior","trireg","unsigned","use","vectored","wait","wand","weak0","weak1","while","wire","wor","xnor","xor"); - if( grep (/^$in$/,@keys)){ - return "$in is a Verlig reserved word.\n"; - } - return undef; - + my @keys = ("always","and","assign","automatic","begin","buf","bufif0","bufif1","case","casex","casez","cell","cmos","config","deassign","default","defparam","design","disable","edge","else","end","endcase","endconfig","endfunction","endgenerate","endmodule","endprimitive","endspecify","endtable","endtask","event","for","force","forever","fork","function","generate","genvar","highz0","highz1","if","ifnone","incdir","include","initial","inout","input","instance","integer","join","large","liblist","library","localparam","macromodule","medium","module","nand","negedge","nmos","nor","noshowcancelled","not","notif0","notif1","or","output","parameter","pmos","posedge","primitive","pull0","pull1","pulldown","pullup","pulsestyle_onevent","pulsestyle_ondetect","remos","real","realtime","reg","release","repeat","rnmos","rpmos","rtran","rtranif0","rtranif1","scalared","showcancelled","signed","small","specify","specparam","strong0","strong1","supply0","supply1","table","task","time","tran","tranif0","tranif1","tri","tri0","tri1","triand","trior","trireg","unsigned","use","vectored","wait","wand","weak0","weak1","while","wire","wor","xnor","xor"); + if( grep (/^$in$/,@keys)){ + return "$in is a Verlig reserved word.\n"; + } + return undef; } - sub capture_number_after { - my ($after,$text)=@_; - my @q =split (/$after/,$text); - #my $d=$q[1]; - my @d = split (/[^0-9. ]/,$q[1]); - return $d[0]; - + my ($after,$text)=@_; + my @q =split (/$after/,$text); + #my $d=$q[1]; + my @d = split (/[^0-9. ]/,$q[1]); + return $d[0]; } sub capture_string_between { - my ($start,$text,$end)=@_; - my @q =split (/$start/,$text); - my @d = split (/$end/,$q[1]); - return $d[0]; + my ($start,$text,$end)=@_; + my @q =split (/$start/,$text); + my @d = split (/$end/,$q[1]); + return $d[0]; } sub capture_cores_data { - my ($data,$text)=@_; - my %result; - my @q =split (/End_point/,$text); - my $i=0; - foreach my $p (@q){ - if ($i!=0){ - my @d = split (/[^0-9. ]/,$p); - my $n= $d[0]; - my $val = capture_number_after("$data",$p); - $result{remove_all_white_spaces($n)}=remove_all_white_spaces($val); - } - $i++; - } - return %result; + my ($data,$text)=@_; + my %result; + my @q =split (/End_point/,$text); + my $i=0; + foreach my $p (@q){ + if ($i!=0){ + my @d = split (/[^0-9. ]/,$p); + my $n= $d[0]; + my $val = capture_number_after("$data",$p); + $result{remove_all_white_spaces($n)}=remove_all_white_spaces($val); + } + $i++; + } + return %result; } sub make_undef_as_string { - foreach my $p (@_){ - $$p= 'undef' if (! defined $$p); - - } + foreach my $p (@_){ + $$p= 'undef' if (! defined $$p); + + } } sub powi{ # x^y - my ($x,$y)=@_; # compute x to the y - my $r=1; - for (my $i = 0; $i < $y; ++$i ) { - $r *= $x; - } - return $r; + my ($x,$y)=@_; # compute x to the y + my $r=1; + for (my $i = 0; $i < $y; ++$i ) { + $r *= $x; + } + return $r; } sub sum_powi{ # x^(y-1) + x^(y-2) + ...+ 1; - my ($x,$y)=@_; # compute x to the y - my $r = 0; + my ($x,$y)=@_; # compute x to the y + my $r = 0; for (my $i = 0; $i < $y; $i++){ - $r += powi( $x, $i ); + $r += powi( $x, $i ); } - return $r; -} - - - + return $r; +} ############# # object ############ - sub object_add_attribute{ - my ($self,$attribute1,$attribute2,$value)=@_; - if(!defined $attribute2){$self->{$attribute1}=$value;} - else {$self->{$attribute1}{$attribute2}=$value;} - + my ($self,$attribute1,$attribute2,$value)=@_; + if(!defined $attribute2){$self->{$attribute1}=$value;} + else {$self->{$attribute1}{$attribute2}=$value;} } - - sub object_get_attribute{ - my ($self,$attribute1,$attribute2)=@_; - if(!defined $attribute2) {return $self->{$attribute1};} - return $self->{$attribute1}{$attribute2}; + my ($self,$attribute1,$attribute2)=@_; + if(!defined $attribute2) {return $self->{$attribute1};} + return $self->{$attribute1}{$attribute2}; } sub object_add_attribute_order{ - my ($self,$attribute,@param)=@_; - my $r = $self->{'parameters_order'}{$attribute}; - my @a; - @a = @{$r} if(defined $r); - push (@a,@param); - @a=uniq(@a); - $self->{'parameters_order'}{$attribute} =\@a; + my ($self,$attribute,@param)=@_; + my $r = $self->{'parameters_order'}{$attribute}; + my @a; + @a = @{$r} if(defined $r); + push (@a,@param); + @a=uniq(@a); + $self->{'parameters_order'}{$attribute} =\@a; } sub object_remove_attribute_order{ - my ($self,$attribute,$param)=@_; - my @r=@{$self->{parameters_order}{$attribute}}; - my @n; - foreach my $p(@r){ - if( $p ne $param) {push(@n,$p)}; - - } - $self->{parameters_order}{$attribute}=\@n; - + my ($self,$attribute,$param)=@_; + my @r=@{$self->{parameters_order}{$attribute}}; + my @n; + foreach my $p(@r){ + if( $p ne $param) {push(@n,$p)}; + } + $self->{parameters_order}{$attribute}=\@n; } sub object_get_attribute_order{ - my ($self,$attribute)=@_; - return unless(defined $self->{parameters_order}{$attribute}); - my @order=@{$self->{parameters_order}{$attribute}}; - return uniq(@order) + my ($self,$attribute)=@_; + return unless(defined $self->{parameters_order}{$attribute}); + my @order=@{$self->{parameters_order}{$attribute}}; + return uniq(@order) } sub object_remove_attribute{ - my ($self,$attribute1,$attribute2)=@_; - if(!defined $attribute2){ - delete $self->{$attribute1} if ( exists( $self->{$attribute1})); - } - else { - delete $self->{$attribute1}{$attribute2} if ( exists( $self->{$attribute1}{$attribute2})); ; - } + my ($self,$attribute1,$attribute2)=@_; + if(!defined $attribute2){ + delete $self->{$attribute1} if ( exists( $self->{$attribute1})); + } + else { + delete $self->{$attribute1}{$attribute2} if ( exists( $self->{$attribute1}{$attribute2})); ; + } } ############# # graphviz ############# - - sub generate_and_show_graph_using_graphviz { - my ($self,$scrolled_win,$dotfile, $graph_name)=@_; - - - #empty the scrolled win - if(defined $scrolled_win){ - my @list = $scrolled_win->get_children(); - foreach my $l (@list){ - $scrolled_win->remove($l); - } - } - - my $scale=$self->object_get_attribute($graph_name,"scale"); - $scale= 1 if (!defined $scale); - my $diagram; - - my $cmd = "echo \'$dotfile\' | dot -Tpng -q"; - my ($stdout,$exit,$stderr)= run_cmd_in_back_ground_get_stdout ($cmd); - if ( length( $stderr || '' ) !=0) { - message_dialog("$stderr\nHave you installed graphviz? If not run \n \t \"sudo apt-get install graphviz\" \n in terminal",'error'); - } - $diagram =open_inline_image( $stdout,70*$scale,70*$scale,'percent'); - if(defined $scrolled_win){ - add_widget_to_scrolled_win($diagram,$scrolled_win); - $scrolled_win->show_all(); - } + my ($self,$scrolled_win,$dotfile, $graph_name)=@_; + #empty the scrolled win + if(defined $scrolled_win){ + my @list = $scrolled_win->get_children(); + foreach my $l (@list){ + $scrolled_win->remove($l); + } + } + my $scale=$self->object_get_attribute($graph_name,"scale"); + $scale= 1 if (!defined $scale); + my $diagram; + my $cmd = "echo \'$dotfile\' | dot -Tpng -q"; + my ($stdout,$exit,$stderr)= run_cmd_in_back_ground_get_stdout ($cmd); + if ( length( $stderr || '' ) !=0) { + message_dialog("$stderr\nHave you installed graphviz? If not run \n \t \"sudo apt-get install graphviz\" \n in terminal",'error'); + } + $diagram =open_inline_image( $stdout,70*$scale,70*$scale,'percent'); + if(defined $scrolled_win){ + add_widget_to_scrolled_win($diagram,$scrolled_win); + $scrolled_win->show_all(); + } my $save=$self->object_get_attribute("graph_save","enable"); - $save=0 if(!defined $save); - if($save==1){ - my $file = $self->object_get_attribute("graph_save","name"); - my $ext = $self->object_get_attribute("graph_save","extension"); - my $pixbuff= $diagram->get_pixbuf; - $pixbuff->save ("$file.$ext", "$ext"); - $self->object_add_attribute("graph_save","enable",'0'); - } - - + $save=0 if(!defined $save); + if($save==1){ + my $file = $self->object_get_attribute("graph_save","name"); + my $ext = $self->object_get_attribute("graph_save","extension"); + my $pixbuff= $diagram->get_pixbuf; + $pixbuff->save ("$file.$ext", "$ext"); + $self->object_add_attribute("graph_save","enable",'0'); + } } ########### -# run_multiple_proc_in_background (@cmds) -# run parallel application in background and return err, stdout -# return for $ith application i start from 0 -# $pipes{$i}{"out"}= stdout; -# $pipes{$i}{"err"}= stderr; +# run_multiple_proc_in_background (@cmds) +# run parallel application in background and return err, stdout +# return for $ith application i start from 0 +# $pipes{$i}{"out"}= stdout; +# $pipes{$i}{"err"}= stderr; ########### - sub run_multiple_proc_in_background { - my @cmds = @_; - my %pipes; + my @cmds = @_; + my %pipes; my $i=0; - #open seprate pipe for each command - foreach my $cmd (@cmds){ - #print "$cmd\n"; - my ($pipe,$in, $out, $err,$r); - $pipes{$i}{"out"}=\$out; - $pipes{$i}{"err"}=\$err; + #open seprate pipe for each command + foreach my $cmd (@cmds){ + #print "$cmd\n"; + my ($pipe,$in, $out, $err,$r); + $pipes{$i}{"out"}=\$out; + $pipes{$i}{"err"}=\$err; $pipes{$i}{"pipe"}=\$pipe; - my @cat = split ('\s+', $cmd ); - my $cmd_name=$cat[0]; - #perevent pipe from crock - if (!(-e $cmd_name)) { - $err= "file not found: $cmd_name"; - }elsif (!(-f $cmd_name)) { - $err= "not a file: $cmd_name"; - }elsif (!(-x $cmd_name)) { - $err= "permission denied: $cmd_name"; - } - if (defined $err){ - $i++; - next; - } - - $pipe =start \@cat, \$in, \$out, \$err or $r=$?; - if(defined $r){ - #add_colored_info($tview," quartus_stp got an Error: $r\n",'red'); - $err= "Pipe got an Error: $r\n"; - $i++; - next; - } + my @cat = split ('\s+', $cmd ); + my $cmd_name=$cat[0]; + #perevent pipe from crock + if (!(-e $cmd_name)) { + $err= "file not found: $cmd_name"; + }elsif (!(-f $cmd_name)) { + $err= "not a file: $cmd_name"; + }elsif (!(-x $cmd_name)) { + $err= "permission denied: $cmd_name"; + } + if (defined $err){ + $i++; + next; + } + $pipe =start \@cat, \$in, \$out, \$err or $r=$?; + if(defined $r){ + #add_colored_info($tview," quartus_stp got an Error: $r\n",'red'); + $err= "Pipe got an Error: $r\n"; + $i++; + next; + } $i++; - } - - my $pumpble=0; - my $cnt=0; - do{ - $pumpble=0; - for (my $i=0; $i< scalar @cmds; $i++){ - my $pipe= ${$pipes{$i}{"pipe"}}; - next if(!defined $pipe); - if (pumpable ($pipe)) { - pump $pipe; - $pumpble=1; - print "pump $i\n"; - } - } - #if($cnt==100) { - # $cnt=0; - refresh_gui(); - #} - #$cnt++ - }while($pumpble); - - - for (my $i=0; $i< scalar @cmds; $i++){ - my $pipe= ${$pipes{$i}{"pipe"}}; - next if(!defined $pipe); - finish $pipe; - } - return %pipes; + } + my $pumpble=0; + my $cnt=0; + do{ + $pumpble=0; + for (my $i=0; $i< scalar @cmds; $i++){ + my $pipe= ${$pipes{$i}{"pipe"}}; + next if(!defined $pipe); + if (pumpable ($pipe)) { + pump $pipe; + $pumpble=1; + print "pump $i\n"; + } + } + #if($cnt==100) { + # $cnt=0; + refresh_gui(); + #} + #$cnt++ + }while($pumpble); + for (my $i=0; $i< scalar @cmds; $i++){ + my $pipe= ${$pipes{$i}{"pipe"}}; + next if(!defined $pipe); + finish $pipe; + } + return %pipes; } sub add_param_widget { - my ($self,$name,$param, $default,$type,$content,$info, $table,$row,$column,$show,$attribut1,$ref_delay,$new_status,$loc)=@_; - my $label; - $label =gen_label_in_left(" $name") if(defined $name); - my $widget; - my $value=$self->object_get_attribute($attribut1,$param); - if(! defined $value) { - $self->object_add_attribute($attribut1,$param,$default); - $self->object_add_attribute_order($attribut1,$param); - $value=$default; - } - if(! defined $new_status){ - $new_status='ref'; - } - if (! defined $loc){ - $loc = "vertical"; - } - if ($type eq "Entry"){ - $widget=gen_entry($value); - $widget-> signal_connect("changed" => sub{ - my $new_param_value=$widget->get_text(); - $self->object_add_attribute($attribut1,$param,$new_param_value); - set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); - }); - } - elsif ($type eq "Combo-box"){ - my @combo_list=split(/\s*,\s*/,$content); - my $pos=get_pos($value, @combo_list) if(defined $value); - if(!defined $pos){ - $self->object_add_attribute($attribut1,$param,$default); - $pos=get_item_pos($default, @combo_list) if (defined $default); - - } - #print " my $pos=get_item_pos($value, @combo_list);\n"; - $widget=gen_combo(\@combo_list, $pos); - $widget-> signal_connect("changed" => sub{ - my $new_param_value=$widget->get_active_text(); - $self->object_add_attribute($attribut1,$param,$new_param_value); - set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); - }); - - } - elsif ($type eq "EntryCombo"){ - my @combo_list; - @combo_list=split(/\s*,\s*/,$content) if(defined $content); - my $pos=get_pos($value, @combo_list) if(defined $value && defined $content); - $widget= gen_combo_entry (\@combo_list,$pos); - my $child = combo_entry_get_chiled($widget); - $child->signal_connect('changed' => sub { - my ($entry) = @_; - my $new_param_value=$entry->get_text(); - $self->object_add_attribute($attribut1,$param,$new_param_value); - set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); - }); - } - - elsif ($type eq "Spin-button"){ - my ($min,$max,$step,$digit)=split(/\s*,\s*/,$content); - - $value=~ s/[^0-9.\-]//g; - $min=~ s/[^0-9.\-]//g; - $max=~ s/[^0-9.\-]//g; - $step=~ s/[^0-9.\-]//g; - $digit=~ s/[^0-9.\-]//g if (defined $digit); - #$max = $min if($max<$min); - $widget=gen_spin($min,$max,$step,$digit); - $widget->set_value($value); - $widget-> signal_connect("value_changed" => sub{ - my $new_param_value=$widget->get_value(); - $self->object_add_attribute($attribut1,$param,$new_param_value); - set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); - }); - - # $box=def_label_spin_help_box ($param,$info, $value,$min,$max,$step, 2); - } - - elsif ( $type eq "Check-box"){ - $widget = def_hbox(FALSE,0); - my @check; - for (my $i=0;$i<$content;$i++){ - $check[$i]= gen_checkbutton(); - } - for (my $i=0;$i<$content;$i++){ - $widget->pack_end( $check[$i], FALSE, FALSE, 0); - - my @chars = split("",$value); - #check if saved value match the size of check box - if($chars[0] ne $content ) { - $self->object_add_attribute($attribut1,$param,$default); - $value=$default; - @chars = split("",$value); - } - #set initial value - - #print "\@chars=@chars\n"; - for (my $i=0;$i<$content;$i++){ - my $loc= (scalar @chars) -($i+1); - if( $chars[$loc] eq '1') {$check[$i]->set_active(TRUE);} - else {$check[$i]->set_active(FALSE);} - } - - - #get new value - $check[$i]-> signal_connect("toggled" => sub{ - my $new_val="$content\'b"; - - for (my $i=$content-1; $i >= 0; $i--){ - if($check[$i]->get_active()) {$new_val="${new_val}1" ;} - else {$new_val="${new_val}0" ;} - } - $self->object_add_attribute($attribut1,$param,$new_val); - #print "\$new_val=$new_val\n"; - set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); - }); - } - - } - elsif ( $type eq "DIR_path"){ - $widget =get_dir_in_object ($self,$attribut1,$param,$value,'ref',10,$default); - set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); - } - elsif ( $type eq "FILE_path"){ # use $content as extention - $widget =get_file_name_object ($self,$attribut1,$param,$content,undef,$new_status,$ref_delay); - - } - elsif ( $type eq 'Fixed'){ - $self->object_add_attribute($attribut1,$param,$default); - $widget =gen_label_in_left("$default"); - } - else { - $widget =gen_label_in_left("unsuported widget type!"); - } - - my $inf_bt= (defined $info)? gen_button_message ($info,"icons/help.png"):gen_label_in_left(" "); - if($show==1){ - attach_widget_to_table ($table,$row,$label,$inf_bt,$widget,$column); - if ($loc eq "vertical"){ - #print "$loc\n"; - $row ++;} - else { - - $column+=4; - } - } + my ($self,$name,$param, $default,$type,$content,$info, $table,$row,$column,$show,$attribut1,$ref_delay,$new_status,$loc)=@_; + my $label; + $label =gen_label_in_left(" $name") if(defined $name); + my $widget; + my $value=$self->object_get_attribute($attribut1,$param); + if(! defined $value) { + $self->object_add_attribute($attribut1,$param,$default); + $self->object_add_attribute_order($attribut1,$param); + $value=$default; + } + if(! defined $new_status){ + $new_status='ref'; + } + if (! defined $loc){ + $loc = "vertical"; + } + if ($type eq "Entry"){ + $widget=gen_entry($value); + $widget-> signal_connect("changed" => sub{ + my $new_param_value=$widget->get_text(); + $self->object_add_attribute($attribut1,$param,$new_param_value); + set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); + }); + } + elsif ($type eq "Combo-box"){ + my @combo_list=split(/\s*,\s*/,$content); + my $pos=get_pos($value, @combo_list) if(defined $value); + if(!defined $pos){ + $self->object_add_attribute($attribut1,$param,$default); + $pos=get_item_pos($default, @combo_list) if (defined $default); + } + #print " my $pos=get_item_pos($value, @combo_list);\n"; + $widget=gen_combo(\@combo_list, $pos); + $widget-> signal_connect("changed" => sub{ + my $new_param_value=$widget->get_active_text(); + $self->object_add_attribute($attribut1,$param,$new_param_value); + set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); + }); + } + elsif ($type eq "EntryCombo"){ + my @combo_list; + @combo_list=split(/\s*,\s*/,$content) if(defined $content); + my $pos=get_pos($value, @combo_list) if(defined $value && defined $content); + $widget= gen_combo_entry (\@combo_list,$pos); + my $child = combo_entry_get_chiled($widget); + $child->signal_connect('changed' => sub { + my ($entry) = @_; + my $new_param_value=$entry->get_text(); + $self->object_add_attribute($attribut1,$param,$new_param_value); + set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); + }); + } + elsif ($type eq "Spin-button"){ + my ($min,$max,$step,$digit)=split(/\s*,\s*/,$content); + $value=~ s/[^0-9.\-]//g; + $min=~ s/[^0-9.\-]//g; + $max=~ s/[^0-9.\-]//g; + $step=~ s/[^0-9.\-]//g; + $digit=~ s/[^0-9.\-]//g if (defined $digit); + #$max = $min if($max<$min); + $widget=gen_spin($min,$max,$step,$digit); + $widget->set_value($value); + $widget-> signal_connect("value_changed" => sub{ + my $new_param_value=$widget->get_value(); + $self->object_add_attribute($attribut1,$param,$new_param_value); + set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); + }); + # $box=def_label_spin_help_box ($param,$info, $value,$min,$max,$step, 2); + } + elsif ( $type eq "Check-box"){ + $widget = def_hbox(FALSE,0); + my @check; + for (my $i=0;$i<$content;$i++){ + $check[$i]= gen_checkbutton(); + } + for (my $i=0;$i<$content;$i++){ + $widget->pack_end( $check[$i], FALSE, FALSE, 0); + + my @chars = split("",$value); + #check if saved value match the size of check box + if($chars[0] ne $content ) { + $self->object_add_attribute($attribut1,$param,$default); + $value=$default; + @chars = split("",$value); + } + #set initial value + #print "\@chars=@chars\n"; + for (my $i=0;$i<$content;$i++){ + my $loc= (scalar @chars) -($i+1); + if( $chars[$loc] eq '1') {$check[$i]->set_active(TRUE);} + else {$check[$i]->set_active(FALSE);} + } + #get new value + $check[$i]-> signal_connect("toggled" => sub{ + my $new_val="$content\'b"; + for (my $i=$content-1; $i >= 0; $i--){ + if($check[$i]->get_active()) {$new_val="${new_val}1" ;} + else {$new_val="${new_val}0" ;} + } + $self->object_add_attribute($attribut1,$param,$new_val); + #print "\$new_val=$new_val\n"; + set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); + }); + } + } + elsif ( $type eq "DIR_path"){ + $widget =get_dir_in_object ($self,$attribut1,$param,$value,'ref',10,$default); + set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); + } + elsif ( $type eq "FILE_path"){ # use $content as extention + $widget =get_file_name_object ($self,$attribut1,$param,$content,undef,$new_status,$ref_delay); + } + elsif ( $type eq 'Fixed'){ + $self->object_add_attribute($attribut1,$param,$default); + $widget =gen_label_in_left("$default"); + } + else { + $widget =gen_label_in_left("unsuported widget type!"); + } + my $inf_bt= (defined $info)? gen_button_message ($info,"icons/help.png"):gen_label_in_left(" "); + if($show==1){ + attach_widget_to_table ($table,$row,$label,$inf_bt,$widget,$column); + if ($loc eq "vertical"){ + #print "$loc\n"; + $row ++;} + else { + + $column+=4; + } + } return ($row,$column,$widget); } #get the list of files matching the given extention sub get_file_list_by_extention { - my ($open_in, $ext)=@_; - my @files = glob "$open_in/*"; - my $file_list=""; - foreach my $file (@files){ - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq $ext || $suffix eq ".$ext" ){ - $file_list.=",$name"; - } - } - return ($file_list,\@files); + my ($open_in, $ext)=@_; + my @files = glob "$open_in/*"; + my $file_list=""; + foreach my $file (@files){ + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq $ext || $suffix eq ".$ext" ){ + $file_list.=",$name"; + } + } + return ($file_list,\@files); } - - sub set_gui_setting{ - my $paths=shift; - my %p=%{$paths}; - $glob_setting{'FONT_SIZE'}= $p{'GUI_SETTING'}{'FONT_SIZE'} if (defined $p{'GUI_SETTING'}{'FONT_SIZE'}); - $glob_setting{'ICON_SIZE'}= $p{'GUI_SETTING'}{'ICON_SIZE'} if (defined $p{'GUI_SETTING'}{'ICON_SIZE'}); - $glob_setting{'DSPLY_X'} = $p{'GUI_SETTING'}{'DSPLY_X'} if (defined $p{'GUI_SETTING'}{'DSPLY_X'}); - $glob_setting{'DSPLY_Y'} = $p{'GUI_SETTING'}{'DSPLY_Y'} if (defined $p{'GUI_SETTING'}{'DSPLY_Y'}); + my $paths=shift; + my %p=%{$paths}; + $glob_setting{'FONT_SIZE'}= $p{'GUI_SETTING'}{'FONT_SIZE'} if (defined $p{'GUI_SETTING'}{'FONT_SIZE'}); + $glob_setting{'ICON_SIZE'}= $p{'GUI_SETTING'}{'ICON_SIZE'} if (defined $p{'GUI_SETTING'}{'ICON_SIZE'}); + $glob_setting{'DSPLY_X'} = $p{'GUI_SETTING'}{'DSPLY_X'} if (defined $p{'GUI_SETTING'}{'DSPLY_X'}); + $glob_setting{'DSPLY_Y'} = $p{'GUI_SETTING'}{'DSPLY_Y'} if (defined $p{'GUI_SETTING'}{'DSPLY_Y'}); } my ($screen_x,$screen_y); sub get_default_screen_size{ - return ($screen_x,$screen_y) if (defined $screen_x && defined $screen_y); - - my $fh= 'xrandr --current | awk \'$2~/\*/{print $1}\'' ; - my ($stdout, $stderr, $success) = qxx( ($fh) ); - my @a = split ("\n",$stdout); - ($screen_x,$screen_y) = split ("x",$a[0]); - $screen_x = 600 if(!defined $screen_x); - $screen_y = 800 if(!defined $screen_y); - return ($screen_x,$screen_y); + return ($screen_x,$screen_y) if (defined $screen_x && defined $screen_y); + + my $fh= 'xrandr --current | awk \'$2~/\*/{print $1}\'' ; + my ($stdout, $stderr, $success) = qxx( ($fh) ); + my @a = split ("\n",$stdout); + ($screen_x,$screen_y) = split ("x",$a[0]); + $screen_x = 600 if(!defined $screen_x); + $screen_y = 800 if(!defined $screen_y); + return ($screen_x,$screen_y); } @@ -1380,36 +1172,29 @@ sub get_default_screen_size{ sub get_current_monitor_working_area{ return ($Xaxis_max,$Yaxis_max) if(defined $Yaxis_max && defined $Yaxis_max); my $screen = get_default_screen(); - my $hight = $screen->get_height(); - my $active = $screen->get_active_window(); + my $hight = $screen->get_height(); + my $active = $screen->get_active_window(); if (defined $active ){ - my $monitor = $screen->get_monitor_at_window($active); - my $warea = $screen->get_monitor_workarea($monitor);#get_width(); - ($Xaxis_max,$Yaxis_max)=($warea->{'width'},$warea->{'height'}); - #print Data::Dumper->Dump ([$warea],['ttt']); - return ($Xaxis_max,$Yaxis_max); - } - ($Xaxis_max, $Yaxis_max)=get_default_screen_size(); - return ($Xaxis_max,$Yaxis_max); + my $monitor = $screen->get_monitor_at_window($active); + my $warea = $screen->get_monitor_workarea($monitor);#get_width(); + ($Xaxis_max,$Yaxis_max)=($warea->{'width'},$warea->{'height'}); + #print Data::Dumper->Dump ([$warea],['ttt']); + return ($Xaxis_max,$Yaxis_max); + } + ($Xaxis_max, $Yaxis_max)=get_default_screen_size(); + return ($Xaxis_max,$Yaxis_max); } - - - sub max_win_size { - my ($x,$y); - $x= int($glob_setting{'DSPLY_X'}) if ($glob_setting{'DSPLY_X'} ne 'default'); - $y= int($glob_setting{'DSPLY_Y'}) if ($glob_setting{'DSPLY_Y'} ne 'default'); - if (!defined $x || !defined $y){ - my ($X,$Y)=get_current_monitor_working_area(); - $x=$X if (!defined $x); - $y=$Y if (!defined $y); - } - - return ($x,$y); - - + my ($x,$y); + $x= int($glob_setting{'DSPLY_X'}) if ($glob_setting{'DSPLY_X'} ne 'default'); + $y= int($glob_setting{'DSPLY_Y'}) if ($glob_setting{'DSPLY_Y'} ne 'default'); + if (!defined $x || !defined $y){ + my ($X,$Y)=get_current_monitor_working_area(); + $x=$X if (!defined $x); + $y=$Y if (!defined $y); + } + + return ($x,$y); } - - -1 +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/compile.pl b/mpsoc/perl_gui/lib/perl/compile.pl index f63d7bd..a974f10 100644 --- a/mpsoc/perl_gui/lib/perl/compile.pl +++ b/mpsoc/perl_gui/lib/perl/compile.pl @@ -291,11 +291,11 @@ sub select_parallel_process_num { } } ($row,$col)= add_param_widget ($self,"Paralle run:" , "cpu_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of processors the Verilator can use at once to run parallel compilations/simulations", $table,$row,$col,1, 'compile', undef,undef,'vertical'); - return $table; + return $table; } sub select_parallel_thread_num { - my ($self,$name,$top,$target_dir)=@_; + my ($self,$name,$top,$target_dir)=@_; my $table = def_table(2, 2, FALSE); my $col=0; my $row=0; @@ -303,7 +303,7 @@ sub select_parallel_thread_num { my $cmd = "nproc\n"; if(!defined $cpu_num){ my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ + if(length $stderr>1){ #nproc command has failed. set default 4 paralel processor }else { my ($number ) = $stdout =~ /(\d+)/; @@ -313,7 +313,7 @@ sub select_parallel_thread_num { } } ($row,$col)= add_param_widget ($self,"Thread run:" , "thread_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of threads the Verilator can use at once in one simulation", $table,$row,$col,1, 'compile', undef,undef,'vertical'); - return $table; + return $table; } sub remove_pin_assignment{ @@ -2621,11 +2621,10 @@ sub verilator_testbench{ add_colored_info($tview,"$stderr\n",'red'); }else { add_info($tview,"$stdout\n"); - } + } }else{ add_colored_info($tview,"Cannot find $bin executable binary file! make sure you have compiled the testbench successfully\n", 'red') - } + } }); } - 1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/diagram.pl b/mpsoc/perl_gui/lib/perl/diagram.pl index 5670c28..319b120 100644 --- a/mpsoc/perl_gui/lib/perl/diagram.pl +++ b/mpsoc/perl_gui/lib/perl/diagram.pl @@ -15,116 +15,116 @@ sub get_dot_file{ - my $self= shift; - my $self_name=$self->object_get_attribute('soc_name'); - my $remove_clk = $self->object_get_attribute("tile_diagram","show_clk"); - my $remove_reset = $self->object_get_attribute("tile_diagram","show_reset"); - my $remove_unused = $self->object_get_attribute("tile_diagram","show_unused"); + my $self= shift; + my $self_name=$self->object_get_attribute('soc_name'); + my $remove_clk = $self->object_get_attribute("tile_diagram","show_clk"); + my $remove_reset = $self->object_get_attribute("tile_diagram","show_reset"); + my $remove_unused = $self->object_get_attribute("tile_diagram","show_unused"); - my $dotfile= + my $dotfile= "digraph G { - graph [rankdir = LR , splines=polyline, overlap = false]; - node[shape=record]; + graph [rankdir = LR , splines=polyline, overlap = false]; + node[shape=record]; "; - my @all_instances=$self->soc_get_all_instances(); - #print "@all_instances\n"; - my $graph_connect= ''; - my $n=0; - #my %socket_color; - foreach my $instance_id (@all_instances){ - my $first=1; - my $instance_name=$self->soc_get_instance_name($instance_id); - $dotfile="$dotfile \n\t$instance_id \[label=\"{ "; - - my @sockets= $self->soc_get_all_sockets_of_an_instance($instance_id); - @sockets = remove_scolar_from_array(\@sockets,'clk') if ($remove_clk); - @sockets = remove_scolar_from_array(\@sockets,'reset') if ($remove_reset); - - - foreach my $socket (@sockets){ - - my @nums=$self->soc_list_socket_nums($instance_id,$socket); - foreach my $num (@nums){ - my $name= $self->soc_get_socket_name ($instance_id,$socket,$num); - my ($s_type,$s_value,$s_connection_num)=$self->soc_get_socket_of_instance($instance_id,$socket); - my $v=(defined $s_value) ? $self->soc_get_module_param_value($instance_id,$s_value) : 1; - $v=1 if ( length( $v || '' ) ==0); - #for(my $i=$v-1; $i>=0; $i--) { - for(my $i=0; $i<$v; $i++) { - #$socket_color{socket_${socket}\_$i}=$n; - #$n = ($n<30)? $n+1 : 0; - my ($ref1,$ref2)= $self->soc_get_modules_plug_connected_to_socket($instance_id,$socket,$i); - my %connected_plugs=%$ref1; - my %connected_plug_nums=%$ref2; - if(%connected_plugs || $remove_unused==0){ - $dotfile= ($first)? "$dotfile\{$name\_$i" : "$dotfile |$name\_${i}"; - $first=0; - } - } - - } - } - - - $dotfile=($first)? "$dotfile $instance_name" : "$dotfile}|$instance_name"; - $first=1; - my @plugs= $self->soc_get_all_plugs_of_an_instance($instance_id); - @plugs = remove_scolar_from_array(\@plugs,'clk') if ($remove_clk); - @plugs = remove_scolar_from_array(\@plugs,'reset') if ($remove_reset); - - my %plug_order; - my @noconnect; - foreach my $plug (@plugs){ - - my @nums=$self->soc_list_plug_nums($instance_id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$self->soc_get_plug($instance_id,$plug,$num); - - if(defined $connect_socket || $remove_unused==0){ - #$dotfile= ($first)? "$dotfile |{$name" : "$dotfile|$name"; - if(defined $connect_id && defined $connect_socket){ - my @sockets= $self->soc_get_all_sockets_of_an_instance($connect_id); - my $order_val=0; - my $s1=get_pos($connect_id, @all_instances); - my $s2=get_pos($connect_socket, @sockets); - $order_val=$s1*1000000+$s2*10000+$connect_socket_num; - $plug_order{$order_val}= "$name"; - }else {push (@noconnect,"$name");} - } - - - #my $connect_name=$self->soc_get_instance_name($connect_id); - #my $color = get_color_hex_string($n); - #$n = ($n<30)? $n+1 : 0; - - $graph_connect="$graph_connect $instance_id:plug_${plug}_${num} -> $connect_id:socket_${connect_socket}_${connect_socket_num} [ dir=none]\n" if(defined $connect_socket); - - } - } - foreach my $p (sort {$a<=>$b} keys %plug_order){ - my $k=$plug_order{$p}; - #print "$instance_name : $k=\$plug_order{$p}\n"; - $dotfile= ($first) ? "$dotfile |{ ${k}": "$dotfile |${k}"; - $first=0; - - } - - foreach my $k (@noconnect){ - $dotfile= ($first) ? "$dotfile |{ ${k}": "$dotfile |${k}"; - $first=0; - } - - $dotfile= "$dotfile} }\"];"; - - - - } - $dotfile="$dotfile\n\n$graph_connect"; - $dotfile="$dotfile\n\n}\n"; - - - return $dotfile; + my @all_instances=$self->soc_get_all_instances(); + #print "@all_instances\n"; + my $graph_connect= ''; + my $n=0; + #my %socket_color; + foreach my $instance_id (@all_instances){ + my $first=1; + my $instance_name=$self->soc_get_instance_name($instance_id); + $dotfile="$dotfile \n\t$instance_id \[label=\"{ "; + + my @sockets= $self->soc_get_all_sockets_of_an_instance($instance_id); + @sockets = remove_scolar_from_array(\@sockets,'clk') if ($remove_clk); + @sockets = remove_scolar_from_array(\@sockets,'reset') if ($remove_reset); + + + foreach my $socket (@sockets){ + + my @nums=$self->soc_list_socket_nums($instance_id,$socket); + foreach my $num (@nums){ + my $name= $self->soc_get_socket_name ($instance_id,$socket,$num); + my ($s_type,$s_value,$s_connection_num)=$self->soc_get_socket_of_instance($instance_id,$socket); + my $v=(defined $s_value) ? $self->soc_get_module_param_value($instance_id,$s_value) : 1; + $v=1 if ( length( $v || '' ) ==0); + #for(my $i=$v-1; $i>=0; $i--) { + for(my $i=0; $i<$v; $i++) { + #$socket_color{socket_${socket}\_$i}=$n; + #$n = ($n<30)? $n+1 : 0; + my ($ref1,$ref2)= $self->soc_get_modules_plug_connected_to_socket($instance_id,$socket,$i); + my %connected_plugs=%$ref1; + my %connected_plug_nums=%$ref2; + if(%connected_plugs || $remove_unused==0){ + $dotfile= ($first)? "$dotfile\{$name\_$i" : "$dotfile |$name\_${i}"; + $first=0; + } + } + + } + } + + + $dotfile=($first)? "$dotfile $instance_name" : "$dotfile}|$instance_name"; + $first=1; + my @plugs= $self->soc_get_all_plugs_of_an_instance($instance_id); + @plugs = remove_scolar_from_array(\@plugs,'clk') if ($remove_clk); + @plugs = remove_scolar_from_array(\@plugs,'reset') if ($remove_reset); + + my %plug_order; + my @noconnect; + foreach my $plug (@plugs){ + + my @nums=$self->soc_list_plug_nums($instance_id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$self->soc_get_plug($instance_id,$plug,$num); + + if(defined $connect_socket || $remove_unused==0){ + #$dotfile= ($first)? "$dotfile |{$name" : "$dotfile|$name"; + if(defined $connect_id && defined $connect_socket){ + my @sockets= $self->soc_get_all_sockets_of_an_instance($connect_id); + my $order_val=0; + my $s1=get_pos($connect_id, @all_instances); + my $s2=get_pos($connect_socket, @sockets); + $order_val=$s1*1000000+$s2*10000+$connect_socket_num; + $plug_order{$order_val}= "$name"; + }else {push (@noconnect,"$name");} + } + + + #my $connect_name=$self->soc_get_instance_name($connect_id); + #my $color = get_color_hex_string($n); + #$n = ($n<30)? $n+1 : 0; + + $graph_connect="$graph_connect $instance_id:plug_${plug}_${num} -> $connect_id:socket_${connect_socket}_${connect_socket_num} [ dir=none]\n" if(defined $connect_socket); + + } + } + foreach my $p (sort {$a<=>$b} keys %plug_order){ + my $k=$plug_order{$p}; + #print "$instance_name : $k=\$plug_order{$p}\n"; + $dotfile= ($first) ? "$dotfile |{ ${k}": "$dotfile |${k}"; + $first=0; + + } + + foreach my $k (@noconnect){ + $dotfile= ($first) ? "$dotfile |{ ${k}": "$dotfile |${k}"; + $first=0; + } + + $dotfile= "$dotfile} }\"];"; + + + + } + $dotfile="$dotfile\n\n$graph_connect"; + $dotfile="$dotfile\n\n}\n"; + + + return $dotfile; } @@ -134,1275 +134,1005 @@ sub get_dot_file{ sub show_tile_diagram { - my $self= shift; - - my $table=def_table(20,20,FALSE); - - my $window=def_popwin_size(80,80,"Processing Tile functional block diagram",'percent'); - my $scrolled_win = add_widget_to_scrolled_win(); - - $window->add ($table); - - my $plus = def_image_button('icons/plus.png',undef,TRUE); - my $minues = def_image_button('icons/minus.png',undef,TRUE); - my $unused = gen_check_box_object ($self,"tile_diagram","show_unused",0,undef,undef); - my $save = def_image_button('icons/save.png',undef,TRUE); - my $clk = gen_check_box_object ($self,"tile_diagram","show_clk",0,undef,undef); - my $reset = gen_check_box_object ($self,"tile_diagram","show_reset",0,undef,undef); - my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); - set_tip($dot_file, "Show dot file."); - #my $save = def_image_button('icons/save.png',undef,TRUE); - - my $scale=$self->object_get_attribute("tile_diagram","scale"); - $scale= 1 if (!defined $scale); - - - - - my $col=0; - $table->attach ($plus , $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($minues, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($save, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach (gen_label_in_left(" Remove unconnected Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($unused, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach (gen_label_in_left(" Remove Clk Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($clk, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach (gen_label_in_left(" Remove Reset Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($reset, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($dot_file, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - - while ($col<20){ - - my $tmp=gen_label_in_left(''); - $table->attach_defaults ($tmp, $col, $col+1,0,1);$col++; - } - - $table->attach_defaults ($scrolled_win, 0, 20, 1, 20); #,'fill','shrink',2,2); - - $plus -> signal_connect("clicked" => sub{ - $scale*=1.1 if ($scale <10); - $self->object_add_attribute("tile_diagram","scale", $scale ); - gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - }); - $minues -> signal_connect("clicked" => sub{ - $scale*=.9 if ($scale >0.1); ; - $self->object_add_attribute("tile_diagram","scale", $scale ); - gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - }); - $save-> signal_connect("clicked" => sub{ - save_inline_diagram_as ($self); - show_tile_diagram($self); - $window->destroy; - }); - $unused-> signal_connect("toggled" => sub{ - gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - - }); - $clk-> signal_connect("toggled" => sub{ - gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - - }); - $reset-> signal_connect("toggled" => sub{ - - gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - - }); - - $dot_file-> signal_connect("clicked" => sub{ - my $dotfile = get_dot_file_text($self,'tile'); - show_text_in_scrolled_win($self,$scrolled_win, $dotfile); - }); - - - gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - $window->show_all(); + my $self= shift; + + my $table=def_table(20,20,FALSE); + + my $window=def_popwin_size(80,80,"Processing Tile functional block diagram",'percent'); + my $scrolled_win = add_widget_to_scrolled_win(); + + $window->add ($table); + + my $plus = def_image_button('icons/plus.png',undef,TRUE); + my $minues = def_image_button('icons/minus.png',undef,TRUE); + my $unused = gen_check_box_object ($self,"tile_diagram","show_unused",0,undef,undef); + my $save = def_image_button('icons/save.png',undef,TRUE); + my $clk = gen_check_box_object ($self,"tile_diagram","show_clk",0,undef,undef); + my $reset = gen_check_box_object ($self,"tile_diagram","show_reset",0,undef,undef); + my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); + set_tip($dot_file, "Show dot file."); + #my $save = def_image_button('icons/save.png',undef,TRUE); + + my $scale=$self->object_get_attribute("tile_diagram","scale"); + $scale= 1 if (!defined $scale); + + + + + my $col=0; + $table->attach ($plus , $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($minues, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($save, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach (gen_label_in_left(" Remove unconnected Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($unused, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach (gen_label_in_left(" Remove Clk Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($clk, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach (gen_label_in_left(" Remove Reset Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($reset, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($dot_file, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + + while ($col<20){ + + my $tmp=gen_label_in_left(''); + $table->attach_defaults ($tmp, $col, $col+1,0,1);$col++; + } + + $table->attach_defaults ($scrolled_win, 0, 20, 1, 20); #,'fill','shrink',2,2); + + $plus -> signal_connect("clicked" => sub{ + $scale*=1.1 if ($scale <10); + $self->object_add_attribute("tile_diagram","scale", $scale ); + gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); + }); + $minues -> signal_connect("clicked" => sub{ + $scale*=.9 if ($scale >0.1); ; + $self->object_add_attribute("tile_diagram","scale", $scale ); + gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); + }); + $save-> signal_connect("clicked" => sub{ + save_inline_diagram_as ($self); + show_tile_diagram($self); + $window->destroy; + }); + $unused-> signal_connect("toggled" => sub{ + gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); + + }); + $clk-> signal_connect("toggled" => sub{ + gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); + + }); + $reset-> signal_connect("toggled" => sub{ + + gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); + + }); + + $dot_file-> signal_connect("clicked" => sub{ + my $dotfile = get_dot_file_text($self,'tile'); + show_text_in_scrolled_win($self,$scrolled_win, $dotfile); + }); + + + gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); + $window->show_all(); } sub gen_show_diagram{ - my ($self,$scrolled_win,$type,$name)=@_; - - my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); - if ($type eq 'topology' && $topology eq '"CUSTOM"'){ - - my $name=$self->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); - $name=~s/["]//gs; - my $image= get_project_dir()."/mpsoc/rtl/src_topology/$name/$name.png"; - my $tmp = "$ENV{'PRONOC_WORK'}/tmp/diagram.png"; - - unlink $tmp; - return 0 unless (-f "$image"); - copy ($image,$tmp); - return 0 unless (-f "$tmp"); - show_diagram ($self,$scrolled_win,$name); - return 1; - } - - - - my $dotfile = get_dot_file_text($self,$type); - - generate_and_show_graph_using_graphviz ($self,$scrolled_win,$dotfile, $name); - + my ($self,$scrolled_win,$type,$name)=@_; + my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); + if ($type eq 'topology' && $topology eq '"CUSTOM"'){ + my $name=$self->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); + $name=~s/["]//gs; + my $image= get_project_dir()."/mpsoc/rtl/src_topology/$name/$name.png"; + my $tmp = "$ENV{'PRONOC_WORK'}/tmp/diagram.png"; + unlink $tmp; + return 0 unless (-f "$image"); + copy ($image,$tmp); + return 0 unless (-f "$tmp"); + show_diagram ($self,$scrolled_win,$name); + return 1; + } + my $dotfile = get_dot_file_text($self,$type); + generate_and_show_graph_using_graphviz ($self,$scrolled_win,$dotfile, $name); } sub show_topology_diagram { - my ($self)= @_; - - my $table=def_table(20,20,FALSE); - - my $window=def_popwin_size(80,80,"NoC-based MPSoC topology block diagram",'percent'); - my $scrolled_win = add_widget_to_scrolled_win(); - - - my $notebook = gen_notebook(); - $notebook->set_tab_pos ('top'); - $notebook->set_scrollable(TRUE); - $window->add($notebook); - - - - - my @data; - my $ref =$self->object_get_attribute('noc_param'); - if(defined $ref){ - my %param=%{$ref}; - foreach my $p (sort keys %param){ - push (@data, {0 => "$p", 1 =>"$param{$p}"}); - } - } - - # create list store - my @clmn_type = ('Glib::String', 'Glib::String'); - my @clmns = (" Parameter Name ", " Value "); - my $page2=add_widget_to_scrolled_win(gen_list_store (\@data,\@clmn_type,\@clmns)); - - - - $notebook->append_page ($table,gen_label_with_mnemonic ("Topology diagram")) ; - $notebook->append_page ($page2,gen_label_with_mnemonic ("NoC parameters")) ; - - - - - - - - - - my $plus = def_image_button('icons/plus.png',undef,TRUE); - my $minues = def_image_button('icons/minus.png',undef,TRUE); - my $save = def_image_button('icons/save.png',undef,TRUE); - my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); - set_tip($dot_file, "Show dot file."); - - my $gtype=$self->object_get_attribute("tile_diagram","gtype"); - if (!defined $gtype){ - $gtype='comp' ; - $self->object_add_attribute("tile_diagram","gtype",$gtype); - } - my $graph_type= ($gtype eq 'comp')? def_colored_button('comp',17): def_colored_button('simple',4); - my $box=def_hbox(FALSE,0); - $box->pack_start( $graph_type, FALSE, FALSE, 0); - - - - - my $scale=$self->object_get_attribute("tile_diagram","scale"); - $scale= 1 if (!defined $scale); - - - - - my $col=0; - $table->attach ($plus , $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($minues, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($save, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($dot_file, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($box, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - #$table->attach (gen_label_in_left(" Remove unconnected Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - #$table->attach (gen_label_in_left(" Remove Clk Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - #$table->attach (gen_label_in_left(" Remove Reset Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - while ($col<20){ - my $tmp=gen_label_in_left(''); - $table->attach_defaults ($tmp, $col, $col+1,0,1);$col++; - } - - $table->attach_defaults ($scrolled_win, 0, 20, 1, 20); #,'fill','shrink',2,2); - - $plus -> signal_connect("clicked" => sub{ - $scale*=1.1 if ($scale <10); - $self->object_add_attribute("topology_diagram","scale", $scale ); - gen_show_diagram($self,$scrolled_win,'topology',"topology_diagram"); - - }); - $minues -> signal_connect("clicked" => sub{ - $scale*=.9 if ($scale >0.1); - $self->object_add_attribute("topology_diagram","scale", $scale ); - gen_show_diagram($self,$scrolled_win,'topology',"topology_diagram"); - }); - $save-> signal_connect("clicked" => sub{ - save_inline_diagram_as ($self); - show_topology_diagram($self); - $window->destroy; - }); - - $dot_file-> signal_connect("clicked" => sub{ - my $dot_file=get_dot_file_text($self,'topology'); - show_text_in_scrolled_win($self,$scrolled_win, $dot_file); - }); - - $graph_type-> signal_connect("clicked" => sub{ - my $gtype=$self->object_get_attribute("tile_diagram","gtype"); - my $new = ($gtype eq "simple")? "comp" : "simple"; - $self->object_add_attribute("tile_diagram","gtype",$new); - $graph_type= ($new eq 'comp')? def_colored_button('comp',17): def_colored_button('simple',4); - show_topology_diagram($self); - $window->destroy; - }); - - - gen_show_diagram($self,$scrolled_win,'topology',"topology_diagram"); - $window->show_all(); - $notebook->set_current_page (0); + my ($self)= @_; + my $table=def_table(20,20,FALSE); + my $window=def_popwin_size(80,80,"NoC-based MPSoC topology block diagram",'percent'); + my $scrolled_win = add_widget_to_scrolled_win(); + my $notebook = gen_notebook(); + $notebook->set_tab_pos ('top'); + $notebook->set_scrollable(TRUE); + $window->add($notebook); + my @data; + my $ref =$self->object_get_attribute('noc_param'); + if(defined $ref){ + my %param=%{$ref}; + foreach my $p (sort keys %param){ + push (@data, {0 => "$p", 1 =>"$param{$p}"}); + } + } + + # create list store + my @clmn_type = ('Glib::String', 'Glib::String'); + my @clmns = (" Parameter Name ", " Value "); + my $page2=add_widget_to_scrolled_win(gen_list_store (\@data,\@clmn_type,\@clmns)); + $notebook->append_page ($table,gen_label_with_mnemonic ("Topology diagram")) ; + $notebook->append_page ($page2,gen_label_with_mnemonic ("NoC parameters")) ; + my $plus = def_image_button('icons/plus.png',undef,TRUE); + my $minues = def_image_button('icons/minus.png',undef,TRUE); + my $save = def_image_button('icons/save.png',undef,TRUE); + my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); + set_tip($dot_file, "Show dot file."); + + my $gtype=$self->object_get_attribute("tile_diagram","gtype"); + if (!defined $gtype){ + $gtype='comp' ; + $self->object_add_attribute("tile_diagram","gtype",$gtype); + } + my $graph_type= ($gtype eq 'comp')? def_colored_button('comp',17): def_colored_button('simple',4); + my $box=def_hbox(FALSE,0); + $box->pack_start( $graph_type, FALSE, FALSE, 0); + my $scale=$self->object_get_attribute("tile_diagram","scale"); + $scale= 1 if (!defined $scale); + + my $col=0; + $table->attach ($plus , $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($minues, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($save, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($dot_file, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($box, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + #$table->attach (gen_label_in_left(" Remove unconnected Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + #$table->attach (gen_label_in_left(" Remove Clk Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + #$table->attach (gen_label_in_left(" Remove Reset Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + while ($col<20){ + my $tmp=gen_label_in_left(''); + $table->attach_defaults ($tmp, $col, $col+1,0,1);$col++; + } + + $table->attach_defaults ($scrolled_win, 0, 20, 1, 20); #,'fill','shrink',2,2); + $plus -> signal_connect("clicked" => sub{ + $scale*=1.1 if ($scale <10); + $self->object_add_attribute("topology_diagram","scale", $scale ); + gen_show_diagram($self,$scrolled_win,'topology',"topology_diagram"); + + }); + $minues -> signal_connect("clicked" => sub{ + $scale*=.9 if ($scale >0.1); + $self->object_add_attribute("topology_diagram","scale", $scale ); + gen_show_diagram($self,$scrolled_win,'topology',"topology_diagram"); + }); + $save-> signal_connect("clicked" => sub{ + save_inline_diagram_as ($self); + show_topology_diagram($self); + $window->destroy; + }); + + $dot_file-> signal_connect("clicked" => sub{ + my $dot_file=get_dot_file_text($self,'topology'); + show_text_in_scrolled_win($self,$scrolled_win, $dot_file); + }); + + $graph_type-> signal_connect("clicked" => sub{ + my $gtype=$self->object_get_attribute("tile_diagram","gtype"); + my $new = ($gtype eq "simple")? "comp" : "simple"; + $self->object_add_attribute("tile_diagram","gtype",$new); + $graph_type= ($new eq 'comp')? def_colored_button('comp',17): def_colored_button('simple',4); + show_topology_diagram($self); + $window->destroy; + }); + + gen_show_diagram($self,$scrolled_win,'topology',"topology_diagram"); + $window->show_all(); + $notebook->set_current_page (0); } sub get_dot_file_text { - my ($self,$type)=@_; - my $dotfile; - $dotfile= get_dot_file($self) if ($type eq 'tile'); - $dotfile= get_topology_dot_file($self) if ($type eq 'topology'); - $dotfile= generate_custom_topology_dot_file($self) if ($type eq 'custom_topology'); - $dotfile= generate_trace_dot_file($self) if ($type eq 'trace'); - $dotfile= generate_merge_actor_dot_file ($self) if ($type eq 'merge-actor'); - $dotfile= generate_map_dot_file($self) if ($type eq 'map'); - return $dotfile; + my ($self,$type)=@_; + my $dotfile; + $dotfile= get_dot_file($self) if ($type eq 'tile'); + $dotfile= get_topology_dot_file($self) if ($type eq 'topology'); + $dotfile= generate_custom_topology_dot_file($self) if ($type eq 'custom_topology'); + $dotfile= generate_trace_dot_file($self) if ($type eq 'trace'); + $dotfile= generate_merge_actor_dot_file ($self) if ($type eq 'merge-actor'); + $dotfile= generate_map_dot_file($self) if ($type eq 'map'); + return $dotfile; } sub gen_diagram { - my ($self,$type)=@_; - my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); - if ($type eq 'topology' && $topology eq '"CUSTOM"'){ - - my $name=$self->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); - $name=~s/["]//gs; - my $image= get_project_dir()."/mpsoc/rtl/src_topology/$name/$name.png"; - my $tmp = "$ENV{'PRONOC_WORK'}/tmp/diagram.png"; - - unlink $tmp; - return 0 unless (-f "$image"); - copy ($image,$tmp); - return 0 unless (-f "$tmp"); - return 1; - } - - - - my $dotfile = get_dot_file_text(@_); - - my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; - - - my $cmd; - #$cmd= "dot $tmp_dir/diagram.txt | neato -n -Tpng -o $tmp_dir/diagram.png" if ($type eq 'tile' || $type eq 'trace' ); - #$cmd = "dot $tmp_dir/diagram.txt -Kfdp -n -Tpng -o $tmp_dir/diagram.png" if ( $type eq 'map' || $type eq 'topology' || $type eq 'custom_topology' ); - $cmd= " dot | neato -n -Tpng -o $tmp_dir/diagram.png" if ($type eq 'tile' || $type eq 'trace' ); - $cmd = " dot -Kfdp -n -Tpng -o $tmp_dir/diagram.png" if ( $type eq 'map' || $type eq 'topology' || $type eq 'custom_topology' ); + my ($self,$type)=@_; + my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); + if ($type eq 'topology' && $topology eq '"CUSTOM"'){ + my $name=$self->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); + $name=~s/["]//gs; + my $image= get_project_dir()."/mpsoc/rtl/src_topology/$name/$name.png"; + my $tmp = "$ENV{'PRONOC_WORK'}/tmp/diagram.png"; + unlink $tmp; + return 0 unless (-f "$image"); + copy ($image,$tmp); + return 0 unless (-f "$tmp"); + return 1; + } + my $dotfile = get_dot_file_text(@_); + my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; + my $cmd; + #$cmd= "dot $tmp_dir/diagram.txt | neato -n -Tpng -o $tmp_dir/diagram.png" if ($type eq 'tile' || $type eq 'trace' ); + #$cmd = "dot $tmp_dir/diagram.txt -Kfdp -n -Tpng -o $tmp_dir/diagram.png" if ( $type eq 'map' || $type eq 'topology' || $type eq 'custom_topology' ); + $cmd= " dot | neato -n -Tpng -o $tmp_dir/diagram.png" if ($type eq 'tile' || $type eq 'trace' ); + $cmd = " dot -Kfdp -n -Tpng -o $tmp_dir/diagram.png" if ( $type eq 'map' || $type eq 'topology' || $type eq 'custom_topology' ); $cmd = "echo \'$dotfile\' | $cmd"; - - my ($stdout,$exit,$stderr)= run_cmd_in_back_ground_get_stdout ($cmd); - - if ( length( $stderr || '' ) !=0) { - message_dialog("$stderr\nHave you installed graphviz? If not run \n \t \"sudo apt-get install graphviz\" \n in terminal"); - return 0 unless (-f "$tmp_dir/diagram.png"); - } - return 1; + my ($stdout,$exit,$stderr)= run_cmd_in_back_ground_get_stdout ($cmd); + if ( length( $stderr || '' ) !=0) { + message_dialog("$stderr\nHave you installed graphviz? If not run \n \t \"sudo apt-get install graphviz\" \n in terminal"); + return 0 unless (-f "$tmp_dir/diagram.png"); + } + return 1; } - sub show_diagram { - my ($self,$scrolled_win,$name,$image_name)=@_; - $image_name="diagram.png" if (!defined $image_name); - my @list = $scrolled_win->get_children(); - foreach my $l (@list){ - $scrolled_win->remove($l); - } - - - my $scale=$self->object_get_attribute($name,"scale"); - $scale= 1 if (!defined $scale); - my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; - my $diagram=open_image("$tmp_dir/$image_name",70*$scale,70*$scale,'percent'); - - add_widget_to_scrolled_win($diagram,$scrolled_win); - $scrolled_win->show_all(); - + my ($self,$scrolled_win,$name,$image_name)=@_; + $image_name="diagram.png" if (!defined $image_name); + my @list = $scrolled_win->get_children(); + foreach my $l (@list){ + $scrolled_win->remove($l); + } + my $scale=$self->object_get_attribute($name,"scale"); + $scale= 1 if (!defined $scale); + my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; + my $diagram=open_image("$tmp_dir/$image_name",70*$scale,70*$scale,'percent'); + add_widget_to_scrolled_win($diagram,$scrolled_win); + $scrolled_win->show_all(); } sub show_text_in_scrolled_win { - my ($self,$scrolled_win, $text)=@_; - my @list = $scrolled_win->get_children(); - foreach my $l (@list){ - $scrolled_win->remove($l); - } - - - my ($u,$tview)=create_txview(); - - show_info($tview, $text); - add_widget_to_scrolled_win($u,$scrolled_win); - $scrolled_win->show_all(); + my ($self,$scrolled_win, $text)=@_; + my @list = $scrolled_win->get_children(); + foreach my $l (@list){ + $scrolled_win->remove($l); + } + my ($u,$tview)=create_txview(); + show_info($tview, $text); + add_widget_to_scrolled_win($u,$scrolled_win); + $scrolled_win->show_all(); } - - - sub save_diagram_as { - my $self= shift; - - my $file; - my $title ='Save as'; - - - - my @extensions=('png'); - my $open_in=undef; - my $dialog = save_file_dialog ( 'Save file',@extensions); - $dialog->set_current_folder ($open_in) if(defined $open_in); - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my $ext = $dialog->get_filter; - $ext=$ext->get_name; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; - - $self->object_add_attribute("graph_save","name",$file); - $self->object_add_attribute("graph_save","extension",$ext); - my $tmp = "$ENV{'PRONOC_WORK'}/tmp/diagram.png"; - copy ($tmp,$file); - - - - } - $dialog->destroy; + my $self= shift; + my $file; + my $title ='Save as'; + my @extensions=('png'); + my $open_in=undef; + my $dialog = save_file_dialog ( 'Save file',@extensions); + $dialog->set_current_folder ($open_in) if(defined $open_in); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my $ext = $dialog->get_filter; + $ext=$ext->get_name; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; + $self->object_add_attribute("graph_save","name",$file); + $self->object_add_attribute("graph_save","extension",$ext); + my $tmp = "$ENV{'PRONOC_WORK'}/tmp/diagram.png"; + copy ($tmp,$file); + } + $dialog->destroy; } - - - sub save_inline_diagram_as { - my $self= shift; - - my $file; - my $title ='Save as'; - - - - my @extensions=('png','jpeg'); - my $open_in=undef; - my $dialog = save_file_dialog ('Save file',@extensions); - $dialog->set_current_folder ($open_in) if(defined $open_in); - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my $ext = $dialog->get_filter; - $ext=$ext->get_name; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - - $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; - - $self->object_add_attribute("graph_save","name","$path/$name"); - $self->object_add_attribute("graph_save","extension",$ext); - $self->object_add_attribute("graph_save","enable",1); - set_gui_status($self,"ref",5); - } - $dialog->destroy; + my $self= shift; + my $file; + my $title ='Save as'; + my @extensions=('png','jpeg'); + my $open_in=undef; + my $dialog = save_file_dialog ('Save file',@extensions); + $dialog->set_current_folder ($open_in) if(defined $open_in); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my $ext = $dialog->get_filter; + $ext=$ext->get_name; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; + $self->object_add_attribute("graph_save","name","$path/$name"); + $self->object_add_attribute("graph_save","extension",$ext); + $self->object_add_attribute("graph_save","enable",1); + set_gui_status($self,"ref",5); + } + $dialog->destroy; } sub generate_trace_dot_file{ - my $self=shift; - my $dotfile= + my $self=shift; + my $dotfile= "digraph G { - graph [ layout = neato, rankdir = LR , splines=polyline, overlap = false]; - + graph [ layout = neato, rankdir = LR , splines=polyline, overlap = false]; + "; - - - #add connections - - my @traces= get_trace_list($self,'raw'); - foreach my $p (@traces) { - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); - $dotfile=$dotfile."\"$src\" -> \"$dst\" [label=\"$Mbytes\" ];\n"; - } - - $dotfile=$dotfile."\n}\n"; - return $dotfile; - + my @traces= get_trace_list($self,'raw'); + foreach my $p (@traces) { + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); + $dotfile=$dotfile."\"$src\" -> \"$dst\" [label=\"$Mbytes\" ];\n"; + } + $dotfile=$dotfile."\n}\n"; + return $dotfile; } - sub generate_map_dot_file{ - my $self=shift; - my $dotfile= + my $self=shift; + my $dotfile= "digraph G { - graph [layout = neato, rankdir = LR ,splines=spline, overlap = false]; - node[shape=record]; - - "; - -#add nodes - my @tasks=get_all_tasks($self,"merge"); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); - my %pos=get_endp_pos($self); - my @mappedtasks; - for(my $i=0; $i<$NE; $i++){ - my $task=get_task_assigned_to_tile($self,$i); - push(@mappedtasks,$task) if (defined $task); - - $task= "_" if (!defined $task); - my $n = "tile($i)" ; - my $m = "tile($i)" ; - my $node = "\"$m\""; - my $label = "\" $n| $task\"" ; - - $dotfile=$dotfile." + graph [layout = neato, rankdir = LR ,splines=spline, overlap = false]; + node[shape=record]; + + "; + +#add nodes + my @tasks=get_all_tasks($self,"merge"); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); + my %pos=get_endp_pos($self); + my @mappedtasks; + for(my $i=0; $i<$NE; $i++){ + my $task=get_task_assigned_to_tile($self,$i); + push(@mappedtasks,$task) if (defined $task); + $task= "_" if (!defined $task); + my $n = "tile($i)" ; + my $m = "tile($i)" ; + my $node = "\"$m\""; + my $label = "\" $n| $task\"" ; + $dotfile=$dotfile." $node\[ - label = $label + label = $label pos = $pos{$i} -];"; - - } - $dotfile=$dotfile."\n\n"; - #add connections - my @traces= get_trace_list($self,'merge'); - my %src_dst; - - foreach my $p (@traces){ - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'merge',$p); - my $src_tile=get_task_give_tile($self,"$src"); - my $dst_tile=get_task_give_tile($self,"$dst"); - next if ($src_dst{"${src_tile}_$dst_tile"}); #make sure there will be only one arow betwenn each source destination tile - next if ( $src_tile eq "-" || $dst_tile eq "-" ); - $dotfile=$dotfile." \"$src_tile\" : \"S$src\" -> \"$dst_tile\" : \"R$dst\" ;\n" if((defined $src_tile )&& (defined $dst_tile)); - $src_dst{"${src_tile}_$dst_tile"}=1; - } - $dotfile=$dotfile."\n}\n"; - return $dotfile; +];"; + } + $dotfile=$dotfile."\n\n"; + #add connections + my @traces= get_trace_list($self,'merge'); + my %src_dst; + foreach my $p (@traces){ + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'merge',$p); + my $src_tile=get_task_give_tile($self,"$src"); + my $dst_tile=get_task_give_tile($self,"$dst"); + next if ($src_dst{"${src_tile}_$dst_tile"}); #make sure there will be only one arow betwenn each source destination tile + next if ( $src_tile eq "-" || $dst_tile eq "-" ); + $dotfile=$dotfile." \"$src_tile\" : \"S$src\" -> \"$dst_tile\" : \"R$dst\" ;\n" if((defined $src_tile )&& (defined $dst_tile)); + $src_dst{"${src_tile}_$dst_tile"}=1; + } + $dotfile=$dotfile."\n}\n"; + return $dotfile; } - - - sub show_trace_diagram { - my ($self,$type)=@_; - my $table=def_table(20,20,FALSE); - - my $window=def_popwin_size(80,80,"Trace Diagram",'percent'); - my $scrolled_win =add_widget_to_scrolled_win(); - - $window->add ($table); - - my $plus = def_image_button('icons/plus.png',undef,TRUE); - my $minues = def_image_button('icons/minus.png',undef,TRUE); - my $save = def_image_button('icons/save.png',undef,TRUE); - my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); - set_tip($dot_file, "Show dot file."); - - - - my $scale=$self->object_get_attribute("${type}_diagram","scale"); - $scale= 1 if (!defined $scale); - - - - - my $col=0; - $table->attach ($plus , $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($minues, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($save, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach ($dot_file, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - $table->attach_defaults ($scrolled_win, 0, 20, 1, 20); #,'fill','shrink',2,2); - - while ($col<20){ - my $tmp=gen_label_in_left(''); - $table->attach_defaults ($tmp, $col, $col+1,0,1);$col++; - } - - $plus -> signal_connect("clicked" => sub{ - $scale*=1.1 if ($scale <10); - $self->object_add_attribute("${type}_diagram","scale", $scale ); - my $dotfile = get_dot_file_text($self,$type); - generate_and_show_graph_using_graphviz ($self,$scrolled_win,$dotfile, "${type}_diagram"); - }); - $minues -> signal_connect("clicked" => sub{ - $scale*=.9 if ($scale >0.1); ; - $self->object_add_attribute("${type}_diagram","scale", $scale ); - gen_show_diagram ($self,$scrolled_win,$type,"${type}_diagram"); - }); - $save-> signal_connect("clicked" => sub{ - save_inline_diagram_as ($self); - show_trace_diagram($self,$type); - $window->destroy; - }); - - $dot_file-> signal_connect("clicked" => sub{ - my $dotfile = get_dot_file_text($self,$type); - show_text_in_scrolled_win($self,$scrolled_win, $dotfile); - - }); - - gen_show_diagram ($self,$scrolled_win,$type,"${type}_diagram"); - - $window->show_all(); -} - - - - - + my ($self,$type)=@_; + my $table=def_table(20,20,FALSE); + my $window=def_popwin_size(80,80,"Trace Diagram",'percent'); + my $scrolled_win =add_widget_to_scrolled_win(); + $window->add ($table); + my $plus = def_image_button('icons/plus.png',undef,TRUE); + my $minues = def_image_button('icons/minus.png',undef,TRUE); + my $save = def_image_button('icons/save.png',undef,TRUE); + my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); + set_tip($dot_file, "Show dot file."); + my $scale=$self->object_get_attribute("${type}_diagram","scale"); + $scale= 1 if (!defined $scale); + my $col=0; + $table->attach ($plus , $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($minues, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($save, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach ($dot_file, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; + $table->attach_defaults ($scrolled_win, 0, 20, 1, 20); #,'fill','shrink',2,2); + + while ($col<20){ + my $tmp=gen_label_in_left(''); + $table->attach_defaults ($tmp, $col, $col+1,0,1);$col++; + } + + $plus -> signal_connect("clicked" => sub{ + $scale*=1.1 if ($scale <10); + $self->object_add_attribute("${type}_diagram","scale", $scale ); + my $dotfile = get_dot_file_text($self,$type); + generate_and_show_graph_using_graphviz ($self,$scrolled_win,$dotfile, "${type}_diagram"); + }); + $minues -> signal_connect("clicked" => sub{ + $scale*=.9 if ($scale >0.1); ; + $self->object_add_attribute("${type}_diagram","scale", $scale ); + gen_show_diagram ($self,$scrolled_win,$type,"${type}_diagram"); + }); + $save-> signal_connect("clicked" => sub{ + save_inline_diagram_as ($self); + show_trace_diagram($self,$type); + $window->destroy; + }); + + $dot_file-> signal_connect("clicked" => sub{ + my $dotfile = get_dot_file_text($self,$type); + show_text_in_scrolled_win($self,$scrolled_win, $dotfile); + + }); + gen_show_diagram ($self,$scrolled_win,$type,"${type}_diagram"); + $window->show_all(); +} sub node_connection{ - my ($sn,$sx,$sy,$sp,$dn,$dx,$dy,$dp,$gtype)=@_; - $gtype="comp" if(!defined $gtype); - - my $spp = (defined $sp && $gtype eq "comp" ) ? ":\"p$sp\"" : " "; - my $dpp = (defined $dp && $gtype eq "comp" ) ? ":\"p$dp\"" : " "; - my $sname = (defined $sy) ? "\"$sn${sx}_${sy}\"" : "\"$sn${sx}\""; - my $dname = (defined $dy) ? "\"$dn${dx}_${dy}\"" : "\"$dn${dx}\""; - - my $t= "$sname $spp -> $dname $dpp [ dir=none];\n"; - return $t; + my ($sn,$sx,$sy,$sp,$dn,$dx,$dy,$dp,$gtype)=@_; + $gtype="comp" if(!defined $gtype); + + my $spp = (defined $sp && $gtype eq "comp" ) ? ":\"p$sp\"" : " "; + my $dpp = (defined $dp && $gtype eq "comp" ) ? ":\"p$dp\"" : " "; + my $sname = (defined $sy) ? "\"$sn${sx}_${sy}\"" : "\"$sn${sx}\""; + my $dname = (defined $dy) ? "\"$dn${dx}_${dy}\"" : "\"$dn${dx}\""; + + my $t= "$sname $spp -> $dname $dpp [ dir=none];\n"; + return $t; } sub node_connection2{ - my ($sn,$sx,$sp,$dn,$dx,$dy,$dp)=@_; - my $spp = (defined $sp) ? ":\"p$sp\"" : " "; - my $dpp = (defined $dp) ? ":\"p$dp\"" : " "; - my $sname = "\"$sn${sx}\""; - my $dname = "\"$dn${dx}\""; - - my $t= "$sname $spp -> $dname $dpp [ dir=none];\n"; - return $t; + my ($sn,$sx,$sp,$dn,$dx,$dy,$dp)=@_; + my $spp = (defined $sp) ? ":\"p$sp\"" : " "; + my $dpp = (defined $dp) ? ":\"p$dp\"" : " "; + my $sname = "\"$sn${sx}\""; + my $dname = "\"$dn${dx}\""; + my $t= "$sname $spp -> $dname $dpp [ dir=none];\n"; + return $t; } - - ################################## # -################################## - - - - +################################# sub generate_heat_map_table{ - my ($d)=@_ ; - - return (def_table (1, 1, FALSE),def_table (1, 1, FALSE)) if (!defined $d); - my %data=%{$d}; - my @xs = (sort {$a<=>$b} keys %data); - - - - - my $max=0; - #for(my $y=0; $y<$dim; $y++){ - # for(my $x=0; $x<$dim; $x++){ - foreach my $y (@xs){ - foreach my $x (@xs){ - #$data{$x}{$y}=int(rand(50000)); - #$data{$x}{$y}=$y*64+$x; - $max = $data{$x}{$y} if( $max < $data{$x}{$y}); - } - } - - - my $width_max = length int $max; - - my $table = def_table (1, 1, FALSE); - - #for(my $y=0; $y<$dim; $y++){ - foreach my $y (@xs){ - my $l=gen_label_in_center("$y"); - $table->attach ($l, $y+1,$y+2,0,1,'expand','shrink',2,2); - } - #for(my $x=0; $x<$dim; $x++){ - foreach my $x (@xs){ - my $l=gen_label_in_center("$x"); - $table->attach ($l, 0,1,$x+1,$x+2,'expand','shrink',2,2); - } - - #for(my $y=0; $y<$dim; $y++){ - # for(my $x=0; $x<$dim; $x++){ - foreach my $y (@xs){ - foreach my $x (@xs){ - my $d=$data{$x}{$y}; - my $c = int (((5*$d))/($max+1)); - my $v = length int $d; - until ($v >= $width_max){ - $d=" ".$d; - $v++; - } - - my $l =gen_colored_label( " " ,32+$c); - set_tip($l,"E[$x]->E[$y]=$d"); - $table->attach ($l, $y+1,$y+2,$x+1,$x+2,'expand','shrink',2,2); - } - - } - - my $scale = def_table (1, 1, FALSE); - my $v=gen_label_in_center("0"); - $scale->attach ($v, 1,2,0,1,'expand','shrink',2,2); - for (my $i=0; $i<5; $i++){ - my $l =gen_colored_label( " " ,32+$i); - my $val =int( (2*$i+1)*$max/10); - my $v=gen_label_in_center($val); - $scale->attach ($v, 0,1,$i+1,$i+2,'expand','shrink',2,2); - $scale->attach ($l, 1,2,$i+1,$i+2,'expand','shrink',2,2); - $scale->attach (gen_label_in_center("$max"), 1,2,$i+2,$i+3,'expand','shrink',2,2) if($i==4); - } - - - return ($table,$scale); - -} - + my ($d)=@_ ; + return (def_table (1, 1, FALSE),def_table (1, 1, FALSE)) if (!defined $d); + my %data=%{$d}; + my @xs = (sort {$a<=>$b} keys %data); + my $max=0; + #for(my $y=0; $y<$dim; $y++){ + # for(my $x=0; $x<$dim; $x++){ + foreach my $y (@xs){ + foreach my $x (@xs){ + #$data{$x}{$y}=int(rand(50000)); + #$data{$x}{$y}=$y*64+$x; + $max = $data{$x}{$y} if( $max < $data{$x}{$y}); + } + } + my $width_max = length int $max; + my $table = def_table (1, 1, FALSE); + #for(my $y=0; $y<$dim; $y++){ + foreach my $y (@xs){ + my $l=gen_label_in_center("$y"); + $table->attach ($l, $y+1,$y+2,0,1,'expand','shrink',2,2); + } + #for(my $x=0; $x<$dim; $x++){ + foreach my $x (@xs){ + my $l=gen_label_in_center("$x"); + $table->attach ($l, 0,1,$x+1,$x+2,'expand','shrink',2,2); + } + #for(my $y=0; $y<$dim; $y++){ + # for(my $x=0; $x<$dim; $x++){ + foreach my $y (@xs){ + foreach my $x (@xs){ + my $d=$data{$x}{$y}; + my $c = int (((5*$d))/($max+1)); + my $v = length int $d; + until ($v >= $width_max){ + $d=" ".$d; + $v++; + } + my $l =gen_colored_label( " " ,32+$c); + set_tip($l,"E[$x]->E[$y]=$d"); + $table->attach ($l, $y+1,$y+2,$x+1,$x+2,'expand','shrink',2,2); + } + } + my $scale = def_table (1, 1, FALSE); + my $v=gen_label_in_center("0"); + $scale->attach ($v, 1,2,0,1,'expand','shrink',2,2); + for (my $i=0; $i<5; $i++){ + my $l =gen_colored_label( " " ,32+$i); + my $val =int( (2*$i+1)*$max/10); + my $v=gen_label_in_center($val); + $scale->attach ($v, 0,1,$i+1,$i+2,'expand','shrink',2,2); + $scale->attach ($l, 1,2,$i+1,$i+2,'expand','shrink',2,2); + $scale->attach (gen_label_in_center("$max"), 1,2,$i+2,$i+3,'expand','shrink',2,2) if($i==4); + } + return ($table,$scale); +} sub generate_heat_map_img_file{ - my ($d,$image_file,$title)=@_ ; - return if (!defined $d); - my %hash=%{$d}; - my @data; - my @xs = (sort {$a<=>$b} keys %hash); - foreach my $y (@xs){ - my @b; - push (@data ,\@b) if ($y!=0); - foreach my $x (@xs){ - my @a=($x,$y, $hash{$x}{$y}); - push (@data ,\@a); - } - - } - -my $length = @xs; -$length+=1; - -my $chart = Chart::Gnuplot->new( - bg => 'white', - view => 'map', - palette => 'defined (0 0 0 1, 1 1 1 0, 2 1 0 0)', - output => "$image_file", - title => "$title", - xlabel => 'Endp-ID', - ylabel => 'Endp-ID', - xrange => [-1, $length], - size => 'ratio -1', - xtics => { - labels => \@xs, - }, - ytics => { - labels => \@xs, - }, - mxtics => '2', - mytics => '2', - border => undef, - grid => 'front mxtics mytics lw 1.5 lt -1 lc rgb \'white\'', - -); -my $dataSet = Chart::Gnuplot::DataSet->new( - points => \@data, - view => 'map', - type => 'matrix', - using => "1:2:3 with image", -); - - -$chart->plot2d($dataSet); - - - - - + my ($d,$image_file,$title)=@_ ; + return if (!defined $d); + my %hash=%{$d}; + my @data; + my @xs = (sort {$a<=>$b} keys %hash); + foreach my $y (@xs){ + my @b; + push (@data ,\@b) if ($y!=0); + foreach my $x (@xs){ + my @a=($x,$y, $hash{$x}{$y}); + push (@data ,\@a); + } + } + my $length = @xs; + $length+=1; + my $chart = Chart::Gnuplot->new( + bg => 'white', + view => 'map', + palette => 'defined (0 0 0 1, 1 1 1 0, 2 1 0 0)', + output => "$image_file", + title => "$title", + xlabel => 'Endp-ID', + ylabel => 'Endp-ID', + xrange => [-1, $length], + size => 'ratio -1', + xtics => { + labels => \@xs, + }, + ytics => { + labels => \@xs, + }, + mxtics => '2', + mytics => '2', + border => undef, + grid => 'front mxtics mytics lw 1.5 lt -1 lc rgb \'white\'', + ); + my $dataSet = Chart::Gnuplot::DataSet->new( + points => \@data, + view => 'map', + type => 'matrix', + using => "1:2:3 with image", + ); + $chart->plot2d($dataSet); } - sub generate_heat_map_dot_file{ - my ($data,$dim)=@_ ; - my $dotfile= + my ($data,$dim)=@_ ; + my $dotfile= "digraph G { - graph [layout = neato, rankdir = RL , splines = true, overlap = true]; - node[shape=record]; - "; - for(my $y=0; $y<$dim; $y++){ - for(my $x=0; $x<$dim; $x++){ - my $tx=$x*2+0.5; - my $ty=($dim-$y-1)*2+0.5; - my $w=2; - - $tx/=2; - $ty/=2; - $w/=2; - - - $dotfile.=" - \"t${x}_$y\"[ - label = \"8822255\" + graph [layout = neato, rankdir = RL , splines = true, overlap = true]; + node[shape=record]; + "; + for(my $y=0; $y<$dim; $y++){ + for(my $x=0; $x<$dim; $x++){ + my $tx=$x*2+0.5; + my $ty=($dim-$y-1)*2+0.5; + my $w=2; + $tx/=2; + $ty/=2; + $w/=2; + $dotfile.=" + \"t${x}_$y\"[ + label = \"8822255\" pos = \"$tx,$ty!\" width =$w height=$w - style=filled - fontsize=\"12\" - fillcolor=orange + style=filled + fontsize=\"12\" + fillcolor=orange ]; -" - } - } - - $dotfile=$dotfile."\n}\n"; - return $dotfile; - +" + } + } + $dotfile=$dotfile."\n}\n"; + return $dotfile; } - sub generate_mesh_dot_file{ - my $self=shift; - - my $gtype=$self->object_get_attribute("tile_diagram","gtype"); - - my $dotfile= + my $self=shift; + my $gtype=$self->object_get_attribute("tile_diagram","gtype"); + my $dotfile= "digraph G { - graph [layout = neato, rankdir = RL , splines = true, overlap = true]; - - - node[shape=record]; - - "; - + graph [layout = neato, rankdir = RL , splines = true, overlap = true]; + + + node[shape=record]; + + "; + #five_port_router [ -# label="{ |2| } | {3|R0|1} | { |4|0}" -# shape=record -# color=blue -# style=filled -# fillcolor=blue -#]; - +# label="{ |2| } | {3|R0|1} | { |4|0}" +# shape=record +# color=blue +# style=filled +# fillcolor=blue +#]; + #add nodes - my $nx=$self->object_get_attribute('noc_param','T1'); - my $ny=$self->object_get_attribute('noc_param','T2'); - my $nz=$self->object_get_attribute('noc_param','T3'); - - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); - - - my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); - - - my $btrace= ($topology eq '"TORUS"' || $topology eq '"RING"'); - my $oned = ($topology eq '"RING"' || $topology eq '"LINE"'); - - #generate endpoints - for(my $y=0; $y<$ny; $y++){ - for(my $x=0; $x<$nx; $x++){ - for(my $z=0; $z<$nz; $z++){ - my $id=($y*$nx+$x)*$nz+$z; - my $offsetx = ($z==0 || $z==3) ? 1.05 : -1.05; - my $offsety = ($z==0 || $z==1) ? -0.85 : +0.85; - my $tx=$x*3+$offsetx; - my $ty=($ny-$y-1)*2.5+1+$offsety; - $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); - }}} - - if($topology eq '"FMESH"' ) { - my $tmp = $ny*$nx*$nz; - for(my $x=0; $x<$nx; $x++){ - #top edges - my $id=$tmp + $x; - my $tx=$x*3; - my $ty=($ny)*2.5-.5; - $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); - get_connected_router_id_to_endp($self,$id); - - - - #down edges - $id= $tmp + $nx +$x; - $tx=$x*3; - $ty=-.5; - $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); - } - for(my $y=0; $y<$ny; $y++){ - #right edges - my $id= $tmp + 2*$nx +$y; - my $tx=-1.5; - my $ty=($ny-$y-1)*2.5+1; - $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); - - - #left edges - $id= $tmp + 2*$nx+$ny +$y; - $tx=$nx*3-1.5; - $ty=($ny-$y-1)*2.5+1; - $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); - - } - - } - - -#generate routers - for(my $y=0; $y<$ny; $y++){ - for(my $x=0; $x<$nx; $x++){ - my $e0 = '0'; - my $e1 = ($nz>1)? ( ($oned)? '3':'5') : ' '; - my $e2 = ($nz>2)? ( ($oned)? '4':'6') : ' '; - my $e3 = ($nz>3)? ( ($oned)? '5':'7') : ' '; - - my $id=$y*$nx+$x; - my $n = "R${id}"; - my $label = ($oned)? - "\{$e2 | |$e3 \} | \{2|$n|1\} | \{$e1 | |$e0\}" - :"\{$e2 |2|$e3 \} | \{3|$n|1\} | \{$e1 |4|$e0\}"; - my $xx=$x*3; - my $yy=($ny-$y-1)*2.5+1; - - - - - $dotfile.=get_router_dot_file($n,$label,"$xx,$yy!",$gtype); - - - }} - - - $dotfile=$dotfile."\n\n"; - - #add connections - for(my $y=0; $y<$ny; $y++){ - for(my $x=0; $x<$nx; $x++){ - - $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,1,'R',get_router_num($self,($x+1),$y),undef,3,$gtype) if($x <$nx-1); - $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,1,'R',get_router_num($self,0,$y),undef,3,$gtype) if($x == ($nx-1) && $btrace); - $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,2,'R',get_router_num($self,$x,($y-1)),undef,4,$gtype)if($y>0) ; - $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,2,'R',get_router_num($self,$x,($ny-1)),undef,4,$gtype) if($y ==0 && $btrace && !$oned); - # $dotfile=$dotfile.node_connection('R',$x,$y,0,'T',$x,$y); - }} -if($topology eq '"FMESH"' ) { - for(my $id=0; $id<$NE; $id++){ - my $rid= get_connected_router_id_to_endp($self,$id); - my $tmp = $nx*$ny*$nz; - my $p = ($id<$tmp)? $id%$nz+5 : - ($id<$tmp+$nx)? 2 : - ($id<$tmp+2*$nx)? 4 : - ($id<$tmp+2*$nx+$ny)? 3:1; - $dotfile=$dotfile.node_connection('R',$rid,undef,$p,'T',$id,undef,undef,$gtype); - - } - -}else{ - for(my $id=0; $id<$NE; $id++){ - my $rid=int($id/$nz); - my $p = $id%$nz+5; - $dotfile=$dotfile.node_connection('R',$rid,undef,$p,'T',$id,undef,undef,$gtype); - - } -} - $dotfile=$dotfile."\n}\n"; - return $dotfile; - - - + my $nx=$self->object_get_attribute('noc_param','T1'); + my $ny=$self->object_get_attribute('noc_param','T2'); + my $nz=$self->object_get_attribute('noc_param','T3'); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); + my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); + my $btrace= ($topology eq '"TORUS"' || $topology eq '"RING"'); + my $oned = ($topology eq '"RING"' || $topology eq '"LINE"'); + #generate endpoints + for(my $y=0; $y<$ny; $y++){ + for(my $x=0; $x<$nx; $x++){ + for(my $z=0; $z<$nz; $z++){ + my $id=($y*$nx+$x)*$nz+$z; + my $offsetx = ($z==0 || $z==3) ? 1.05 : -1.05; + my $offsety = ($z==0 || $z==1) ? -0.85 : +0.85; + my $tx=$x*3+$offsetx; + my $ty=($ny-$y-1)*2.5+1+$offsety; + $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); + }}} + + if($topology eq '"FMESH"' ) { + my $tmp = $ny*$nx*$nz; + for(my $x=0; $x<$nx; $x++){ + #top edges + my $id=$tmp + $x; + my $tx=$x*3; + my $ty=($ny)*2.5-.5; + $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); + get_connected_router_id_to_endp($self,$id); + #down edges + $id= $tmp + $nx +$x; + $tx=$x*3; + $ty=-.5; + $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); + } + for(my $y=0; $y<$ny; $y++){ + #right edges + my $id= $tmp + 2*$nx +$y; + my $tx=-1.5; + my $ty=($ny-$y-1)*2.5+1; + $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); + #left edges + $id= $tmp + 2*$nx+$ny +$y; + $tx=$nx*3-1.5; + $ty=($ny-$y-1)*2.5+1; + $dotfile.=get_record_endp_dot_file("T$id","T$id", "$tx,$ty!"); + } + } + #generate routers + for(my $y=0; $y<$ny; $y++){ + for(my $x=0; $x<$nx; $x++){ + my $e0 = '0'; + my $e1 = ($nz>1)? ( ($oned)? '3':'5') : ' '; + my $e2 = ($nz>2)? ( ($oned)? '4':'6') : ' '; + my $e3 = ($nz>3)? ( ($oned)? '5':'7') : ' '; + my $id=$y*$nx+$x; + my $n = "R${id}"; + my $label = ($oned)? + "\{$e2 | |$e3 \} | \{2|$n|1\} | \{$e1 | |$e0\}" + :"\{$e2 |2|$e3 \} | \{3|$n|1\} | \{$e1 |4|$e0\}"; + my $xx=$x*3; + my $yy=($ny-$y-1)*2.5+1; + $dotfile.=get_router_dot_file($n,$label,"$xx,$yy!",$gtype); + } + } + $dotfile=$dotfile."\n\n"; + #add connections + for(my $y=0; $y<$ny; $y++){ + for(my $x=0; $x<$nx; $x++){ + $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,1,'R',get_router_num($self,($x+1),$y),undef,3,$gtype) if($x <$nx-1); + $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,1,'R',get_router_num($self,0,$y),undef,3,$gtype) if($x == ($nx-1) && $btrace); + $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,2,'R',get_router_num($self,$x,($y-1)),undef,4,$gtype)if($y>0) ; + $dotfile=$dotfile.node_connection('R',get_router_num($self,$x,$y),undef,2,'R',get_router_num($self,$x,($ny-1)),undef,4,$gtype) if($y ==0 && $btrace && !$oned); + # $dotfile=$dotfile.node_connection('R',$x,$y,0,'T',$x,$y); + } + } + if($topology eq '"FMESH"' ) { + for(my $id=0; $id<$NE; $id++){ + my $rid= get_connected_router_id_to_endp($self,$id); + my $tmp = $nx*$ny*$nz; + my $p = ($id<$tmp)? $id%$nz+5 : + ($id<$tmp+$nx)? 2 : + ($id<$tmp+2*$nx)? 4 : + ($id<$tmp+2*$nx+$ny)? 3:1; + $dotfile=$dotfile.node_connection('R',$rid,undef,$p,'T',$id,undef,undef,$gtype); + } + }else{ + for(my $id=0; $id<$NE; $id++){ + my $rid=int($id/$nz); + my $p = $id%$nz+5; + $dotfile=$dotfile.node_connection('R',$rid,undef,$p,'T',$id,undef,undef,$gtype); + } + } + $dotfile=$dotfile."\n}\n"; + return $dotfile; } + sub get_endp_pos { - my $self=shift; - my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); - my %pos; - if($topology eq '"FATTREE"' || $topology eq '"TREE"'){ - - for(my $i=0; $i<$NE; $i++){ - $pos{$i} = "\"$i,0!\""; - } - return %pos; - } - #($topology eq '"TORUS"' || $topology eq '"RING"' || $topology eq '"RING"' || $topology eq '"LINE"'); - - my $nx=$self->object_get_attribute('noc_param','T1'); - my $ny=$self->object_get_attribute('noc_param','T2'); - my $nz=$self->object_get_attribute('noc_param','T3'); - - - #generate endpoints - for(my $y=0; $y<$ny; $y++){ - for(my $x=0; $x<$nx; $x++){ - for(my $z=0; $z<$nz; $z++){ - my $id=($y*$nx+$x)*$nz+$z; - my $offsetx = ($z==0 || $z==3) ? 1.05 : -1.05; - my $offsety = ($z==0 || $z==1) ? -0.85 : +0.85; - my $tx=$x*3+$offsetx; - my $ty=($ny-$y-1)*2.5+1+$offsety; - $pos{$id} = "\"$tx,$ty!\""; - } - } - } - return %pos; + my $self=shift; + my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); + my %pos; + if($topology eq '"FATTREE"' || $topology eq '"TREE"'){ + for(my $i=0; $i<$NE; $i++){ + $pos{$i} = "\"$i,0!\""; + } + return %pos; + } + #($topology eq '"TORUS"' || $topology eq '"RING"' || $topology eq '"RING"' || $topology eq '"LINE"'); + my $nx=$self->object_get_attribute('noc_param','T1'); + my $ny=$self->object_get_attribute('noc_param','T2'); + my $nz=$self->object_get_attribute('noc_param','T3'); + #generate endpoints + for(my $y=0; $y<$ny; $y++){ + for(my $x=0; $x<$nx; $x++){ + for(my $z=0; $z<$nz; $z++){ + my $id=($y*$nx+$x)*$nz+$z; + my $offsetx = ($z==0 || $z==3) ? 1.05 : -1.05; + my $offsety = ($z==0 || $z==1) ? -0.85 : +0.85; + my $tx=$x*3+$offsetx; + my $ty=($ny-$y-1)*2.5+1+$offsety; + $pos{$id} = "\"$tx,$ty!\""; + } + } + } + return %pos; } sub get_record_endp_dot_file { - my ($name,$label,$pos)=@_; - + my ($name,$label,$pos)=@_; return "$name\[ - label = \"$label\" + label = \"$label\" pos = \"$pos\" shape=record - color=orange - style=filled - fillcolor=orange + color=orange + style=filled + fillcolor=orange ]; -" -; +"; } sub get_router_dot_file { - my ($name,$label,$pos,$type)=@_; - - - return ($type eq 'comp')? "\"$name\"\[ - label=\"$label\" + my ($name,$label,$pos,$type)=@_; + return ($type eq 'comp')? "\"$name\"\[ + label=\"$label\" pos = \"$pos\" shape=record - color=blue - style=filled - fillcolor=blue -]; + color=blue + style=filled + fillcolor=blue +]; " : "\"$name\"\[ - label=\"$name\" + label=\"$name\" pos = \"$pos\" shape=circle - color=blue - style=filled - fillcolor=blue -]; -" -; - - + color=blue + style=filled + fillcolor=blue +]; +"; } sub generate_fattree_dot_file{ - my $self=shift; - my $gtype=$self->object_get_attribute("tile_diagram","gtype"); - - - my $dotfile= + my $self=shift; + my $gtype=$self->object_get_attribute("tile_diagram","gtype"); + my $dotfile= "digraph G { - graph [layout = neato, rankdir = LR , splines = true, overlap = true]; - node[shape=record]; - "; - + graph [layout = neato, rankdir = LR , splines = true, overlap = true]; + node[shape=record]; + "; #add nodes my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - - my $k=$self->object_get_attribute('noc_param','T1'); - my $nl=$self->object_get_attribute('noc_param','T2'); - my @bp; - my @hp; - for(my $p=0; $p<$k; $p++) {push (@bp,"$p");} - for(my $p=$k; $p<2*$k; $p++) {push (@hp,"$p");} - my $bp= join("|",@bp); - my $hp= join("|",@hp); - #my $NC= powi( $k,$nl ); #total endpoints - my $NL= $NE/$k ; #number of nodes in each layer - - -#add endpoints -for(my $i=0; $i<$NE; $i++){ - my $x=$i%$k; - my $y=int($i/$k); - + my $k=$self->object_get_attribute('noc_param','T1'); + my $nl=$self->object_get_attribute('noc_param','T2'); + my @bp; + my @hp; + for(my $p=0; $p<$k; $p++) {push (@bp,"$p");} + for(my $p=$k; $p<2*$k; $p++) {push (@hp,"$p");} + my $bp= join("|",@bp); + my $hp= join("|",@hp); + #my $NC= powi( $k,$nl ); #total endpoints + my $NL= $NE/$k ; #number of nodes in each layer + #add endpoints + for(my $i=0; $i<$NE; $i++){ + my $x=$i%$k; + my $y=int($i/$k); $dotfile=$dotfile."T$i\[ - label = \"T$i\" + label = \"T$i\" pos = \"$i,0!\" shape=house margin=0 - color=orange - style=filled - fillcolor=orange + color=orange + style=filled + fillcolor=orange ]; "; - } - - #add roots - for(my $pos=0; $pos<$NL; $pos++){ - my $x=($k)*$pos+($k/2)-0.5; - my $y= 1.5*($nl-1)+1; - my $r=$pos; - my $label = "\{R$r\}|\{$bp\}"; - - $dotfile.=get_router_dot_file("R$r",$label,"$x,$y!",$gtype); - - } - - #add leaves - for(my $l=1; $l<$nl; $l++){ - for(my $pos=0; $pos<$NL; $pos++){ - my $x=($k)*$pos+($k/2)-0.5; - my $y= 1.5*($nl-$l-1)+1; - my $r=$NL*$l+$pos; - my $label = "\{$hp\}|\{R$r\}|\{$bp\}"; - - $dotfile.=get_router_dot_file("R$r",$label,"$x,$y!",$gtype); - - } - } - - - - #connect all down input chanels - my $n=$nl; - my $nPos = powi( $k, $n-1); - my $chan_per_direction = ($k * powi( $k , $n-1 )); #up or down - my $chan_per_level = 2*($k * powi( $k , $n-1 )); #up+down - - for (my $level = 0; $level<$n-1; $level++){ - #input chanel are numbered interleavely, the interleaev depends on level - my $routers_per_neighborhood = powi($k,$n-1-($level)); - my $routers_per_branch = powi($k,$n-1-($level+1)); - my $level_offset = $routers_per_neighborhood*$k; - for ( my $pos = 0; $pos < $nPos; ++$pos ) { - my $neighborhood = int($pos/$routers_per_neighborhood); - my $neighborhood_pos = $pos % $routers_per_neighborhood; - for ( my $port = 0; $port < $k; ++$port ) { - my $link = - (($level+1)*$chan_per_level - $chan_per_direction) #which levellevel - +$neighborhood*$level_offset #region in level - +$port*$routers_per_branch*$k #sub region in region - +($neighborhood_pos)%$routers_per_branch*$k #router in subregion - +($neighborhood_pos)/$routers_per_branch; #port on router - - #int link = (level*chan_per_level - chan_per_direction) + pos*k + port ; - my $connect_l= int(($link+$chan_per_direction)/$chan_per_level); - my $tmp=(($link+$chan_per_direction) % $chan_per_level); - my $connect_pos= int($tmp/$k); - my $connect_port= ($tmp%$k)+$k; - my $id1=$NL*$level+$pos; - my $connect_id=$NL*$connect_l+$connect_pos; - $dotfile=$dotfile.node_connection('R',$id1,undef,$port,'R',$connect_id,undef,$connect_port,$gtype); - } - } - } - - #add endpoints connection - for(my $i=0; $i<$NE; $i++){ - my $r= $NL*($nl-1)+int($i/$k); - $dotfile=$dotfile.node_connection('T',$i,undef,undef,'R',$r,undef,$i%($k),$gtype); - - } - $dotfile=$dotfile."\n}\n"; - return $dotfile; + } + #add roots + for(my $pos=0; $pos<$NL; $pos++){ + my $x=($k)*$pos+($k/2)-0.5; + my $y= 1.5*($nl-1)+1; + my $r=$pos; + my $label = "\{R$r\}|\{$bp\}"; + $dotfile.=get_router_dot_file("R$r",$label,"$x,$y!",$gtype); + } + #add leaves + for(my $l=1; $l<$nl; $l++){ + for(my $pos=0; $pos<$NL; $pos++){ + my $x=($k)*$pos+($k/2)-0.5; + my $y= 1.5*($nl-$l-1)+1; + my $r=$NL*$l+$pos; + my $label = "\{$hp\}|\{R$r\}|\{$bp\}"; + $dotfile.=get_router_dot_file("R$r",$label,"$x,$y!",$gtype); + } + } + #connect all down input chanels + my $n=$nl; + my $nPos = powi( $k, $n-1); + my $chan_per_direction = ($k * powi( $k , $n-1 )); #up or down + my $chan_per_level = 2*($k * powi( $k , $n-1 )); #up+down + for (my $level = 0; $level<$n-1; $level++){ + #input chanel are numbered interleavely, the interleaev depends on level + my $routers_per_neighborhood = powi($k,$n-1-($level)); + my $routers_per_branch = powi($k,$n-1-($level+1)); + my $level_offset = $routers_per_neighborhood*$k; + for ( my $pos = 0; $pos < $nPos; ++$pos ) { + my $neighborhood = int($pos/$routers_per_neighborhood); + my $neighborhood_pos = $pos % $routers_per_neighborhood; + for ( my $port = 0; $port < $k; ++$port ) { + my $link = + (($level+1)*$chan_per_level - $chan_per_direction) #which levellevel + +$neighborhood*$level_offset #region in level + +$port*$routers_per_branch*$k #sub region in region + +($neighborhood_pos)%$routers_per_branch*$k #router in subregion + +($neighborhood_pos)/$routers_per_branch; #port on router + #int link = (level*chan_per_level - chan_per_direction) + pos*k + port ; + my $connect_l= int(($link+$chan_per_direction)/$chan_per_level); + my $tmp=(($link+$chan_per_direction) % $chan_per_level); + my $connect_pos= int($tmp/$k); + my $connect_port= ($tmp%$k)+$k; + my $id1=$NL*$level+$pos; + my $connect_id=$NL*$connect_l+$connect_pos; + $dotfile=$dotfile.node_connection('R',$id1,undef,$port,'R',$connect_id,undef,$connect_port,$gtype); + } + } + } + #add endpoints connection + for(my $i=0; $i<$NE; $i++){ + my $r= $NL*($nl-1)+int($i/$k); + $dotfile=$dotfile.node_connection('T',$i,undef,undef,'R',$r,undef,$i%($k),$gtype); + } + $dotfile=$dotfile."\n}\n"; + return $dotfile; } sub generate_star_dot_file{ - my $self=shift; - - my $dotfile= + my $self=shift; + my $dotfile= "digraph G { - graph [layout = neato, fontsize=3, rankdir = LR , splines = true, overlap = false]; - node[shape=record]; - "; - - my $pnum=$self->object_get_attribute('noc_param','T1'); - $dotfile.=router_node_dot_sim($pnum,"R","R"); - - for(my $p=0; $p<$pnum; $p++) { - $dotfile.=endp_node_dot_sim ("T$p","T$p"); - $dotfile.="R -> T$p [dir=none];\n"; - $dotfile.='#'.node_connection('T',$p,undef,undef,'R',0,undef,$p); - } - - $dotfile.="\n}\n"; - return $dotfile; + graph [layout = neato, fontsize=3, rankdir = LR , splines = true, overlap = false]; + node[shape=record]; + "; + my $pnum=$self->object_get_attribute('noc_param','T1'); + $dotfile.=router_node_dot_sim($pnum,"R","R"); + for(my $p=0; $p<$pnum; $p++) { + $dotfile.=endp_node_dot_sim ("T$p","T$p"); + $dotfile.="R -> T$p [dir=none];\n"; + $dotfile.='#'.node_connection('T',$p,undef,undef,'R',0,undef,$p); + } + $dotfile.="\n}\n"; + return $dotfile; } - - - - - - - - - - sub generate_tree_dot_file{ - my $self=shift; - my $gtype=$self->object_get_attribute("tile_diagram","gtype"); - - my $dotfile= + my $self=shift; + my $gtype=$self->object_get_attribute("tile_diagram","gtype"); + my $dotfile= "digraph G { - graph [layout = neato, rankdir = LR , splines = true, overlap = true]; - node[shape=record]; - "; - - - my $k=$self->object_get_attribute('noc_param','T1'); - my $nl=$self->object_get_attribute('noc_param','T2'); - #generate routres port interface - my @bp; - my @hp; - for(my $p=0; $p<$k; $p++) { - push (@bp,"") if(($k%2)==0 && $p==$k/2);#if k is odd number add one empty space in the middle - push (@bp,"$p"); - - } - for(my $p=$k; $p<2*$k; $p++) { - if($p==$k+int(($k-1)/2)){ - push (@hp,"") if(($k%2)==0);#if k is odd number add one empty space in the middle - push (@hp,"$k"); - }else{ - push (@hp,""); - } - } - my $bp= join("|",@bp); - my $hp= join("|",@hp); -# my ($NE,$NR)=get_topology_info($self); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); - - - #add endpoints - for(my $i=0; $i<$NE; $i++){ - $dotfile=$dotfile."T$i\[ - label = \"T$i\" + graph [layout = neato, rankdir = LR , splines = true, overlap = true]; + node[shape=record]; + "; + my $k=$self->object_get_attribute('noc_param','T1'); + my $nl=$self->object_get_attribute('noc_param','T2'); + #generate routres port interface + my @bp; + my @hp; + for(my $p=0; $p<$k; $p++) { + push (@bp,"") if(($k%2)==0 && $p==$k/2);#if k is odd number add one empty space in the middle + push (@bp,"$p"); + } + for(my $p=$k; $p<2*$k; $p++) { + if($p==$k+int(($k-1)/2)){ + push (@hp,"") if(($k%2)==0);#if k is odd number add one empty space in the middle + push (@hp,"$k"); + }else{ + push (@hp,""); + } + } + my $bp= join("|",@bp); + my $hp= join("|",@hp); + # my ($NE,$NR)=get_topology_info($self); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); + #add endpoints + for(my $i=0; $i<$NE; $i++){ + $dotfile=$dotfile."T$i\[ + label = \"T$i\" pos = \"$i,0!\" shape=house margin=0 - color=orange - style=filled - fillcolor=orange + color=orange + style=filled + fillcolor=orange ]; "; - } - - #add roots - my $label = "\{R0\}|\{$bp\}"; - my $x=(($NE-1)/2); - my $y= 1.5*($nl-1)+1; - $dotfile.=get_router_dot_file("R0",$label,"$x,$y!",$gtype); - - - - #add leaves - my $t=1; - - for(my $l=$nl-1; $l>0; $l--){ - my $NL = powi($k,$l); - $t*=$k; - for(my $pos=0; $pos<$NL; $pos++){ - my $x= $t*$pos + ($t-1)/2 ; - my $y= 1.5*($nl-$l)-.5; - my $r=sum_powi($k,$l)+$pos; - my $label = "\{$hp\}|\{R$r\}|\{$bp\}"; - - $dotfile.=get_router_dot_file("R$r",$label,"$x,$y!",$gtype); - - - } - } - - #add leave connections - for(my $l=$nl-1; $l>0; $l--){ - my $NL = powi($k,$l); - for(my $pos=0; $pos<$NL; $pos++){ - my $id1=sum_powi($k,$l)+$pos; - my $id2=sum_powi($k,$l-1)+int($pos/$k); - $dotfile=$dotfile.node_connection('R',$id1,undef,$k,'R',$id2,undef,$pos % $k,$gtype); - } - } - - #add endpoints connection - for(my $i=0; $i<$NE; $i++){ - my $r= sum_powi($k,$nl-1)+int($i/$k); - $dotfile=$dotfile.node_connection('T',$i,undef,undef,'R',$r,undef,$i%($k),$gtype); - - } - - - - $dotfile=$dotfile."\n}\n"; - return $dotfile; + } + #add roots + my $label = "\{R0\}|\{$bp\}"; + my $x=(($NE-1)/2); + my $y= 1.5*($nl-1)+1; + $dotfile.=get_router_dot_file("R0",$label,"$x,$y!",$gtype); + #add leaves + my $t=1; + for(my $l=$nl-1; $l>0; $l--){ + my $NL = powi($k,$l); + $t*=$k; + for(my $pos=0; $pos<$NL; $pos++){ + my $x= $t*$pos + ($t-1)/2 ; + my $y= 1.5*($nl-$l)-.5; + my $r=sum_powi($k,$l)+$pos; + my $label = "\{$hp\}|\{R$r\}|\{$bp\}"; + $dotfile.=get_router_dot_file("R$r",$label,"$x,$y!",$gtype); + } + } + #add leave connections + for(my $l=$nl-1; $l>0; $l--){ + my $NL = powi($k,$l); + for(my $pos=0; $pos<$NL; $pos++){ + my $id1=sum_powi($k,$l)+$pos; + my $id2=sum_powi($k,$l-1)+int($pos/$k); + $dotfile=$dotfile.node_connection('R',$id1,undef,$k,'R',$id2,undef,$pos % $k,$gtype); + } + } + #add endpoints connection + for(my $i=0; $i<$NE; $i++){ + my $r= sum_powi($k,$nl-1)+int($i/$k); + $dotfile=$dotfile.node_connection('T',$i,undef,undef,'R',$r,undef,$i%($k),$gtype); + } + $dotfile=$dotfile."\n}\n"; + return $dotfile; } sub get_topology_dot_file{ - my $self=shift; - my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); - return generate_mesh_dot_file ($self) if($topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"MESH"'|| $topology eq '"FMESH"' || $topology eq '"TORUS"' ); - return generate_fattree_dot_file ($self) if($topology eq '"FATTREE"'); - return generate_tree_dot_file($self) if($topology eq '"TREE"'); - return generate_star_dot_file($self) if($topology eq '"STAR"'); - + my $self=shift; + my $topology=$self->object_get_attribute('noc_param','TOPOLOGY'); + return generate_mesh_dot_file ($self) if($topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"MESH"'|| $topology eq '"FMESH"' || $topology eq '"TORUS"' ); + return generate_fattree_dot_file ($self) if($topology eq '"FATTREE"'); + return generate_tree_dot_file($self) if($topology eq '"TREE"'); + return generate_star_dot_file($self) if($topology eq '"STAR"'); } sub generate_merge_actor_dot_file{ - my $self=shift; - my $dotfile= + my $self=shift; + my $dotfile= "digraph G { - graph [ layout = neato, rankdir = LR , splines=polyline, overlap = false]; - + graph [ layout = neato, rankdir = LR , splines=polyline, overlap = false]; + "; - - - #add connections - - my @traces= get_trace_list($self,'merge'); - my %src_dst; - my %dests= get_destport_constant_list ($self,'merge'); - my %srcs = get_srcport_constant_list ($self,'merge'); - - - - foreach my $p (@traces){ - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class) - =get_trace($self,'merge',$p); - - - - $dotfile=$dotfile."\"$src\" -> \"$dst\" [label=\"$srcs{$src}{$src_port}{$chanel}->$dests{$dst}{$dst_port}\" ];\n"; - } - - $dotfile=$dotfile."\n}\n"; - return $dotfile; - + my @traces= get_trace_list($self,'merge'); + my %src_dst; + my %dests= get_destport_constant_list ($self,'merge'); + my %srcs = get_srcport_constant_list ($self,'merge'); + foreach my $p (@traces){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class) + =get_trace($self,'merge',$p); + $dotfile=$dotfile."\"$src\" -> \"$dst\" [label=\"$srcs{$src}{$src_port}{$chanel}->$dests{$dst}{$dst_port}\" ];\n"; + } + $dotfile=$dotfile."\n}\n"; + return $dotfile; } - - - - - - - - - -return 1; +return 1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/drag_drop.pl b/mpsoc/perl_gui/lib/perl/drag_drop.pl index 5055b6f..2f802b3 100644 --- a/mpsoc/perl_gui/lib/perl/drag_drop.pl +++ b/mpsoc/perl_gui/lib/perl/drag_drop.pl @@ -3,183 +3,150 @@ use strict; use constant::boolean; - use FindBin; use lib $FindBin::Bin; require "widget.pl"; use POSIX qw(ceil floor); - #Declare our columns use constant C_MARKUP => 0; use constant C_PIXBUF => 1; - #Declare our IDENDTIFIER ID's use constant ID_ICONVIEW => 48; - - - - - sub drag_and_drop_page { - my ($self,$tview,$name,$items_ref, $ctrl_box)=@_; + my ($self,$tview,$name,$items_ref, $ctrl_box)=@_; my $vbox = def_vbox(FALSE,5); - my $group_num=$self->object_get_attribute($name,'group_num'); - update_group_item_list($self,$group_num,$name,$items_ref); - my $ref_source = $self->object_get_attribute("$name",'ungrouped'); + my $group_num=$self->object_get_attribute($name,'group_num'); + update_group_item_list($self,$group_num,$name,$items_ref); + my $ref_source = $self->object_get_attribute("$name",'ungrouped'); my $lb=$self->object_get_attribute($name,'lable'); my ($win,$list_store)=create_iconview($self,"$lb",'NO', $ref_source,$name,'ungrouped',undef); my $table = def_table($group_num%8,$group_num/8,FALSE); my $dim_y = floor(sqrt($group_num)); - my $gname=$self->object_get_attribute("$name",'group_name_root'); - my $editable =$self->object_get_attribute("$name",'group_name_editble'); - my $limit=$self->object_get_attribute($name,'map_limit'); - for (my $i=0; $i<$group_num;$i++){ - - my $ref_grp = $self->object_get_attribute("$name","$gname($i)"); - - my ($gwin,$list_store)=create_iconview($self,"$gname($i)",$editable,$ref_grp,$name,"$gname($i)",$limit ); - my $y= int($i/$dim_y); - my $x= $i % $dim_y; - $table->attach_defaults ($gwin, $x, $x+1 , $y, $y+1); + my $gname=$self->object_get_attribute("$name",'group_name_root'); + my $editable =$self->object_get_attribute("$name",'group_name_editble'); + my $limit=$self->object_get_attribute($name,'map_limit'); + for (my $i=0; $i<$group_num;$i++){ + my $ref_grp = $self->object_get_attribute("$name","$gname($i)"); + my ($gwin,$list_store)=create_iconview($self,"$gname($i)",$editable,$ref_grp,$name,"$gname($i)",$limit ); + my $y= int($i/$dim_y); + my $x= $i % $dim_y; + $table->attach_defaults ($gwin, $x, $x+1 , $y, $y+1); } - my $sw = add_widget_to_scrolled_win($table); - - my $v_paned=gen_vpaned($win,.2,$sw); - my $h_paned= (defined $ctrl_box)? gen_hpaned_adj($self,$v_paned,.5,$ctrl_box, "drag.$name") : $v_paned; - -$vbox->add($h_paned); -$vbox->show_all(); -return $vbox; + my $sw = add_widget_to_scrolled_win($table); + my $v_paned=gen_vpaned($win,.2,$sw); + my $h_paned= (defined $ctrl_box)? gen_hpaned_adj($self,$v_paned,.5,$ctrl_box, "drag.$name") : $v_paned; + $vbox->add($h_paned); + $vbox->show_all(); + return $vbox; } sub get_item_group_name{ - my ($self,$name,$item)=@_; - #print "($self,$name,$item)\n"; - my $group_num=$self->object_get_attribute("$name",'group_num'); - my $gname=$self->object_get_attribute("$name",'group_name_root'); - for(my $i=0;$i<$group_num;$i=$i+1){ - my $gref = $self->object_get_attribute("$name","$gname($i)"); - next if(! defined $gref); - return $self->object_get_attribute("$name","$gname($i)".'_name') if( check_scolar_exist_in_array($item,$gref )); - } - return $item; + my ($self,$name,$item)=@_; + #print "($self,$name,$item)\n"; + my $group_num=$self->object_get_attribute("$name",'group_num'); + my $gname=$self->object_get_attribute("$name",'group_name_root'); + for(my $i=0;$i<$group_num;$i=$i+1){ + my $gref = $self->object_get_attribute("$name","$gname($i)"); + next if(! defined $gref); + return $self->object_get_attribute("$name","$gname($i)".'_name') if( check_scolar_exist_in_array($item,$gref )); + } + return $item; } sub get_items_in_a_group{ - my ($self,$name,$group_name)=@_; - my $group_num=$self->object_get_attribute("$name",'group_num'); - my $gname=$self->object_get_attribute("$name",'group_name_root'); - for(my $i=0;$i<$group_num;$i=$i+1){ - my $current_name= $self->object_get_attribute("$name","$gname($i)".'_name'); - return $self->object_get_attribute("$name","$gname($i)") if($current_name eq $group_name ); - } - return undef; + my ($self,$name,$group_name)=@_; + my $group_num=$self->object_get_attribute("$name",'group_num'); + my $gname=$self->object_get_attribute("$name",'group_name_root'); + for(my $i=0;$i<$group_num;$i=$i+1){ + my $current_name= $self->object_get_attribute("$name","$gname($i)".'_name'); + return $self->object_get_attribute("$name","$gname($i)") if($current_name eq $group_name ); + } + return undef; } sub update_group_item_list{ - my ($self,$group_num,$name,$items_ref)=@_; - #get the list of current items - my @items = (defined $items_ref) ? @{$items_ref}:(); - my @items_grouped; - my $gname=$self->object_get_attribute("$name",'group_name_root'); - #update groaped_list - for(my $i=0;$i<$group_num;$i=$i+1){ - my $gref = $self->object_get_attribute("$name","$gname($i)"); - next if(! defined $gref); - my @grouped = @{$gref}; - @grouped=get_common_array(\@grouped,\@items); - $self->object_add_attribute("$name","$gname($i)",\@grouped); - push (@items_grouped,@grouped); - } - #@items_ungroaped= @items - @items_groaped - my @items_ungrouped= get_diff_array(\@items ,\@items_grouped); - $self->object_add_attribute("$name",'ungrouped',\@items_ungrouped); + my ($self,$group_num,$name,$items_ref)=@_; + #get the list of current items + my @items = (defined $items_ref) ? @{$items_ref}:(); + my @items_grouped; + my $gname=$self->object_get_attribute("$name",'group_name_root'); + #update groaped_list + for(my $i=0;$i<$group_num;$i=$i+1){ + my $gref = $self->object_get_attribute("$name","$gname($i)"); + next if(! defined $gref); + my @grouped = @{$gref}; + @grouped=get_common_array(\@grouped,\@items); + $self->object_add_attribute("$name","$gname($i)",\@grouped); + push (@items_grouped,@grouped); + } + #@items_ungroaped= @items - @items_groaped + my @items_ungrouped= get_diff_array(\@items ,\@items_grouped); + $self->object_add_attribute("$name",'ungrouped',\@items_ungrouped); } - - sub create_iconview { #--------------------------------------------------- #Creates an Iconview in a ScrolledWindow. This ----- #Iconview has the ability to drag items off it ----- #--------------------------------------------------- - my ($self,$label,$editable,$ref,$name,$param,$limit)=@_; + my ($self,$label,$editable,$ref,$name,$param,$limit)=@_; my $icon_string= undef; my $tree_model = create_iconview_model($self,$name,$ref); - my $icon_view = gen_iconview($tree_model,C_MARKUP,C_PIXBUF); - #Enable the IconView as a drag source - add_drag_source($icon_view,'STRING',[],ID_ICONVIEW); add_drop_source($icon_view,$tree_model,$name,$param,$self,$limit); - #This is a nice to have. It changes the drag icon to that of the #icon which are now selected and dragged (single selection mode) - my $saved; - + my $saved; $icon_view->signal_connect('drag-begin' => sub { $icon_view->selected_foreach ( sub{ - my $iter =$tree_model->get_iter($_[1]); - $saved=$iter; - #set the text and pixbuf - my $icon_pixbuf = $tree_model->get_value($iter,C_PIXBUF); - drag_set_icon_pixbuf($icon_view,$icon_pixbuf); - $icon_view->show_all(); + my $iter =$tree_model->get_iter($_[1]); + $saved=$iter; + #set the text and pixbuf + my $icon_pixbuf = $tree_model->get_value($iter,C_PIXBUF); + drag_set_icon_pixbuf($icon_view,$icon_pixbuf); + $icon_view->show_all(); } ); }); - #set up the data which needs to be fed to the drag destination (drop) $icon_view->signal_connect ('drag-data-get' => sub { - return if(! defined $saved); - $icon_string = $tree_model->get_value($saved,C_MARKUP); - #print "\$icon_string=$icon_string\n"; - my $no_markup = $icon_string; + return if(! defined $saved); + $icon_string = $tree_model->get_value($saved,C_MARKUP); + #print "\$icon_string=$icon_string\n"; + my $no_markup = $icon_string; $no_markup =~ s/<[^>]*>//g; - - - my $gref = $self->object_get_attribute("$name",$param); - $tree_model->remove($saved); - source_drag_data_get(@_,$icon_string); - my @array=remove_scolar_from_array($gref,$no_markup ); - $self->object_add_attribute("$name",$param,\@array); - set_gui_status($self,"drag-data-get",0); - - } ); + my $gref = $self->object_get_attribute("$name",$param); + $tree_model->remove($saved); + source_drag_data_get(@_,$icon_string); + my @array=remove_scolar_from_array($gref,$no_markup ); + $self->object_add_attribute("$name",$param,\@array); + set_gui_status($self,"drag-data-get",0); + } ); #Standard scrolledwindow to allow growth my $sw = add_widget_to_scrolled_win($icon_view); $sw->set_policy('never','automatic'); $sw->set_border_width(6); my($width,$hight)=max_win_size(); - $sw->set_size_request($width/10,$hight/10); - - + $sw->set_size_request($width/10,$hight/10); my $frame = gen_frame(); - $frame->set_shadow_type ('in'); - # Animation - $frame->add ($sw); - #$align->add ($frame); - - - - my $entry=gen_entry_object($self,$name,$param."_name",$label); - $frame->set_label_widget ($entry) if($editable eq 'YES'); - $frame->set_label_widget (gen_label_in_center($label)) unless($editable eq 'YES'); - - + $frame->set_shadow_type ('in'); + # Animation + $frame->add ($sw); + #$align->add ($frame); + my $entry=gen_entry_object($self,$name,$param."_name",$label); + $frame->set_label_widget ($entry) if($editable eq 'YES'); + $frame->set_label_widget (gen_label_in_center($label)) unless($editable eq 'YES'); return ($frame,$tree_model); } - - - sub target_drag_data_received { #--------------------------------------------------- #Extract the data which was set up during the ----- @@ -187,44 +154,26 @@ sub target_drag_data_received { #the 'drag-data-received' event. Also checks which-- #source supplied the data, and handle accordingly---- #--------------------------------------------------- - my ($widget, $context, $x, $y, $data, $info, $time,$ref) = @_; - - my ($target,$name,$param,$self,$limit) = @{$ref}; + my ($target,$name,$param,$self,$limit) = @{$ref}; my @array; - my $icon=$self->object_get_attribute($name,'trace_icon'); - my $pixbuf = get_icon_pixbuff ($icon ); - - - - - my $no_markup = $data->get_text; - #print Dumper ($widget, $context, $x, $y, $data, $info, $time,$no_markup); - - $no_markup =~ s/<[^>]*>//g; - - - - - add_icon_to_tree($self,$name,$target,$no_markup) ; - my $r=$self->object_get_attribute("$name","$param"); - - @array = defined ($r)? @{$r}:(); - push (@array ,$no_markup); - $self->object_add_attribute("$name","$param",\@array); - - - - - -# check if the maximum number of dropped item is received -$limit =655350 if(!defined $limit); -if( scalar @array >= $limit){ - stop_drag_dest( $widget); -} - - call_gtk_drag_finish($context, 0, 0, $time); - # $context->finish (0, 0, $time); + my $icon=$self->object_get_attribute($name,'trace_icon'); + my $pixbuf = get_icon_pixbuff ($icon ); + my $no_markup = $data->get_text; + #print Dumper ($widget, $context, $x, $y, $data, $info, $time,$no_markup); + $no_markup =~ s/<[^>]*>//g; + add_icon_to_tree($self,$name,$target,$no_markup) ; + my $r=$self->object_get_attribute("$name","$param"); + @array = defined ($r)? @{$r}:(); + push (@array ,$no_markup); + $self->object_add_attribute("$name","$param",\@array); + # check if the maximum number of dropped item is received + $limit =655350 if(!defined $limit); + if( scalar @array >= $limit){ + stop_drag_dest( $widget); + } + call_gtk_drag_finish($context, 0, 0, $time); + # $context->finish (0, 0, $time); } sub source_drag_data_get { @@ -233,71 +182,49 @@ sub source_drag_data_get { #required before the 'drag-data-received' event ---- #fires which can be used to extract this data ------ #--------------------------------------------------- - my ($widget, $context, $data, $info, $time,$string) = @_; - $data->set_text($string,-1) if defined $string; $data->set_text("Unknown-event-name",-1) unless defined $string; - - - } - - sub add_icon_to_tree{ - my ($self,$name,$list_store,$val)=@_; - + my ($self,$name,$list_store,$val)=@_; my $icon=$self->object_get_attribute($name,'trace_icon'); - my $pixbuf = get_icon_pixbuff ($icon ); - - - #if there was a valid icon in the iconset, add it - if( defined $pixbuf ){ - - my $iter = $list_store->append; - $list_store->set ( - $iter, - C_MARKUP, "$val", - C_PIXBUF, $pixbuf, - ); - - } - + my $pixbuf = get_icon_pixbuff ($icon ); + #if there was a valid icon in the iconset, add it + if( defined $pixbuf ){ + my $iter = $list_store->append; + $list_store->set ( + $iter, + C_MARKUP, "$val", + C_PIXBUF, $pixbuf, + ); + } } - - - sub stop_drag_dest { - my $widget=shift; - $widget->drag_dest_unset (); + my $widget=shift; + $widget->drag_dest_unset (); } sub add_drop_source { - my ($widget,$target,$name,$param,$self,$limit)=@_; - - #Create a target table to receive drops - add_drag_dest_set($widget, 'STRING',[],ID_ICONVIEW); - + my ($widget,$target,$name,$param,$self,$limit)=@_; + #Create a target table to receive drops + add_drag_dest_set($widget, 'STRING',[],ID_ICONVIEW); #make this the drag destination (drop) for various drag sources my $r=$self->object_get_attribute("$name","$param"); my @array = defined ($r)? @{$r}:(); - # check if the maximum number of dropped item is received - $limit =655350 if(!defined $limit); - if( scalar @array >= $limit){ - stop_drag_dest( $widget); - } - - + $limit =655350 if(!defined $limit); + if( scalar @array >= $limit){ + stop_drag_dest( $widget); + } #do a callback as soon as drag data is received my @params=($target,$name,$param,$self,$limit); $widget->signal_connect ('drag-data-received' => \&target_drag_data_received,\@params ); $widget->signal_connect ('drag-data-get' => sub { - add_drag_dest_set($widget, 'STRING',[],ID_ICONVIEW); + add_drag_dest_set($widget, 'STRING',[],ID_ICONVIEW); }); - -} +} \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/emulator.pl b/mpsoc/perl_gui/lib/perl/emulator.pl index d4269f3..b2c17c1 100755 --- a/mpsoc/perl_gui/lib/perl/emulator.pl +++ b/mpsoc/perl_gui/lib/perl/emulator.pl @@ -36,7 +36,7 @@ use constant RAM_Aw =>7; use constant RAM_RESERVED_ADDR_NUM=>8; use constant MAX_PATTERN => ((2**RAM_Aw)-(RAM_RESERVED_ADDR_NUM)); -use constant RAM_SIZE => (2**RAM_Aw); +use constant RAM_SIZE => (2**RAM_Aw); #use constant MAX_PCK_NUM => (2**PCK_CNTw)-1; @@ -54,34 +54,30 @@ sub get_MAX_PCK_SIZ(){MAX_PCK_SIZ} sub check_inserted_ratios { - my $str=shift; - my @ratios; - - my @chunks=split(/\s*,\s*/,$str); - foreach my $p (@chunks){ - if($p !~ /^[0-9.:,]+$/){ message_dialog ("$p has invalid character(S)" ); return undef; } - my @range=split(':',$p); - my $size= scalar @range; - if($size==1){ # its a number - if ( $range[0] <= 0 || $range[0] >100 ) { message_dialog ("Injection ratio $range[0] is out of bounds: 1<=ratio=<100" ); return undef; } - push(@ratios,$range[0]); - }elsif($size ==3){# its a range - my($min,$max,$step)=@range; - if ( $min <= 0 || $min >100 ) { message_dialog ("Injection ratio $min in $p is out of bounds: 1<=ratio=<100" ); return undef; } - if ( $max <= 0 || $max >100 ) { message_dialog ("Injection ratio $max in $p is out of bounds: 1<=ratio=<100" ); return undef; } - for (my $i=$min; $i<=$max; $i=$i+$step){ - push(@ratios,$i); - } - - }else{ - message_dialog ("Injection ratio $p has an invalid format. The correct format for range is \[min\]:\[max\]:\[step\]" ); - return undef; - } - - }#foreach - my @r=uniq(sort {$a<=>$b} @ratios); - return \@r; - + my $str=shift; + my @ratios; + my @chunks=split(/\s*,\s*/,$str); + foreach my $p (@chunks){ + if($p !~ /^[0-9.:,]+$/){ message_dialog ("$p has invalid character(S)" ); return undef; } + my @range=split(':',$p); + my $size= scalar @range; + if($size==1){ # its a number + if ( $range[0] <= 0 || $range[0] >100 ) { message_dialog ("Injection ratio $range[0] is out of bounds: 1<=ratio=<100" ); return undef; } + push(@ratios,$range[0]); + }elsif($size ==3){# its a range + my($min,$max,$step)=@range; + if ( $min <= 0 || $min >100 ) { message_dialog ("Injection ratio $min in $p is out of bounds: 1<=ratio=<100" ); return undef; } + if ( $max <= 0 || $max >100 ) { message_dialog ("Injection ratio $max in $p is out of bounds: 1<=ratio=<100" ); return undef; } + for (my $i=$min; $i<=$max; $i=$i+$step){ + push(@ratios,$i); + } + }else{ + message_dialog ("Injection ratio $p has an invalid format. The correct format for range is \[min\]:\[max\]:\[step\]" ); + return undef; + } + }#foreach + my @r=uniq(sort {$a<=>$b} @ratios); + return \@r; } sub get_injection_ratios{ @@ -92,7 +88,7 @@ sub get_injection_ratios{ my $button=def_image_button("icons/right.png",'Check'); $button->signal_connect("clicked" => sub { my $text= $entry->get_text(); - my $r=check_inserted_ratios($text); + my $r=check_inserted_ratios($text); if(defined $r){ my $all= join (',',@$r); message_dialog ("$all" ); @@ -108,414 +104,305 @@ sub get_injection_ratios{ } sub get_noc_configuration{ - my ($emulate,$mode,$sample,$set_win) =@_; - if($mode eq "simulate") {get_simulator_noc_configuration(@_); return;} - get_emulator_noc_configuration(@_); + my ($emulate,$mode,$sample,$set_win) =@_; + if($mode eq "simulate") {get_simulator_noc_configuration(@_); return;} + get_emulator_noc_configuration(@_); } sub get_sof_file_full_addr{ - my ($emulate,$sample)=@_; - my $open_in = $emulate->object_get_attribute($sample,"sof_path"); - my $board = $emulate->object_get_attribute($sample,"FPGA_board"); - my $file = $emulate->object_get_attribute($sample,"sof_file"); - return undef if(!defined ${open_in} || !defined ${board} || !defined $file ); - my $sof = "${open_in}/${board}/$file"; - #print "\n$sof\n"; - return $sof; + my ($emulate,$sample)=@_; + my $open_in = $emulate->object_get_attribute($sample,"sof_path"); + my $board = $emulate->object_get_attribute($sample,"FPGA_board"); + my $file = $emulate->object_get_attribute($sample,"sof_file"); + return undef if(!defined ${open_in} || !defined ${board} || !defined $file ); + my $sof = "${open_in}/${board}/$file"; + #print "\n$sof\n"; + return $sof; } sub get_emulator_noc_configuration{ - my ($emulate,$mode,$sample,$set_win) =@_; - my $table=def_table(10,2,FALSE); - my $row=0; - - my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,shuffle,bit rotation,neighbor"; #TODO hot spot for emulator - - #search path - my $dir = Cwd::getcwd(); - my $open_in = abs_path("$ENV{PRONOC_WORK}/emulate/sof"); - attach_widget_to_table ($table,$row,gen_label_in_left("Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), - get_dir_in_object ($emulate,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; - $open_in = $emulate->object_get_attribute($sample,"sof_path"); - - - - #select the board - my($label,$param,$default,$content,$type,$info); - my @dirs = grep {-d} glob("$open_in/*"); - my $fpgas; - foreach my $dir (@dirs) { - my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); - $default=$name; - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - } - - attach_widget_to_table ($table,$row,gen_label_in_left("Select FPGA board:"),gen_button_message ("Select the FPGA board. You can add your own FPGA board by adding its configuration file to mpsoc/boards directory","icons/help.png"), - gen_combobox_object ($emulate,$sample, "FPGA_board", $fpgas, undef,'ref_set_win',1)); $row++; - - - #select the sram object file - my $board = $emulate->object_get_attribute($sample,"FPGA_board"); - my @files; - @files = glob "${open_in}/${board}/*" if(defined $board); - my $sof_files=""; - foreach my $file (@files){ - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - $sof_files="$sof_files,$name" if($suffix eq '.sof'); - } - attach_widget_to_table ($table,$row,gen_label_in_left("Sram Object File:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), - gen_combobox_object ($emulate,$sample, "sof_file", $sof_files, undef,undef,undef)); $row++; - - - - #attach_widget_to_table ($table,$row,gen_label_in_left("SoF file:"),gen_button_message ("Select the SRAM Object File (sof) for this NoC configration.","icons/help.png"), get_file_name_object ($emulate,$sample,"sof_file",'sof',$open_in)); $row++; - - - my @emulateinfo = ( - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef}, - - { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>undef}, - -{ label=>"Packet size in flit:", param_name=>'PCK_SIZE', type=>'Spin-button', default_val=>4, content=>"2,".MAX_PCK_SIZ.",1", info=>undef, param_parent=>$sample, ref_delay=>undef}, - - { label=>"Packet number limit per node:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>1000000, content=>"2,".MAX_PCK_NUM.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef}, - -{ label=>"Emulation clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>MAX_SIM_CLKs, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef}, - - -); - - - - my @siminfo = ( - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - - { label=>"Packet size in flit:", param_name=>'PCK_SIZE', type=>'Spin-button', default_val=>4, content=>"2,".MAX_PCK_SIZ.",1", info=>undef, param_parent=>$sample, ref_delay=>undef}, - - { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,".MAX_PCK_NUM.",1", info=>"Simulation will stop when total numbr of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - ); - - -my $hot_num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); -$hot_num=1 if(!defined $hot_num); -my $max= ($hot_num>0)? 100/$hot_num: 20; - -my @hotspot_info=( - { label=>'Hot Spot num:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, - content=>"1,5,1", info=>"Number of hot spot nodes in the network", - param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}, - { label=>'Hot Spot traffic percentage:', param_name=>'HOTSPOT_PERCENTAGE', type=>'Spin-button', default_val=>1, - content=>"1, $max,1", info=>"If it is set as n then each node sends n % of its traffic to each hotspot node", - param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - { label=>'Hot Spot nodes send enable:', param_name=>'HOTSPOT_SEND', type=>'Combo-box', default_val=>1, - content=>"0,1", info=>"If it is set as 0 then hot spot nodes only recieves packet from other nodes and do not send packets to others", - param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - - ); - - - my @info= ($mode eq "simulate")? @siminfo : @emulateinfo; - - my $coltmp=0; - foreach my $d ( @info) { - ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - my $traffic=$emulate->object_get_attribute($sample,"traffic"); - - if ($traffic eq 'hot spot'){ - foreach my $d ( @hotspot_info) { - ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - my $num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); - for (my $i=0;$i<$num;$i++){ - my $m=$i+1; - ($row,$coltmp)=add_param_widget ($emulate, "Hotspot $m tile num:", "HOTSPOT_CORE_$m", 0, 'Spin-button', "0,256,1", - "Defne the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node ", $table,$row,undef,1,$sample); - - } - - } - my $l= "Injection ratios in flits/clk/Endpoint (%). + my ($emulate,$mode,$sample,$set_win) =@_; + my $table=def_table(10,2,FALSE); + my $row=0; + my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,shuffle,bit rotation,neighbor"; #TODO hot spot for emulator + #search path + my $dir = Cwd::getcwd(); + my $open_in = abs_path("$ENV{PRONOC_WORK}/emulate/sof"); + attach_widget_to_table ($table,$row,gen_label_in_left("Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), + get_dir_in_object ($emulate,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; + $open_in = $emulate->object_get_attribute($sample,"sof_path"); + + #select the board + my($label,$param,$default,$content,$type,$info); + my @dirs = grep {-d} glob("$open_in/*"); + my $fpgas; + foreach my $dir (@dirs) { + my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); + $default=$name; + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + } + attach_widget_to_table ($table,$row,gen_label_in_left("Select FPGA board:"),gen_button_message ("Select the FPGA board. You can add your own FPGA board by adding its configuration file to mpsoc/boards directory","icons/help.png"), + gen_combobox_object ($emulate,$sample, "FPGA_board", $fpgas, undef,'ref_set_win',1)); $row++; + + #select the sram object file + my $board = $emulate->object_get_attribute($sample,"FPGA_board"); + my @files; + @files = glob "${open_in}/${board}/*" if(defined $board); + my $sof_files=""; + foreach my $file (@files){ + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + $sof_files="$sof_files,$name" if($suffix eq '.sof'); + } + attach_widget_to_table ($table,$row,gen_label_in_left("Sram Object File:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), + gen_combobox_object ($emulate,$sample, "sof_file", $sof_files, undef,undef,undef)); $row++; + #attach_widget_to_table ($table,$row,gen_label_in_left("SoF file:"),gen_button_message ("Select the SRAM Object File (sof) for this NoC configration.","icons/help.png"), get_file_name_object ($emulate,$sample,"sof_file",'sof',$open_in)); $row++; + my @emulateinfo = ( + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef}, + { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>undef}, + { label=>"Packet size in flit:", param_name=>'PCK_SIZE', type=>'Spin-button', default_val=>4, content=>"2,".MAX_PCK_SIZ.",1", info=>undef, param_parent=>$sample, ref_delay=>undef}, + { label=>"Packet number limit per node:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>1000000, content=>"2,".MAX_PCK_NUM.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef}, + { label=>"Emulation clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>MAX_SIM_CLKs, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef}, + ); + my @siminfo = ( + { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, + { label=>"Packet size in flit:", param_name=>'PCK_SIZE', type=>'Spin-button', default_val=>4, content=>"2,".MAX_PCK_SIZ.",1", info=>undef, param_parent=>$sample, ref_delay=>undef}, + { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,".MAX_PCK_NUM.",1", info=>"Simulation will stop when total numbr of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, + ); + my $hot_num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); + $hot_num=1 if(!defined $hot_num); + my $max= ($hot_num>0)? 100/$hot_num: 20; + my @hotspot_info=( + { label=>'Hot Spot num:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, + content=>"1,5,1", info=>"Number of hot spot nodes in the network", + param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}, + { label=>'Hot Spot traffic percentage:', param_name=>'HOTSPOT_PERCENTAGE', type=>'Spin-button', default_val=>1, + content=>"1, $max,1", info=>"If it is set as n then each node sends n % of its traffic to each hotspot node", + param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + { label=>'Hot Spot nodes send enable:', param_name=>'HOTSPOT_SEND', type=>'Combo-box', default_val=>1, + content=>"0,1", info=>"If it is set as 0 then hot spot nodes only recieves packet from other nodes and do not send packets to others", + param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + ); + my @info= ($mode eq "simulate")? @siminfo : @emulateinfo; + my $coltmp=0; + foreach my $d ( @info) { + ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + } + my $traffic=$emulate->object_get_attribute($sample,"traffic"); + if ($traffic eq 'hot spot'){ + foreach my $d ( @hotspot_info) { + ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + } + my $num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); + for (my $i=0;$i<$num;$i++){ + my $m=$i+1; + ($row,$coltmp)=add_param_widget ($emulate, "Hotspot $m tile num:", "HOTSPOT_CORE_$m", 0, 'Spin-button', "0,256,1", + "Defne the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node ", $table,$row,undef,1,$sample); + } + } + my $l= "Injection ratios in flits/clk/Endpoint (%). E.g. Injection ratio 10% means each endpoint inject one flit every 10 cycles. You can define individual ratios seprating by comma (\',\') or define a range of injection ratios with \$min:\$max:\$step format. As an example defining 2,3,4:10:2 will result in (2,3,4,6,8,10) injection ratios. " ; - my $u=get_injection_ratios ($emulate,$sample,"ratios"); - - attach_widget_to_table ($table,$row,gen_label_in_left("Injection ratios:"),gen_button_message ($l,"icons/help.png") , $u); $row++; - - my $scrolled_win = add_widget_to_scrolled_win($table); - - my $ok = def_image_button('icons/select.png','OK'); - my $mtable = def_table(10, 1, TRUE); - - $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable-> attach ($ok , 0, 1, 9, 10,'expand','shrink',2,2); - - add_widget_to_scrolled_win ($mtable,$set_win); - $set_win->show_all(); - - $set_win ->signal_connect (destroy => sub{ - - $emulate->object_add_attribute("active_setting",undef,undef); - }); - - - - $ok->signal_connect("clicked"=> sub{ - #check if sof file has been selected - my $s=get_sof_file_full_addr($emulate,$sample); - #check if injection ratios are valid - my $r=$emulate->object_get_attribute($sample,"ratios"); - if(defined $s && defined $r) { - $set_win->hide; - $emulate->object_add_attribute("active_setting",undef,undef); - set_gui_status($emulate,"ref",1); - } else { - - if(!defined $s){ - my $m=($mode eq 'simulate') ? "Please select NoC verilated file" : "Please select sof file!"; - message_dialog($m); - } else { - message_dialog("Please define valid injection ratio(s)!"); - } - } - }); - - -} - + my $u=get_injection_ratios ($emulate,$sample,"ratios"); + attach_widget_to_table ($table,$row,gen_label_in_left("Injection ratios:"),gen_button_message ($l,"icons/help.png") , $u); $row++; + my $scrolled_win = add_widget_to_scrolled_win($table); + my $ok = def_image_button('icons/select.png','OK'); + my $mtable = def_table(10, 1, TRUE); + $mtable->attach_defaults($scrolled_win,0,1,0,9); + $mtable-> attach ($ok , 0, 1, 9, 10,'expand','shrink',2,2); + add_widget_to_scrolled_win ($mtable,$set_win); + $set_win->show_all(); + $set_win ->signal_connect (destroy => sub{ + + $emulate->object_add_attribute("active_setting",undef,undef); + }); + + $ok->signal_connect("clicked"=> sub{ + #check if sof file has been selected + my $s=get_sof_file_full_addr($emulate,$sample); + #check if injection ratios are valid + my $r=$emulate->object_get_attribute($sample,"ratios"); + if(defined $s && defined $r) { + $set_win->hide; + $emulate->object_add_attribute("active_setting",undef,undef); + set_gui_status($emulate,"ref",1); + } else { + + if(!defined $s){ + my $m=($mode eq 'simulate') ? "Please select NoC verilated file" : "Please select sof file!"; + message_dialog($m); + } else { + message_dialog("Please define valid injection ratio(s)!"); + } + } + }); +} - ##################### -# gen_widgets_column -################### - +# gen_widgets_column +################### sub gen_emulation_column { - my ($emulate,$mode, $row_num,$info,$set_win,@charts)=@_; - my $table=def_table($row_num,10,FALSE); - if(!defined $set_win){ - $set_win=def_popwin_size(40,80,"NoC configuration setting",'percent'); - $set_win->signal_connect (delete_event => sub {$emulate->object_add_attribute("active_setting",undef,undef); $set_win->hide_on_delete }); - - } else{ - my @childs = $set_win->get_children; - foreach my $c (@childs){ $c->destroy;} - } - my $scrolled_win = gen_scr_win_with_adjst ($emulate,"emulation_column"); - add_widget_to_scrolled_win($table,$scrolled_win); - my $row=0; - - #title - my $title_l =($mode eq "simulate" ) ? "NoC Simulator" : "NoC Emulator"; - my $title=gen_label_in_center($title_l); - $table->attach ($title , 0, 10, $row, $row+1,'expand','shrink',2,2); $row++; - add_Hsep_to_table($table,0,10,$row);$row++; - - - - - my %order; - $order{'+/-'}=0; - $order{'Setting'}=1; - $order{'Run'}=2; - $order{'Name'}=3; - $order{'Color'}=4; - $order{'Clear'}=5; - $order{'Traffic'}=6; - $order{'Done'}=7; - - foreach my $t (sort keys %order){ - $table->attach (gen_label_in_center($t), $order{$t}, $order{$t}+1, $row, $row+1,'expand','shrink',2,2); - } - - my $traffics="Random,Transposed 1,Transposed 2,Tornado"; - - - $row++; - - - - #my $i=0; - my $active=$emulate->object_get_attribute("active_setting",undef); - my @samples; - @samples =$emulate->object_get_attribute_order("samples"); - - - - foreach my $ss (@samples){ - - - my $sample=$ss; - #my $sample="sample$i"; - #my $n=$i; - - my $name=$emulate->object_get_attribute($sample,"line_name"); - my $l; - my $s=($mode eq "simulate" ) ? 1 : get_sof_file_full_addr($emulate,$sample); - #check if injection ratios are valid - my $r=$emulate->object_get_attribute($sample,"ratios"); - if(defined $s && defined $name){ - - $l=def_image_button('icons/diagram.png',$name); - $l-> signal_connect("clicked" => sub{ - - __PACKAGE__->mk_accessors(qw{noc_param}); - my $temp = __PACKAGE__->new(); - - - - my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); - return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my $ref=$emulate->object_get_attribute($sample,"noc_info"); - if (defined $ref){ - my %noc_info= %$ref; - foreach my $p (sort keys %noc_info){ - $temp->object_add_attribute('noc_param',$p,$noc_info{$p}); - } - } - - show_topology_diagram ($temp); - }); - - my $traffic = def_button("Pattern"); - $traffic-> signal_connect("clicked" => sub{ - my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); - return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - $emulate->object_add_attribute('noc_param','T1',$T1); - $emulate->object_add_attribute('noc_param','T2',$T2); - $emulate->object_add_attribute('noc_param','T3',$T3); - $emulate->object_add_attribute('noc_param','TOPOLOGY',$topology); - my $pattern=""; - my $traffictype=$emulate->object_get_attribute($sample,"TRAFFIC_TYPE"); - $pattern=get_synthetic_traffic_pattern($emulate, $sample) if($traffictype eq "Synthetic"); - $pattern=" Custom traffic based on input file. " if($traffictype eq "Task-graph"); - - my $window = def_popwin_size(40,40,"Traffic pattern",'percent'); - my ($outbox,$tview)= create_txview(); - show_info($tview,"$pattern"); - $window->add ($outbox); - $window->show_all(); - - }); - - - $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); - $table->attach ($traffic, $order{'Traffic'}, $order{'Traffic'}+1, $row, $row+1,'expand','shrink',2,2); - - - } else { - $l=gen_label_in_left("Define NoC configuration"); - $l->set_markup("Define NoC configuration"); - $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); - } - - - #remove - my $remove=def_image_button("icons/cancel.png"); - $table->attach ($remove,$order{'+/-'},$order{'+/-'}+1, $row, $row+1,'expand','shrink',2,2); - $remove->signal_connect("clicked"=> sub{ - $emulate->object_delete_attribute_order("samples",$sample); - set_gui_status($emulate,"ref",2); - }); - - #setting - my $set=def_image_button("icons/setting.png"); - $table->attach ($set, $order{'Setting'}, $order{'Setting'}+1, $row, $row+1,'expand','shrink',2,2); - - - if(defined $active){#The setting windows ask for refershing so open it again - get_noc_configuration($emulate,$mode,$sample,$set_win) if ($active eq $sample); - } - - - - $set->signal_connect("clicked"=> sub{ - $emulate->object_add_attribute("active_setting",undef,$sample); - get_noc_configuration($emulate,$mode,$sample,$set_win); - }); - - - - my $color_num=$emulate->object_get_attribute($sample,"color"); - if(!defined $color_num){ - $color_num = (scalar @samples) +1; - $emulate->object_add_attribute($sample,"color",$color_num); - } - my $color=def_colored_button(" ",$color_num); - $table->attach ($color, $order{'Color'}, $order{'Color'}+1, $row, $row+1,'fill','fill',2,2); - - $color->signal_connect("clicked"=> sub{ - get_color_window($emulate,$sample,"color"); - }); - - #clear line - my $clear = def_image_button('icons/clear.png'); - $clear->signal_connect("clicked"=> sub{ - foreach my $chart (@charts){ - $emulate->object_add_attribute ($sample,"$chart->{result_name}",undef); - - #print "\$emulate->object_add_attribute ($sample,$chart->{result_name}_result,undef);"; - - } - set_gui_status($emulate,"ref",2); - }); - $table->attach ($clear, $order{'Clear'}, $order{'Clear'}+1, $row, $row+1,'expand','shrink',2,2); - #run/pause - my $run = def_image_button('icons/run.png',undef); - $table->attach ($run, $order{'Run'}, $order{'Run'}+1, $row, $row+1,'expand','shrink',2,2); - $run->signal_connect("clicked"=> sub{ - $emulate->object_add_attribute ($sample,"status","run"); - #start the emulator if it is not running - my $status= $emulate->object_get_attribute('status',undef); - if($status ne 'run'){ - - run_emulator($emulate,$info) if($mode eq 'emulate'); - run_simulator($emulate,$info) if($mode eq 'simulate'); - set_gui_status($emulate,"ref",2); - } - - }); - - my $image = gen_noc_status_image($emulate,$sample); - $table->attach ($image, $order{'Done'},$order{'Done'}+1, $row, $row+1,'expand','shrink',2,2); - - $row++; - - } - # add new simulation - - my $add=def_image_button("icons/plus.png",' A_dd ',FALSE,1); - $table->attach ($add, $order{'+/-'},$order{'+/-'}+2, $row, $row+1,'expand','shrink',2,2); - - - - $add->signal_connect("clicked"=> sub{ - my $n=$emulate->object_get_attribute("id",undef); - $n=0 if (!defined $n); - my $sample="sample$n"; - $n++; - $emulate->object_add_attribute("id",undef,$n); - $emulate->object_add_attribute("active_setting",undef,$sample); - #get_noc_configuration($emulate,$mode,$sample,$set_win); - $emulate->object_add_attribute_order("samples",$sample); - set_gui_status($emulate,"ref",1); - - }); - - - - return ($scrolled_win,$set_win); -} + my ($emulate,$mode, $row_num,$info,$set_win,@charts)=@_; + my $table=def_table($row_num,10,FALSE); + if(!defined $set_win){ + $set_win=def_popwin_size(40,80,"NoC configuration setting",'percent'); + $set_win->signal_connect (delete_event => sub {$emulate->object_add_attribute("active_setting",undef,undef); $set_win->hide_on_delete }); + } else{ + my @childs = $set_win->get_children; + foreach my $c (@childs){ $c->destroy;} + } + my $scrolled_win = gen_scr_win_with_adjst ($emulate,"emulation_column"); + add_widget_to_scrolled_win($table,$scrolled_win); + my $row=0; + #title + my $title_l =($mode eq "simulate" ) ? "NoC Simulator" : "NoC Emulator"; + my $title=gen_label_in_center($title_l); + $table->attach ($title , 0, 10, $row, $row+1,'expand','shrink',2,2); $row++; + add_Hsep_to_table($table,0,10,$row);$row++; + my %order; + $order{'+/-'}=0; + $order{'Setting'}=1; + $order{'Run'}=2; + $order{'Name'}=3; + $order{'Color'}=4; + $order{'Clear'}=5; + $order{'Traffic'}=6; + $order{'Done'}=7; + foreach my $t (sort keys %order){ + $table->attach (gen_label_in_center($t), $order{$t}, $order{$t}+1, $row, $row+1,'expand','shrink',2,2); + } + my $traffics="Random,Transposed 1,Transposed 2,Tornado"; + $row++; + #my $i=0; + my $active=$emulate->object_get_attribute("active_setting",undef); + my @samples; + @samples =$emulate->object_get_attribute_order("samples"); + foreach my $ss (@samples){ + my $sample=$ss; + #my $sample="sample$i"; + #my $n=$i; + my $name=$emulate->object_get_attribute($sample,"line_name"); + my $l; + my $s=($mode eq "simulate" ) ? 1 : get_sof_file_full_addr($emulate,$sample); + #check if injection ratios are valid + my $r=$emulate->object_get_attribute($sample,"ratios"); + if(defined $s && defined $name){ + $l=def_image_button('icons/diagram.png',$name); + $l-> signal_connect("clicked" => sub{ + __PACKAGE__->mk_accessors(qw{noc_param}); + my $temp = __PACKAGE__->new(); + my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); + return if $st==0; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my $ref=$emulate->object_get_attribute($sample,"noc_info"); + if (defined $ref){ + my %noc_info= %$ref; + foreach my $p (sort keys %noc_info){ + $temp->object_add_attribute('noc_param',$p,$noc_info{$p}); + } + } + show_topology_diagram ($temp); + }); + my $traffic = def_button("Pattern"); + $traffic-> signal_connect("clicked" => sub{ + my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); + return if $st==0; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + $emulate->object_add_attribute('noc_param','T1',$T1); + $emulate->object_add_attribute('noc_param','T2',$T2); + $emulate->object_add_attribute('noc_param','T3',$T3); + $emulate->object_add_attribute('noc_param','TOPOLOGY',$topology); + my $pattern=""; + my $traffictype=$emulate->object_get_attribute($sample,"TRAFFIC_TYPE"); + $pattern=get_synthetic_traffic_pattern($emulate, $sample) if($traffictype eq "Synthetic"); + $pattern=" Custom traffic based on input file. " if($traffictype eq "Task-graph"); + my $window = def_popwin_size(40,40,"Traffic pattern",'percent'); + my ($outbox,$tview)= create_txview(); + show_info($tview,"$pattern"); + $window->add ($outbox); + $window->show_all(); + }); + $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); + $table->attach ($traffic, $order{'Traffic'}, $order{'Traffic'}+1, $row, $row+1,'expand','shrink',2,2); + } else { + $l=gen_label_in_left("Define NoC configuration"); + $l->set_markup("Define NoC configuration"); + $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); + } + #remove + my $remove=def_image_button("icons/cancel.png"); + $table->attach ($remove,$order{'+/-'},$order{'+/-'}+1, $row, $row+1,'expand','shrink',2,2); + $remove->signal_connect("clicked"=> sub{ + $emulate->object_delete_attribute_order("samples",$sample); + set_gui_status($emulate,"ref",2); + }); + #setting + my $set=def_image_button("icons/setting.png"); + $table->attach ($set, $order{'Setting'}, $order{'Setting'}+1, $row, $row+1,'expand','shrink',2,2); + if(defined $active){#The setting windows ask for refershing so open it again + get_noc_configuration($emulate,$mode,$sample,$set_win) if ($active eq $sample); + } + $set->signal_connect("clicked"=> sub{ + $emulate->object_add_attribute("active_setting",undef,$sample); + get_noc_configuration($emulate,$mode,$sample,$set_win); + }); + my $color_num=$emulate->object_get_attribute($sample,"color"); + if(!defined $color_num){ + $color_num = (scalar @samples) +1; + $emulate->object_add_attribute($sample,"color",$color_num); + } + my $color=def_colored_button(" ",$color_num); + $table->attach ($color, $order{'Color'}, $order{'Color'}+1, $row, $row+1,'fill','fill',2,2); + $color->signal_connect("clicked"=> sub{ + get_color_window($emulate,$sample,"color"); + }); + #clear line + my $clear = def_image_button('icons/clear.png'); + $clear->signal_connect("clicked"=> sub{ + foreach my $chart (@charts){ + $emulate->object_add_attribute ($sample,"$chart->{result_name}",undef); + #print "\$emulate->object_add_attribute ($sample,$chart->{result_name}_result,undef);"; + } + set_gui_status($emulate,"ref",2); + }); + $table->attach ($clear, $order{'Clear'}, $order{'Clear'}+1, $row, $row+1,'expand','shrink',2,2); + #run/pause + my $run = def_image_button('icons/run.png',undef); + $table->attach ($run, $order{'Run'}, $order{'Run'}+1, $row, $row+1,'expand','shrink',2,2); + $run->signal_connect("clicked"=> sub{ + $emulate->object_add_attribute ($sample,"status","run"); + #start the emulator if it is not running + my $status= $emulate->object_get_attribute('status',undef); + if($status ne 'run'){ + run_emulator($emulate,$info) if($mode eq 'emulate'); + run_simulator($emulate,$info) if($mode eq 'simulate'); + set_gui_status($emulate,"ref",2); + } + }); + my $image = gen_noc_status_image($emulate,$sample); + $table->attach ($image, $order{'Done'},$order{'Done'}+1, $row, $row+1,'expand','shrink',2,2); + $row++; + } + # add new simulation + my $add=def_image_button("icons/plus.png",' A_dd ',FALSE,1); + $table->attach ($add, $order{'+/-'},$order{'+/-'}+2, $row, $row+1,'expand','shrink',2,2); + $add->signal_connect("clicked"=> sub{ + my $n=$emulate->object_get_attribute("id",undef); + $n=0 if (!defined $n); + my $sample="sample$n"; + $n++; + $emulate->object_add_attribute("id",undef,$n); + $emulate->object_add_attribute("active_setting",undef,$sample); + #get_noc_configuration($emulate,$mode,$sample,$set_win); + $emulate->object_add_attribute_order("samples",$sample); + set_gui_status($emulate,"ref",1); + }); + return ($scrolled_win,$set_win); +} @@ -524,195 +411,161 @@ sub gen_emulation_column { ########## sub check_sample{ - my ($emulate,$sample,$info)=@_; - my $status=1; - my $sof=get_sof_file_full_addr($emulate,$sample); - - - - # ckeck if sample have sof file - if(!defined $sof){ - #add_info($info, "Error: SoF file has not set for $sample!\n"); - add_colored_info($info, "Error: SoF file has not set for $sample!\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); - $status=0; - } else { - # ckeck if sof file has info file - my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); - my $sof_info= "$path$name.inf"; - - # print "\n $sof \t $sof_info\n"; - - if(!(-f $sof_info)){ - add_colored_info($info, "Error: Could not find $name.inf file in $path. An information file is required for each sof file containig the device name and NoC configuration. Press F3 for more help.\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); - $status=0; - }else { #add info - my $pp= do $sof_info ; - - my $p=$pp->{'noc_param'}; - - $status=0 if $@; - message_dialog("Error reading: $@",'error') if $@; - if ($status==1){ - $emulate->object_add_attribute ($sample,"noc_info",$p) ; - - - } - } - } - - return $status; + my ($emulate,$sample,$info)=@_; + my $status=1; + my $sof=get_sof_file_full_addr($emulate,$sample); + # ckeck if sample have sof file + if(!defined $sof){ + #add_info($info, "Error: SoF file has not set for $sample!\n"); + add_colored_info($info, "Error: SoF file has not set for $sample!\n",'red'); + $emulate->object_add_attribute ($sample,"status","failed"); + $status=0; + } else { + # ckeck if sof file has info file + my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); + my $sof_info= "$path$name.inf"; + + # print "\n $sof \t $sof_info\n"; + + if(!(-f $sof_info)){ + add_colored_info($info, "Error: Could not find $name.inf file in $path. An information file is required for each sof file containig the device name and NoC configuration. Press F3 for more help.\n",'red'); + $emulate->object_add_attribute ($sample,"status","failed"); + $status=0; + }else { #add info + my $pp= do $sof_info ; + my $p=$pp->{'noc_param'}; + $status=0 if $@; + message_dialog("Error reading: $@",'error') if $@; + if ($status==1){ + $emulate->object_add_attribute ($sample,"noc_info",$p) ; + } + } + } + return $status; } - - - - - - - ############# # images ########## sub get_status_gif{ - my $emulate=shift; - my $status= $emulate->object_get_attribute('status',undef); - if($status eq 'ideal'){ - return show_gif ("icons/ProNoC.png"); - } elsif ($status eq 'run') { - my($width,$hight)=max_win_size(); - my $image=($width>=1600)? "icons/hamster_l.gif": - ($width>=1200)? "icons/hamster_m.gif": "icons/hamster_s.gif"; - - return show_gif ($image); - } elsif ($status eq 'programmer_failed') { - return show_gif ("icons/Error.png"); - } - -} - - + my $emulate=shift; + my $status= $emulate->object_get_attribute('status',undef); + if($status eq 'ideal'){ + return show_gif ("icons/ProNoC.png"); + } elsif ($status eq 'run') { + my($width,$hight)=max_win_size(); + my $image=($width>=1600)? "icons/hamster_l.gif": + ($width>=1200)? "icons/hamster_m.gif": "icons/hamster_s.gif"; + return show_gif ($image); + } elsif ($status eq 'programmer_failed') { + return show_gif ("icons/Error.png"); + } +} sub gen_noc_status_image { - my ($emulate,$sample)=@_; - my $status= $emulate->object_get_attribute ($sample,"status"); - $status='' if(!defined $status); - my $image; - my $box = def_hbox(TRUE,1); - $image = new_image_from_file ("icons/load.gif") if($status eq "run"); - $image = def_icon("icons/button_ok.png") if($status eq "done"); - $image = def_icon("icons/warning.png") if($status eq "failed"); - - if (defined $image) { - $box->pack_start (add_frame_to_image($image), FALSE, FALSE, 0); - } - return $box; - + my ($emulate,$sample)=@_; + my $status= $emulate->object_get_attribute ($sample,"status"); + $status='' if(!defined $status); + my $image; + my $box = def_hbox(TRUE,1); + $image = new_image_from_file ("icons/load.gif") if($status eq "run"); + $image = def_icon("icons/button_ok.png") if($status eq "done"); + $image = def_icon("icons/warning.png") if($status eq "failed"); + + if (defined $image) { + $box->pack_start (add_frame_to_image($image), FALSE, FALSE, 0); + } + return $box; } ############ -# run_emulator +# run_emulator ########### sub run_emulator { - my ($emulate,$info)=@_; - #my $graph_name="latency_ratio"; - #return if(!check_samples($emulate,$info)); - $emulate->object_add_attribute('status',undef,'run'); - set_gui_status($emulate,"ref",1); - show_colored_info($info, "start emulation\n",'blue'); - -# #search for available usb blaster -# my $cmd = "jtagconfig"; -# my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); -# my @matches= ($stdout =~ /USB-Blaster.*/g); -# my $usb_blaster=$matches[0]; -# if (!defined $usb_blaster){ -# add_info($info, "jtagconfig could not find any USB blaster cable: $stdout \n"); -# $emulate->object_add_attribute('status',undef,'programmer_failed'); -# set_gui_status($emulate,"ref",2); -# #/***/ -# return; -# }else{ -# add_info($info, "find $usb_blaster\n"); -# } - my @samples =$emulate->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - my $status=$emulate->object_get_attribute ($sample,"status"); - next if($status ne "run"); - next if(!check_sample($emulate,$sample,$info)); - my $r= $emulate->object_get_attribute($sample,"ratios"); - my @ratios=@{check_inserted_ratios($r)}; - #$emulate->object_add_attribute ("sample$i","status","run"); - my $sof=get_sof_file_full_addr($emulate,$sample); - add_info($info, "Programe FPGA device using $sof.sof\n"); - my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); - my $programmer="$path/program_device.sh"; - my $jtag_intfc="$path/jtag_intfc.sh"; - if((-f $programmer)==0){ - add_colored_info ($info, " Error: file \"$programmer\" dose not exist. \n",'red'); - $emulate->object_add_attribute('status',undef,'programmer_failed'); - $emulate->object_add_attribute ($sample,"status","failed"); - set_gui_status($emulate,"ref",2); - last; - } - if((-f $jtag_intfc)==0){ - add_colored_info ($info, " Error: file \"$jtag_intfc\" dose not exist. \n",'red'); - $emulate->object_add_attribute('status',undef,'programmer_failed'); - $emulate->object_add_attribute ($sample,"status","failed"); - set_gui_status($emulate,"ref",2); - last; - } - my $cmd = "bash $programmer $sof.sof"; - - - #my $Quartus_bin= $ENV{QUARTUS_BIN}; - - - #my $cmd = "$Quartus_bin/quartus_pgm -c \"$usb_blaster\" -m jtag -o \"p;$sof\""; - - #my $output = `$cmd 2>&1 1>/dev/null`; # either with backticks - - #/***/ - my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); - if($exit){#programming FPGA board has failed - $emulate->object_add_attribute('status',undef,'programmer_failed'); - add_colored_info($info, "$stdout\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); - set_gui_status($emulate,"ref",2); - next; - } - #print "$stdout\n"; - - # load noc configuration - foreach my $ratio_in (@ratios){ - - add_info($info, "Configure packet generators for injection ratio of $ratio_in \% \n"); - if(!programe_pck_gens($emulate,$sample,$ratio_in,$info,$jtag_intfc)){ - add_colored_info($info, "Error in programe_pck_gens function\n",'red'); - next; - } - - - my $r=read_pack_gen($emulate,$sample,$info,$jtag_intfc,$ratio_in); - next if (!defined $r); - - - - set_gui_status($emulate,"ref",2); - - } - $emulate->object_add_attribute ($sample,"status","done"); - - } - - add_colored_info($info, "End emulation!\n",'blue'); - $emulate->object_add_attribute('status',undef,'ideal'); - set_gui_status($emulate,"ref",1); + my ($emulate,$info)=@_; + #my $graph_name="latency_ratio"; + #return if(!check_samples($emulate,$info)); + $emulate->object_add_attribute('status',undef,'run'); + set_gui_status($emulate,"ref",1); + show_colored_info($info, "start emulation\n",'blue'); + +# #search for available usb blaster +# my $cmd = "jtagconfig"; +# my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); +# my @matches= ($stdout =~ /USB-Blaster.*/g); +# my $usb_blaster=$matches[0]; +# if (!defined $usb_blaster){ +# add_info($info, "jtagconfig could not find any USB blaster cable: $stdout \n"); +# $emulate->object_add_attribute('status',undef,'programmer_failed'); +# set_gui_status($emulate,"ref",2); +# #/***/ +# return; +# }else{ +# add_info($info, "find $usb_blaster\n"); +# } + my @samples =$emulate->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + my $status=$emulate->object_get_attribute ($sample,"status"); + next if($status ne "run"); + next if(!check_sample($emulate,$sample,$info)); + my $r= $emulate->object_get_attribute($sample,"ratios"); + my @ratios=@{check_inserted_ratios($r)}; + #$emulate->object_add_attribute ("sample$i","status","run"); + my $sof=get_sof_file_full_addr($emulate,$sample); + add_info($info, "Programe FPGA device using $sof.sof\n"); + my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); + my $programmer="$path/program_device.sh"; + my $jtag_intfc="$path/jtag_intfc.sh"; + if((-f $programmer)==0){ + add_colored_info ($info, " Error: file \"$programmer\" dose not exist. \n",'red'); + $emulate->object_add_attribute('status',undef,'programmer_failed'); + $emulate->object_add_attribute ($sample,"status","failed"); + set_gui_status($emulate,"ref",2); + last; + } + if((-f $jtag_intfc)==0){ + add_colored_info ($info, " Error: file \"$jtag_intfc\" dose not exist. \n",'red'); + $emulate->object_add_attribute('status',undef,'programmer_failed'); + $emulate->object_add_attribute ($sample,"status","failed"); + set_gui_status($emulate,"ref",2); + last; + } + my $cmd = "bash $programmer $sof.sof"; + #my $Quartus_bin= $ENV{QUARTUS_BIN}; + #my $cmd = "$Quartus_bin/quartus_pgm -c \"$usb_blaster\" -m jtag -o \"p;$sof\""; + #my $output = `$cmd 2>&1 1>/dev/null`; # either with backticks + #/***/ + my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); + if($exit){#programming FPGA board has failed + $emulate->object_add_attribute('status',undef,'programmer_failed'); + add_colored_info($info, "$stdout\n",'red'); + $emulate->object_add_attribute ($sample,"status","failed"); + set_gui_status($emulate,"ref",2); + next; + } + #print "$stdout\n"; + # load noc configuration + foreach my $ratio_in (@ratios){ + add_info($info, "Configure packet generators for injection ratio of $ratio_in \% \n"); + if(!programe_pck_gens($emulate,$sample,$ratio_in,$info,$jtag_intfc)){ + add_colored_info($info, "Error in programe_pck_gens function\n",'red'); + next; + } + my $r=read_pack_gen($emulate,$sample,$info,$jtag_intfc,$ratio_in); + next if (!defined $r); + set_gui_status($emulate,"ref",2); + } + $emulate->object_add_attribute ($sample,"status","done"); + + } + + add_colored_info($info, "End emulation!\n",'blue'); + $emulate->object_add_attribute('status',undef,'ideal'); + set_gui_status($emulate,"ref",1); } @@ -721,46 +574,46 @@ sub run_emulator { ############## -# process_notebook_gen +# process_notebook_gen ############## sub process_notebook_gen{ - my ($emulate,$info,$mode,$set_win,@charts)=@_; - my $notebook = gen_notebook(); - $notebook->set_tab_pos ('left'); - $notebook->set_scrollable(TRUE); - #$notebook->can_focus(FALSE); - - my $page1; - ($page1,$set_win)=gen_emulation_column($emulate, $mode,10,$info,$set_win,@charts); - $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run emulator ")) if($mode eq "emulate"); - $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run simulator ")) if($mode eq "simulate"); - - - my $page2=get_noc_setting_gui ($emulate,$info,$mode); - my $tt=($mode eq "emulate")? " _Generate NoC \nEmulation Model" : " _Generate NoC \nSimulation Model" ; - $notebook->append_page ($page2,gen_label_with_mnemonic ($tt)); - - - - my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($emulate,"process_sc_win")); - $scrolled_win->show_all; - my $page_num=$emulate->object_get_attribute ("process_notebook","currentpage"); - $notebook->set_current_page ($page_num) if(defined $page_num); - $notebook->signal_connect( 'switch-page'=> sub{ - $emulate->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber - - }); - - return ($scrolled_win,$set_win); - + my ($emulate,$info,$mode,$set_win,@charts)=@_; + my $notebook = gen_notebook(); + $notebook->set_tab_pos ('left'); + $notebook->set_scrollable(TRUE); + #$notebook->can_focus(FALSE); + + my $page1; + ($page1,$set_win)=gen_emulation_column($emulate, $mode,10,$info,$set_win,@charts); + $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run emulator ")) if($mode eq "emulate"); + $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run simulator ")) if($mode eq "simulate"); + + + my $page2=get_noc_setting_gui ($emulate,$info,$mode); + my $tt=($mode eq "emulate")? " _Generate NoC \nEmulation Model" : " _Generate NoC \nSimulation Model" ; + $notebook->append_page ($page2,gen_label_with_mnemonic ($tt)); + + + + my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($emulate,"process_sc_win")); + $scrolled_win->show_all; + my $page_num=$emulate->object_get_attribute ("process_notebook","currentpage"); + $notebook->set_current_page ($page_num) if(defined $page_num); + $notebook->signal_connect( 'switch-page'=> sub{ + $emulate->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber + + }); + + return ($scrolled_win,$set_win); + } sub get_noc_setting_gui { my ($emulate,$info_text,$mode)=@_; - my $table=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; + my $table=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; my $scrolled_win = gen_scr_win_with_adjst ($emulate,"noc_setting_gui"); add_widget_to_scrolled_win($table,$scrolled_win); my $row=noc_config ($emulate,$table,$info_text); @@ -770,15 +623,15 @@ sub get_noc_setting_gui { foreach my $dir (@dirs) { my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); $default=$name; - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; } my @fpgainfo; - if($mode eq "emulate"){ + if($mode eq "emulate"){ @fpgainfo = ( { label=>'Pck. injector FIFO Width:', param_name=>'TIMSTMP_FIFO_NUM', type=>'Spin-button', default_val=>16, content=>"2,128,2", info=>"Packet injectors' timestamp FIFO width. In case a packet cannot be injected according to the desired injection ratio, the current system time is saved in a FIFO and then at injection time it will be read and attached to the packet. The larger FIFO width results in more accurate latency calculation at the cost of higher area overhead." , param_parent=>'fpga_param', ref_delay=> undef}, { label=>'Save as:', param_name=>'SAVE_NAME', type=>"Entry", default_val=>'emulate1', content=>undef, info=>undef, param_parent=>'fpga_param', ref_delay=>undef}, { label=>"Project directory", param_name=>"SOF_DIR", type=>"DIR_path", default_val=>"$ENV{'PRONOC_WORK'}/emulate", content=>undef, info=>"Define the working directory for generating .sof file", param_parent=>'fpga_param',ref_delay=>undef }, - ); + ); } else { @fpgainfo = ( @@ -788,10 +641,10 @@ sub get_noc_setting_gui { ); } my $coltmp=0; - foreach my $d (@fpgainfo) { + foreach my $d (@fpgainfo) { ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}); } - my $maintable=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; + my $maintable=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; my $generate = def_image_button('icons/gen.png','Gener_ate',FALSE,1); my $diagram = def_image_button('icons/diagram.png','Diagram'); my $import = def_image_button('icons/import.png','I_mport',FALSE,1); @@ -803,7 +656,7 @@ sub get_noc_setting_gui { $maintable->attach ($import, 4,6, 9, 10,'expand','shrink',2,2); $diagram-> signal_connect("clicked" => sub{ show_topology_diagram ($emulate); - }); + }); $generate->signal_connect ('clicked'=> sub{ generate_sof_file($emulate,$info_text) if($mode eq "emulate"); generate_sim_bin_file($emulate,$info_text) if($mode eq "simulate"); @@ -811,54 +664,54 @@ sub get_noc_setting_gui { $import-> signal_connect("clicked" => sub{ import_noc_info_file($emulate,$mode); }); - $scrolled_win->show_all; - return $maintable; + $scrolled_win->show_all; + return $maintable; } sub import_noc_info_file{ - my ($self,$mode)=@_; - my $file; - my $dialog = gen_file_dialog(undef,'inf'); - - my $open_in = ($mode ne "emulate" ) ? abs_path("$ENV{'PRONOC_WORK'}/simulate") : abs_path("$ENV{'PRONOC_WORK'}/emulate"); - $dialog->set_current_folder ($open_in); - if ( "ok" eq $dialog->run ) { - my $status=1; - $file = $dialog->get_filename; - my $pp= do $file ; - my $p=$pp->{'noc_param'}; - $status=0 if $@; - message_dialog("Error reading: $@") if $@; - if ($status==1){ - $self->object_add_attribute ("noc_param",undef,$p); - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - my $attr1 = ($mode ne "emulate" ) ? 'sim_param' : 'fpga_param'; - $self->object_add_attribute ($attr1,'SAVE_NAME',$name); - - set_gui_status($self,"ref",1); - } - } - $dialog->destroy; + my ($self,$mode)=@_; + my $file; + my $dialog = gen_file_dialog(undef,'inf'); + + my $open_in = ($mode ne "emulate" ) ? abs_path("$ENV{'PRONOC_WORK'}/simulate") : abs_path("$ENV{'PRONOC_WORK'}/emulate"); + $dialog->set_current_folder ($open_in); + if ( "ok" eq $dialog->run ) { + my $status=1; + $file = $dialog->get_filename; + my $pp= do $file ; + my $p=$pp->{'noc_param'}; + $status=0 if $@; + message_dialog("Error reading: $@") if $@; + if ($status==1){ + $self->object_add_attribute ("noc_param",undef,$p); + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + my $attr1 = ($mode ne "emulate" ) ? 'sim_param' : 'fpga_param'; + $self->object_add_attribute ($attr1,'SAVE_NAME',$name); + + set_gui_status($self,"ref",1); + } + } + $dialog->destroy; } ########## -# generate_sof_file +# generate_sof_file ########## sub generate_sof_file { - my ($self,$info)=@_; - my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); - my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; - my $top = "$target_dir/src_verilog/${name}_top.v"; - - if (!defined $name){ - message_dialog("Please define the Save as filed!"); - return; - } + my ($self,$info)=@_; + my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); + my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; + my $top = "$target_dir/src_verilog/${name}_top.v"; + + if (!defined $name){ + message_dialog("Please define the Save as filed!"); + return; + } - #copy all noc source codes - my @files = ( + #copy all noc source codes + my @files = ( '/mpsoc/rtl/src_emulate/rtl/', '/mpsoc/rtl/src_peripheral/jtag/jtag_wb/', '/mpsoc/rtl/src_peripheral/ram/', @@ -868,460 +721,432 @@ sub generate_sof_file { '/mpsoc/rtl/src_topology/', '/mpsoc/rtl/src_noc/'); - my $dir = Cwd::getcwd(); - my $project_dir = abs_path("$dir/../../"); - my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("mkdir -p $target_dir/src_verilog" ); - copy_file_and_folders(\@files,$project_dir,"$target_dir/src_verilog/lib/"); - + my $dir = Cwd::getcwd(); + my $project_dir = abs_path("$dir/../../"); + my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("mkdir -p $target_dir/src_verilog" ); + copy_file_and_folders(\@files,$project_dir,"$target_dir/src_verilog/lib/"); + - #generate parameters for emulator_top.v file - gen_noc_localparam_v_file($self,"$target_dir/src_verilog/lib/src_noc/"); - - open(FILE, ">$top") || die "Can not open: $!"; - print FILE create_emulate_top($self,$name,$top); - close(FILE) || die "Error closing file: $!"; - select_compiler($self,$name,$top,$target_dir,\&save_the_sof_file); - + #generate parameters for emulator_top.v file + gen_noc_localparam_v_file($self,"$target_dir/src_verilog/lib/src_noc/"); + + open(FILE, ">$top") || die "Can not open: $!"; + print FILE create_emulate_top($self,$name,$top); + close(FILE) || die "Error closing file: $!"; + select_compiler($self,$name,$top,$target_dir,\&save_the_sof_file); + return; } sub create_emulate_top{ - my ($self,$name,$top)=@_; - my $top_v= get_license_header("$top"); + my ($self,$name,$top)=@_; + my $top_v= get_license_header("$top"); -$top_v ="$top_v +$top_v ="$top_v -`timescale 1ns/1ps +`timescale 1ns/1ps module ${name}_top( - output done_led, - output noc_reset_led, - output jtag_reset_led, - input reset, - input clk + output done_led, + output noc_reset_led, + output jtag_reset_led, + input reset, + input clk ); - localparam - STATISTIC_VJTAG_INDEX=124, - PATTERN_VJTAG_INDEX=125, - COUNTER_VJTAG_INDEX=126, - DONE_RESET_VJTAG_INDEX=127; - + localparam + STATISTIC_VJTAG_INDEX=124, + PATTERN_VJTAG_INDEX=125, + COUNTER_VJTAG_INDEX=126, + DONE_RESET_VJTAG_INDEX=127; + + - - wire reset_noc, reset_injector, reset_noc_sync, reset_injector_sync, done; - wire jtag_reset_injector, jtag_reset_noc; - wire start_o; - wire done_time_limit; - - assign done_led = done | done_time_limit; - assign noc_reset_led= reset_noc; - assign jtag_reset_led = reset_injector; + wire reset_noc, reset_injector, reset_noc_sync, reset_injector_sync, done; + wire jtag_reset_injector, jtag_reset_noc; + wire start_o; + wire done_time_limit; + + assign done_led = done | done_time_limit; + assign noc_reset_led= reset_noc; + assign jtag_reset_led = reset_injector; - + - // two reset sources which can be controled using jtag. One for reseting NoC another packet injectors - jtag_source_probe #( - .VJTAG_INDEX(DONE_RESET_VJTAG_INDEX), - .Dw(2) //source/probe width in bits - )the_reset( - .probe({done_time_limit,done}), - .source({jtag_reset_injector,jtag_reset_noc}) - ); - - - assign reset_noc = (jtag_reset_noc | reset); - assign reset_injector = (jtag_reset_injector | reset); - - altera_reset_synchronizer noc_rst_sync - ( - .reset_in(reset_noc), - .clk(clk), - .reset_out(reset_noc_sync) - ); - - - altera_reset_synchronizer inject_rst_sync - ( - .reset_in(reset_injector), - .clk(clk), - .reset_out(reset_injector_sync) - ); - - //noc emulator - - noc_emulator #( - .STATISTIC_VJTAG_INDEX(STATISTIC_VJTAG_INDEX), - .PATTERN_VJTAG_INDEX(PATTERN_VJTAG_INDEX), - .NOC_ID(0) - ) - noc_emulate_top - ( - .reset(reset_noc_sync), - .jtag_ctrl_reset(reset_injector_sync), - .clk(clk), - .start_o(start_o), - .done(done) - ); - - - - //clock counter - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2= clk_limit); + + localparam MAX_SIM_CLKs = 1_000_000_000; + localparam CLK_CNTw = log2(MAX_SIM_CLKs+1); + + reg [CLK_CNTw-1 : 0] clk_counter; + wire [CLK_CNTw-1 : 0] clk_limit; + reg start; + always @(posedge clk or posedge reset_injector_sync) begin + if(reset_injector_sync)begin + clk_counter <= {CLK_CNTw{1'b0}}; + start<=1'b0; + end else begin + if(start_o) start<=1'b1; + if(done==1'b0 && start ) clk_counter<=clk_counter +1'b1; + end + end + + jtag_source_probe #( + .VJTAG_INDEX(COUNTER_VJTAG_INDEX), + .Dw(CLK_CNTw) //source/probe width in bits + )the_clk_counter( + .probe(clk_counter), + .source(clk_limit) + ); + + assign done_time_limit = (clk_counter >= clk_limit); endmodule "; - return $top_v; + return $top_v; } sub save_the_sof_file{ - my $self=shift; - my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); - my $sofdir="$ENV{PRONOC_WORK}/emulate/sof"; - my $fpga_board=$self->object_get_attribute('compile','board'); - my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; - - mkpath("$sofdir/$fpga_board/",1,01777); - open(FILE, ">$sofdir/$fpga_board/$name.inf") || die "Can not open: $!"; - print FILE perl_file_header("$name.inf"); - my %pp; - $pp{'noc_param'}= $self->{'noc_param'}; - $pp{'fpga_param'}= $self->{'fpga_param'}; - print FILE Data::Dumper->Dump([\%pp],["emulate_info"]); - close(FILE) || die "Error closing file: $!"; - - - #find $dir_name -name \*.sof -exec cp '{}' $sofdir/$fpga_board/$save_name.sof" - my @files = File::Find::Rule->file() - ->name( '*.sof' ) - ->in( "$target_dir" ); - copy($files[0],"$sofdir/$fpga_board/$name.sof") or do { - my $err= "Error copy($files[0] , $sofdir/$fpga_board/$name.sof"; - print "$err\n"; - message_dialog($err,'error'); - return; - }; - #copy the board's programming and jtag interface files - - my $board_name=$self->object_get_attribute('compile','board'); - #copy board jtag_intfc.sh file - copy("../boards/Altera/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh"); - #print "../boards/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh\n"; - #add argument run to jtag_interface file - my $runarg=' + my $self=shift; + my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); + my $sofdir="$ENV{PRONOC_WORK}/emulate/sof"; + my $fpga_board=$self->object_get_attribute('compile','board'); + my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; + + mkpath("$sofdir/$fpga_board/",1,01777); + open(FILE, ">$sofdir/$fpga_board/$name.inf") || die "Can not open: $!"; + print FILE perl_file_header("$name.inf"); + my %pp; + $pp{'noc_param'}= $self->{'noc_param'}; + $pp{'fpga_param'}= $self->{'fpga_param'}; + print FILE Data::Dumper->Dump([\%pp],["emulate_info"]); + close(FILE) || die "Error closing file: $!"; + + + #find $dir_name -name \*.sof -exec cp '{}' $sofdir/$fpga_board/$save_name.sof" + my @files = File::Find::Rule->file() + ->name( '*.sof' ) + ->in( "$target_dir" ); + copy($files[0],"$sofdir/$fpga_board/$name.sof") or do { + my $err= "Error copy($files[0] , $sofdir/$fpga_board/$name.sof"; + print "$err\n"; + message_dialog($err,'error'); + return; + }; + #copy the board's programming and jtag interface files + + my $board_name=$self->object_get_attribute('compile','board'); + #copy board jtag_intfc.sh file + copy("../boards/Altera/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh"); + #print "../boards/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh\n"; + #add argument run to jtag_interface file + my $runarg=' if [ $# -ne 0 ] then $JTAG_INTFC $1 fi '; - append_text_to_file ("$sofdir/$fpga_board/jtag_intfc.sh",$runarg ); - - - + append_text_to_file ("$sofdir/$fpga_board/jtag_intfc.sh",$runarg ); + + + - #copy board program_device.sh file - copy("../boards/Altera/$board_name/program_device.sh","$sofdir/$fpga_board/program_device.sh"); - - + #copy board program_device.sh file + copy("../boards/Altera/$board_name/program_device.sh","$sofdir/$fpga_board/program_device.sh"); + + - message_dialog("sof file has been generated successfully"); + message_dialog("sof file has been generated successfully"); } ########## -# save_emulation +# save_emulation ########## sub save_emulation { - my ($emulate)=@_; - # read emulation name - my $name=$emulate->object_get_attribute ("emulate_name",undef); - my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; - if ($s == 0){ - message_dialog("Please set emulation name!"); - return 0; - } - # Write object file - open(FILE, ">lib/emulate/$name.EML") || die "Can not open: $!"; - print FILE perl_file_header("$name.EML"); - print FILE Data::Dumper->Dump([\%$emulate],["emulate"]); - close(FILE) || die "Error closing file: $!"; - message_dialog("Emulation saved as lib/emulate/$name.EML!"); - return 1; + my ($emulate)=@_; + # read emulation name + my $name=$emulate->object_get_attribute ("emulate_name",undef); + my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; + if ($s == 0){ + message_dialog("Please set emulation name!"); + return 0; + } + # Write object file + open(FILE, ">lib/emulate/$name.EML") || die "Can not open: $!"; + print FILE perl_file_header("$name.EML"); + print FILE Data::Dumper->Dump([\%$emulate],["emulate"]); + close(FILE) || die "Error closing file: $!"; + message_dialog("Emulation saved as lib/emulate/$name.EML!"); + return 1; } ############# -# load_emulation +# load_emulation ############ sub load_emulation { - my ($emulate,$info)=@_; - my $file; - my $dialog = gen_file_dialog (undef, 'EML'); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/emulate"); - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.EML'){ - - my ($pp,$r,$err) = regen_object($file); - if ($r ){ - add_colored_info($info,"**Error reading $file file: $err\n",'red'); - $dialog->destroy; - return; - } - - clone_obj($emulate,$pp); - #message_dialog("done!"); - } - } - $dialog->destroy; + my ($emulate,$info)=@_; + my $file; + my $dialog = gen_file_dialog (undef, 'EML'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/lib/emulate"); + + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.EML'){ + + my ($pp,$r,$err) = regen_object($file); + if ($r ){ + add_colored_info($info,"**Error reading $file file: $err\n",'red'); + $dialog->destroy; + return; + } + + clone_obj($emulate,$pp); + #message_dialog("done!"); + } + } + $dialog->destroy; } sub update_result { - my ($self,$sample,$name,$x,$y,$z)=@_; - my $ref=$self->object_get_attribute ($sample,$name); - my %results; - %results= %{$ref} if(defined $ref); - if(!defined $z) {$results{$x}=$y;} - else {$results{$x}{$y}=$z;} - $self->object_add_attribute ($sample,$name,\%results); -} + my ($self,$sample,$name,$x,$y,$z)=@_; + my $ref=$self->object_get_attribute ($sample,$name); + my %results; + %results= %{$ref} if(defined $ref); + if(!defined $z) {$results{$x}=$y;} + else {$results{$x}{$y}=$z;} + $self->object_add_attribute ($sample,$name,\%results); +} sub gen_sim_parameter_h { - my ($param_h,$includ_h,$ne,$nr,$router_p,$fifow)=@_; - - $param_h =~ s/\d\'b/ /g; - my $text= " -#ifndef INCLUDE_PARAM - #define INCLUDE_PARAM \n \n - - $param_h - - #define NE $ne - #define NR $nr - #define ROUTER_P_NUM $router_p - - extern Vtraffic *traffic[NE]; - extern Vpck_inj *pck_inj[NE]; - extern int reset,clk; - - //simulation parameter - #define MAX_RATIO ".MAX_RATIO." - #define AVG_LATENCY_METRIC \"HEAD_2_TAIL\" - #define TIMSTMP_FIFO_NUM $fifow + my ($param_h,$includ_h,$ne,$nr,$router_p,$fifow)=@_; + + $param_h =~ s/\d\'b/ /g; + my $text= " +#ifndef INCLUDE_PARAM + #define INCLUDE_PARAM \n \n + + $param_h + + #define NE $ne + #define NR $nr + #define ROUTER_P_NUM $router_p - $includ_h + extern Vtraffic *traffic[NE]; + extern Vpck_inj *pck_inj[NE]; + extern int reset,clk; + + //simulation parameter + #define MAX_RATIO ".MAX_RATIO." + #define AVG_LATENCY_METRIC \"HEAD_2_TAIL\" + #define TIMSTMP_FIFO_NUM $fifow + + $includ_h \n \n \#endif" ; - return $text; -} + return $text; +} sub gen_noc_sim_param { - my $simulate=shift; - my $fifow=$simulate->object_get_attribute('fpga_param','TIMSTMP_FIFO_NUM'); - - $fifow= '16' if (!defined $fifow); - - return " - //simulation parameter - //localparam MAX_RATIO = ".MAX_RATIO."; - localparam MAX_PCK_NUM = ".MAX_SIM_CLKs."; - localparam MAX_PCK_SIZ = ".MAX_PCK_SIZ."; - localparam MAX_SIM_CLKs= ".MAX_SIM_CLKs."; - localparam TIMSTMP_FIFO_NUM = $fifow; - "; - + my $simulate=shift; + my $fifow=$simulate->object_get_attribute('fpga_param','TIMSTMP_FIFO_NUM'); + + $fifow= '16' if (!defined $fifow); + + return " + //simulation parameter + //localparam MAX_RATIO = ".MAX_RATIO."; + localparam MAX_PCK_NUM = ".MAX_SIM_CLKs."; + localparam MAX_PCK_SIZ = ".MAX_PCK_SIZ."; + localparam MAX_SIM_CLKs= ".MAX_SIM_CLKs."; + localparam TIMSTMP_FIFO_NUM = $fifow; + "; + } sub gen_noc_localparam_v_file { - my ($self,$dst_path,$sample,$noc_id)=@_; - $noc_id="" if(!defined $noc_id); - # generate NoC parameter file - my ($noc_param,$pass_param)=gen_noc_param_v($self,$sample,$noc_id); - my $header=autogen_warning().get_license_header("noc_localparam.v"); - open(FILE, ">${dst_path}/noc_localparam.v") || die "Can not open: $!"; - my $sim =gen_noc_sim_param($self); - print FILE "$header - - \`ifdef NOC_LOCAL_PARAM \n \n - $noc_param - - $sim - + my ($self,$dst_path,$sample,$noc_id)=@_; + $noc_id="" if(!defined $noc_id); + # generate NoC parameter file + my ($noc_param,$pass_param)=gen_noc_param_v($self,$sample,$noc_id); + my $header=autogen_warning().get_license_header("noc_localparam.v"); + open(FILE, ">${dst_path}/noc_localparam.v") || die "Can not open: $!"; + my $sim =gen_noc_sim_param($self); + print FILE "$header + + \`ifdef NOC_LOCAL_PARAM \n \n + $noc_param + + $sim + \n \n \`endif"; - close FILE; + close FILE; } +sub noc_emulate_ctrl{ + my ($self,$info)=@_; + my $generate = def_image_button('icons/forward.png','Run all',FALSE,1); + my ($entrybox,$entry ) =gen_save_load_widget ( + $self, #the object + "Name",#the label shown for setting configuration + "emulate_name",#the key name for saveing the setting configuration in object + "Experiment name",#the label full name show in tool tips + undef,#Where the generted RTL files are loacted. Undef if not aplicaple + 0,#check the given name match the SoC or mpsoc name rules + "lib/emulate/",#where the current configuration seting file is saved + "EML",#the extenstion given for configuration seting file + \&load_emulation, + $info); + + $generate-> signal_connect("clicked" => sub{ + my @samples =$self->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + $self->object_add_attribute ($sample,"status","run"); + } + run_emulator($self,$info); + }); + + my $table = def_table (1, 12, FALSE); + $table->attach ($entrybox, 0, 5, 0,1,'expand','shrink',2,2); + $table->attach ($generate, 5, 8, 0,1,'expand','shrink',2,2); + return add_widget_to_scrolled_win($table,gen_scr_win_with_adjst($self,"ctrl_emul_win")); +} ############ # main ############ sub emulator_main{ - - add_color_to_gd(); - my $emulate= emulator->emulator_new(); - set_gui_status($emulate,"ideal",0); - $emulate->object_add_attribute('compile','compilers',"QuartusII"); - my $left_table = def_table (25, 6, FALSE); - my $right_table =def_table (25, 6, FALSE); - my $main_table = def_table (25, 12, FALSE); - my ($infobox,$info)= create_txview(); - - - - my @pages =( - {page_name=>" Avg. throughput/latency", page_num=>0}, - {page_name=>" Injected Packet ", page_num=>1}, - {page_name=>" Worst-Case Delay ",page_num=>2}, - {page_name=>" Execution Time ",page_num=>3}, - ); - - my @charts = ( - { type=>"2D_line", page_num=>0, graph_name=> "Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Latency (clock)', Z_Title=>undef, Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Throughput", result_name => "throughput_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Throughput (flits/clock (%))', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Received", result_name => "packet_rsvd_result", X_Title=>'Core ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Sent", result_name => "packet_sent_result", X_Title=>'Core ID' , Y_Title=>'Sent Packets Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>2, graph_name=> "Received", result_name => "worst_delay_rsvd_result",X_Title=>'Core ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, - { type=>"2D_line", page_num=>3, graph_name=> "-", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Emulation Time (clk)', Z_Title=>undef}, - ); - - my ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate", undef,@charts); - my $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); - - $main_table->set_row_spacings (4); - $main_table->set_col_spacings (1); - - my $generate = def_image_button('icons/forward.png','Run all'); - my $open = def_image_button('icons/browse.png','Load'); - my $diagram = def_image_button('icons/diagram.png','Diagram'); - - my ($entrybox,$entry) = def_h_labeled_entry('Save as:',undef); - - $entry->signal_connect( 'changed'=> sub{ - my $name=$entry->get_text(); - $emulate->object_add_attribute ("emulate_name",undef,$name); - }); - my $save = def_image_button('icons/save.png','Save'); - $entrybox->pack_end($save, FALSE, FALSE,0); - - my $image = get_status_gif($emulate); - my $v1=gen_vpaned($conf_box,.45,$image); - my $v2=gen_vpaned($infobox,.2,$chart); - my $h1=gen_hpaned($v1,.4,$v2); - - #$table->attach_defaults ($event_box, $col, $col+1, $row, $row+1); - $main_table->attach_defaults ($h1 , 0, 12, 0,24); - $main_table->attach ($open,0, 2, 24,25,'expand','shrink',2,2); -# $main_table->attach ($diagram, 2, 4, 24,25,'expand','shrink',2,2); - $main_table->attach ($entrybox,4, 7, 24,25,'expand','shrink',2,2); - $main_table->attach ($generate, 7, 9, 24,25,'expand','shrink',2,2); - - #check soc status every 0.5 second. referesh device table if there is any changes - Glib::Timeout->add (100, sub{ - my ($state,$timeout)= get_gui_status($emulate); - - if ($timeout>0){ - $timeout--; - set_gui_status($emulate,$state,$timeout); - return TRUE; - } - if($state eq "ideal"){ - return TRUE; - - } - - - #refresh GUI - my $name=$emulate->object_get_attribute ("emulate_name",undef); - $entry->set_text($name) if(defined $name); - $conf_box->destroy(); - $chart->destroy(); - $image->destroy(); - $image = get_status_gif($emulate); - ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate",$set_win, @charts); - $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); - $v1 -> pack1($conf_box, TRUE, TRUE); - $v1 -> pack2($image, TRUE, TRUE); - $v2 -> pack2($chart, TRUE, TRUE); - $conf_box->show_all(); - $main_table->show_all(); - set_gui_status($emulate,"ideal",0); - - return TRUE; - - } ); - - $diagram-> signal_connect("clicked" => sub{ - show_topology_diagram ($emulate); - }); - - $generate-> signal_connect("clicked" => sub{ - my @samples =$emulate->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - $emulate->object_add_attribute ($sample,"status","run"); - } - run_emulator($emulate,$info); - }); - - - $open-> signal_connect("clicked" => sub{ - load_emulation($emulate,$info); - set_gui_status($emulate,"ref",5); - }); - - $save-> signal_connect("clicked" => sub{ - save_emulation($emulate); - set_gui_status($emulate,"ref",5); - }); - - - - return add_widget_to_scrolled_win($main_table); + add_color_to_gd(); + my $emulate= emulator->emulator_new(); + set_gui_status($emulate,"ideal",0); + $emulate->object_add_attribute('compile','compilers',"QuartusII"); + my $left_table = def_table (25, 6, FALSE); + my $right_table =def_table (25, 6, FALSE); + my $main_table = def_table (25, 12, FALSE); + my ($infobox,$info)= create_txview(); + my @pages =( + {page_name=>" Avg. throughput/latency", page_num=>0}, + {page_name=>" Injected Packet ", page_num=>1}, + {page_name=>" Worst-Case Delay ",page_num=>2}, + {page_name=>" Execution Time ",page_num=>3}, + ); + my @charts = ( + { type=>"2D_line", page_num=>0, graph_name=> "Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Latency (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Throughput", result_name => "throughput_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Throughput (flits/clock (%))', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Received", result_name => "packet_rsvd_result", X_Title=>'Core ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Sent", result_name => "packet_sent_result", X_Title=>'Core ID' , Y_Title=>'Sent Packets Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>2, graph_name=> "Received", result_name => "worst_delay_rsvd_result",X_Title=>'Core ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, + { type=>"2D_line", page_num=>3, graph_name=> "-", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Emulation Time (clk)', Z_Title=>undef}, + ); + my ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate", undef,@charts); + my $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); + $main_table->set_row_spacings (4); + $main_table->set_col_spacings (1); + my $ctrl = noc_emulate_ctrl($emulate,$info); + my $image = get_status_gif($emulate); + my $v1=gen_vpaned($conf_box,.45,$image); + my $v2=gen_vpaned($infobox,.2,$chart); + my $h1=gen_hpaned($v1,.4,$v2); + #$table->attach_defaults ($event_box, $col, $col+1, $row, $row+1); + $main_table->attach_defaults ($h1 , 0, 12, 0,24); + $main_table->attach ($ctrl, 0,12, 24,25,'fill','fill',2,2); + #check soc status every 0.5 second. referesh device table if there is any changes + Glib::Timeout->add (100, sub{ + my ($state,$timeout)= get_gui_status($emulate); + if ($timeout>0){ + $timeout--; + set_gui_status($emulate,$state,$timeout); + return TRUE; + } + if($state eq "ideal"){ + return TRUE; + } + #refresh GUI + $ctrl->destroy(); + $conf_box->destroy(); + $chart->destroy(); + $image->destroy(); + $image = get_status_gif($emulate); + ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate",$set_win, @charts); + $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); + $ctrl = noc_emulate_ctrl($emulate,$info); + $main_table->attach ($ctrl, 0,12, 24,25,'fill','fill',2,2); + $v1 -> pack1($conf_box, TRUE, TRUE); + $v1 -> pack2($image, TRUE, TRUE); + $v2 -> pack2($chart, TRUE, TRUE); + $conf_box->show_all(); + $main_table->show_all(); + set_gui_status($emulate,"ideal",0); + return TRUE; + } ); + return add_widget_to_scrolled_win($main_table); } diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index 6d02704..5e75a24 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -3248,16 +3248,13 @@ sub add_mpsoc_to_device{ sub ctrl_box{ my ($mpsoc,$info)=@_; my $table = def_table (1, 12, FALSE); - my $generate = def_image_button('icons/gen.png','_Generate RTL',FALSE,1); + my $generate = def_image_button('icons/gen.png','_Generate RTL',FALSE,1); my $compile = def_image_button('icons/gate.png','_Compile RTL',FALSE,1); - my $software = def_image_button('icons/binary.png','_Software',FALSE,1); + my $software = def_image_button('icons/binary.png','_Software',FALSE,1); my $diagram = def_image_button('icons/diagram.png','Diagram'); - my $clk= def_image_button('icons/clk.png','CLK setting'); - + my $clk= def_image_button('icons/clk.png','CLK setting'); my $row=0; - - - my $target_dir= "$ENV{'PRONOC_WORK'}/MPSOC"; + my $target_dir= "$ENV{'PRONOC_WORK'}/MPSOC"; my ($entrybox,$entry ) =gen_save_load_widget ( $mpsoc, #the object "MPSoC name",#the label shown for setting configuration @@ -3270,19 +3267,16 @@ sub ctrl_box{ \&load_mpsoc,#refrence to load function $info ); - $table->attach ($entrybox,$row, $row+2, 0,1,'expand','shrink',2,2);$row+=2; $table->attach ($diagram, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; $table->attach ($clk, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; $table->attach ($generate, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; $table->attach ($software, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; $table->attach ($compile, $row, $row+1, 0,1,'expand','shrink',2,2);$row++; - $generate-> signal_connect("clicked" => sub{ generate_mpsoc($mpsoc,$info,1); set_gui_status($mpsoc,"refresh_soc",1); }); - $compile -> signal_connect("clicked" => sub{ $mpsoc->object_add_attribute('compile','compilers',"QuartusII,Vivado,Verilator,Modelsim"); my $name=$mpsoc->object_get_attribute('mpsoc_name'); @@ -3301,8 +3295,7 @@ sub ctrl_box{ message_dialog("Cannot find $top_file file. Please run RTL Generator first!"); return; } - }); - + }); $software -> signal_connect("clicked" => sub{ my $name=$mpsoc->object_get_attribute('mpsoc_name'); $name="" if (!defined $name); @@ -3317,22 +3310,17 @@ sub ctrl_box{ return; } software_edit_mpsoc($mpsoc); - }); - $diagram-> signal_connect("clicked" => sub{ show_topology_diagram ($mpsoc); }); - $clk-> signal_connect("clicked" => sub{ - clk_setting_win1($mpsoc,$info,'mpsoc'); + clk_setting_win1($mpsoc,$info,'mpsoc'); }); - - return $table; + return $table; } - sub gen_save_load_widget { my ( $self, #the object @@ -3345,20 +3333,18 @@ sub gen_save_load_widget { $extention,#the extenstion given for configuration seting file $load_func, $info - )=@_; + )=@_; my $load = def_image_button('icons/load2.png'); my $entry=gen_entry_object($self,$param_name,undef,undef,undef,undef); my $entrybox=gen_label_info("$label:",$entry); - my $save = def_image_button('icons/save.png'); + my $save = def_image_button('icons/save.png'); my $open_dir = def_image_button('icons/open-folder.png') if (defined $target_dir); set_tip($save, "Save current $full_name configuration setting"); set_tip($load, "Load a saved $full_name configuration setting"); set_tip($open_dir, "Open target $full_name folder") if (defined $target_dir); - $entrybox->pack_start( $save, FALSE, FALSE, 0); $entrybox->pack_start( $load, FALSE, FALSE, 0); $entrybox->pack_start( $open_dir , FALSE, FALSE, 0) if (defined $target_dir); - $open_dir-> signal_connect("clicked" => sub{ my $name=$self->object_get_attribute($param_name); $name="" if (!defined $name); @@ -3374,13 +3360,12 @@ sub gen_save_load_widget { } system "xdg-open $target_dir/$name"; }) if (defined $target_dir); - $save-> signal_connect("clicked" => sub{ my $name=$self->object_get_attribute($param_name); - if (length($name)==0){ + if (length($name)==0){ message_dialog("Please define the $label!"); return ; - } + } return if(check_mpsoc_name($name,$label) && $check=='mpsoc') ; return if(check_soc_name($name,$label) && $check=='soc') ; # Write object file @@ -3389,20 +3374,16 @@ sub gen_save_load_widget { print FILE perl_file_header("${name}.$extention"); print FILE Data::Dumper->Dump([\%$self],[$extention]); close(FILE) || die "Error closing file: $!"; - message_dialog("Current configuration \"$name\" is saved as $config_file."); - + message_dialog("Current configuration \"$name\" is saved as $config_file."); }); - $entry->signal_connect( 'changed'=> sub{ my $name=$entry->get_text(); - $self->object_add_attribute ("save_as",undef,$name); - }); - - $load-> signal_connect("clicked" => sub{ + $self->object_add_attribute ("save_as",undef,$name); + }); + $load-> signal_connect("clicked" => sub{ + &$load_func($self,$info); set_gui_status($self,"ref",5); - &$load_func($self,$info); }); - return ($entrybox,$entry); } @@ -3413,67 +3394,54 @@ sub mpsocgen_main{ my $infc = interface->interface_new(); my $soc = ip->lib_new (); my $mpsoc= mpsoc->mpsoc_new(); - set_gui_status($mpsoc,"ideal",0); my $main_table = def_table (25, 12, FALSE); - # The box which holds the info, warning, error ... messages - my ($infobox,$info)= create_txview(); - + my ($infobox,$info)= create_txview(); my $noc_conf_box=get_config ($mpsoc,$info); my $noc_tiles=gen_tiles($mpsoc); - - $main_table->set_row_spacings (4); $main_table->set_col_spacings (1); - my $ctrl=ctrl_box($mpsoc,$info); + my $ctrl=ctrl_box($mpsoc,$info); my $h1=gen_hpaned($noc_conf_box,.3,$noc_tiles); my $v2=gen_vpaned($h1,.55,$infobox); my $row=0; $main_table->attach_defaults ($v2 , 0, 12, 0,24); #$main_table->attach_defaults ($ctrl,0, 12, 24,25); $main_table->attach ($ctrl,0, 12, 24,25, 'fill','fill',2,2); - #check soc status every 0.5 second. refresh device table if there is any changes Glib::Timeout->add (100, sub{ my ($state,$timeout)= get_gui_status($mpsoc); if ($timeout>0){ $timeout--; - set_gui_status($mpsoc,$state,$timeout); + set_gui_status($mpsoc,$state,$timeout); }elsif ($state eq 'save_project'){ # Write object file my $name=$mpsoc->object_get_attribute('mpsoc_name'); open(FILE, ">lib/mpsoc/$name.MPSOC") || die "Can not open: $!"; print FILE perl_file_header("$name.MPSOC"); print FILE Data::Dumper->Dump([\%$mpsoc],[$name]); - close(FILE) || die "Error closing file: $!"; - set_gui_status($mpsoc,"ideal",0); + close(FILE) || die "Error closing file: $!"; + set_gui_status($mpsoc,"ideal",0); } elsif( $state ne "ideal" ){ $noc_conf_box->destroy(); $noc_conf_box=get_config ($mpsoc,$info); $noc_tiles->destroy(); - $noc_tiles=gen_tiles($mpsoc); - $h1 -> pack1($noc_conf_box, TRUE, TRUE); - $h1 -> pack2($noc_tiles, TRUE, TRUE); - $v2-> pack1($h1, TRUE, TRUE); + $noc_tiles=gen_tiles($mpsoc); + $h1 -> pack1($noc_conf_box, TRUE, TRUE); + $h1 -> pack2($noc_tiles, TRUE, TRUE); + $v2-> pack1($h1, TRUE, TRUE); $h1->show_all; $ctrl->destroy; $ctrl=ctrl_box($mpsoc,$info); $main_table->attach ($ctrl,0, 12, 24,25,'fill','fill',2,2); $main_table->show_all(); - - set_gui_status($mpsoc,"ideal",0); - - - } + } return TRUE; - } ); - - my $sc_win = add_widget_to_scrolled_win($main_table); - + my $sc_win = add_widget_to_scrolled_win($main_table); return $sc_win; } diff --git a/mpsoc/perl_gui/lib/perl/simulator.pl b/mpsoc/perl_gui/lib/perl/simulator.pl index aab51aa..4142cbe 100755 --- a/mpsoc/perl_gui/lib/perl/simulator.pl +++ b/mpsoc/perl_gui/lib/perl/simulator.pl @@ -204,40 +204,16 @@ sub generate_sim_bin_file { set_gui_status($simulate,"ref",1); } -########## -# save_simulation -########## -sub save_simulation { - my ($simulate)=@_; - # read emulation name - my $name=$simulate->object_get_attribute ("simulate_name",undef); - my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; - if ($s == 0){ - message_dialog("Please set Simulation name!"); - return 0; - } - # Write object file - open(FILE, ">lib/simulate/$name.SIM") || die "Can not open: $!"; - print FILE perl_file_header("$name.SIM"); - print FILE Data::Dumper->Dump([\%$simulate],["simulate"]); - close(FILE) || die "Error closing file: $!"; - message_dialog("Simulation has saved as lib/simulate/$name.SIM!"); - return 1; -} ############# # load_simulation ############ - sub load_simulation { my ($simulate,$info)=@_; my $file; - my $dialog = gen_file_dialog (undef, 'SIM'); - + my $dialog = gen_file_dialog (undef, 'SIM'); my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/simulate"); - - + $dialog->set_current_folder ("$dir/lib/simulate"); if ( "ok" eq $dialog->run ) { $file = $dialog->get_filename; my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); @@ -252,19 +228,15 @@ sub load_simulation { $pp->object_add_attribute('status',undef,'ideal'); my @samples =$pp->object_get_attribute_order("samples"); foreach my $sample (@samples){ - my $st=$pp->object_get_attribute ($sample,"status"); - $pp->object_add_attribute ($sample,"status",'done');# if ($st eq "run"); + my $st=$pp->object_get_attribute ($sample,"status"); + $pp->object_add_attribute ($sample,"status",'done');# if ($st eq "run"); } clone_obj($simulate,$pp); - #message_dialog("done!"); - } - } - $dialog->destroy; + } + } + $dialog->destroy; } - - - sub check_hotspot_parameters{ my ($self,$sample)=@_; my $num=$self->object_get_attribute($sample,"HOTSPOT_NUM"); @@ -280,11 +252,9 @@ sub check_hotspot_parameters{ push( @hotspots,$w1); my $w2 = $self->object_get_attribute($sample,"HOTSPOT_PERCENT_$i"); $acuum+=$w2; - } if ($acuum > 100){ $result="Error: The traffic summation of all hotspot nodes is $acuum. The hotspot summation must be <=100"; - } } return $result; @@ -296,7 +266,6 @@ sub get_district_avg { $vt = "2,3,4,5" unless (defined $vt); my $pt=$self->object_get_attribute($sample,"PROBEB_RANGE"); $pt= "25,25,25,25" unless (defined $pt); - my $avg=0; my @valus = split(',',$vt); my @probs = split(',',$pt); @@ -314,7 +283,6 @@ sub get_district_avg { } return ("-","The summation of probebilities are $sum which is not equal 100.") if($sum!=100); $avg/=100; - $self->object_add_attribute ($sample,"MIN_PCK_SIZE",$min); $self->object_add_attribute ($sample,"MAX_PCK_SIZE",$max); return ($avg,undef); @@ -322,37 +290,32 @@ sub get_district_avg { sub get_simulator_noc_configuration{ my ($self,$mode,$sample,$set_win) =@_; - my $table=def_table(10,2,FALSE); my $row=0; - - my $scrolled_win = add_widget_to_scrolled_win ($table,gen_scr_win_with_adjst($self,'noc_conf_scr_win')); - my $ok = def_image_button('icons/select.png','_OK',FALSE,1); my $import = def_image_button('icons/import.png','I_mport',FALSE,1); my $save = def_image_button('icons/save.png','_Export',FALSE,1); - $save ->signal_connect("clicked"=> sub{ my $dialog=save_file_dialog ("Enter configuration file name",'conf'); #$dialog->set_current_folder ($open_in) if(defined $open_in); if ( "ok" eq $dialog->run ) { - my $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + my $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); my $t=$self->object_get_attribute($sample); open(FILE, ">$path/${name}.conf") || die "Can not open: $!"; print FILE Data::Dumper->Dump([\$t],['config']); close FILE; - } - $dialog->destroy(); + } + $dialog->destroy(); }); $import ->signal_connect("clicked"=> sub{ my $dialog=save_file_dialog ("Enter configuration file name",'conf'); #$dialog->set_current_folder ($open_in) if(defined $open_in); if ( "ok" eq $dialog->run ) { - my $file = $dialog->get_filename; - my $pp= do $file ; + my $file = $dialog->get_filename; + my $pp= do $file; my $status=1; $status=0 if $@; message_dialog("Error reading: $@") if $@; @@ -361,36 +324,24 @@ sub get_simulator_noc_configuration{ set_gui_status($self,'ref_set_win',1); } } - $dialog->destroy(); + $dialog->destroy(); }); - - - my $mtable = def_table(10, 3, TRUE); - $mtable->attach_defaults($scrolled_win,0,3,0,9); $mtable-> attach ($ok , 1, 2, 9, 10,'expand','shrink',2,2); $mtable-> attach ($import , 0, 1, 9, 10,'expand','shrink',2,2); $mtable-> attach ($save , 2, 3, 9, 10,'expand','shrink',2,2); - - - $set_win ->signal_connect (destroy => sub{ $self->object_add_attribute("active_setting",undef,undef); - }); - + }); my $dir = Cwd::getcwd(); my $open_in = abs_path("$ENV{PRONOC_WORK}/simulate"); - attach_widget_to_table ($table,$row,gen_label_in_left(" Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), get_dir_in_object ($self,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; - - $open_in = $self->object_get_attribute($sample,"sof_path"); - - + $open_in = $self->object_get_attribute($sample,"sof_path"); my @files = glob "$open_in/*"; my $exe_files=""; @@ -398,204 +349,140 @@ sub get_simulator_noc_configuration{ my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); if($suffix eq '.inf'){ $exe_files="$exe_files,$name"; - } + } } my $model_obj = gen_combobox_object ($self,$sample, "sof_file", $exe_files, undef,'ref_set_win',1); attach_widget_to_table ($table,$row,gen_label_in_left(" Verilated Model:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), $model_obj); $row++; - my $cast_type= '"UNICAST"'; - #get simulation parameters here - my $s=$self->object_get_attribute($sample,"sof_file"); - if (defined $s){ - my ($infobox,$info)= create_txview(); - my $sof=get_sim_bin_path($self,$sample,$info); - my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); + my $s=$self->object_get_attribute($sample,"sof_file"); + if (defined $s){ + my ($infobox,$info)= create_txview(); + my $sof=get_sim_bin_path($self,$sample,$info); + my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); my $sof_info= "$path$name.inf"; - - my $pp= do $sof_info ; + my $pp= do $sof_info ; my $p=$pp->{'noc_param'}; - $cast_type = $p->{'CAST_TYPE'}; - $cast_type= '"UNICAST"' if (!defined $cast_type); - } - - my $trf_info = "Select of the following traffic models: - 1- Synthetic - 2- Task-graph : - The task graph traffic pattern can be generated - using ProNoC trace generator - 3- Netrace: - Dependency-Tracking Trace-Based Network-on-Chip - Simulation. For downloading the trace files and more - information refere to https://www.cs.utexas.edu/~netrace/ - 4- SynFull: - Synthetic Traffic Models Capturing a Full Range - of Cache Coherent Behaviour - https://github.com/mariobadr/synfull-isca + $cast_type = $p->{'CAST_TYPE'}; + $cast_type= '"UNICAST"' if (!defined $cast_type); + } + my $trf_info = "Select of the following traffic models: + 1- Synthetic + 2- Task-graph : + The task graph traffic pattern can be generated + using ProNoC trace generator + 3- Netrace: + Dependency-Tracking Trace-Based Network-on-Chip + Simulation. For downloading the trace files and more + information refere to https://www.cs.utexas.edu/~netrace/ + 4- SynFull: + Synthetic Traffic Models Capturing a Full Range + of Cache Coherent Behaviour + https://github.com/mariobadr/synfull-isca "; - my $coltmp=0; ($row,$coltmp)=add_param_widget ($self, "Traffic Type", "TRAFFIC_TYPE", "Synthetic", 'Combo-box', "Synthetic,Task-graph,SynFull,Netrace", $trf_info, $table,$row,undef,1, $sample, 1,'ref_set_win'); - my $traffictype=$self->object_get_attribute($sample,"TRAFFIC_TYPE"); my $MIN_PCK_SIZE=$self->object_get_attribute($sample,"MIN_PCK_SIZE"); - - - - my $max_pck_num = get_MAX_PCK_NUM(); - my $max_sim_clk = get_MAX_SIM_CLKs(); - - my $pck_info = "Select how injected packet size are selected. + my $max_pck_num = get_MAX_PCK_NUM(); + my $max_sim_clk = get_MAX_SIM_CLKs(); + my $pck_info = "Select how injected packet size are selected. random-range: The injected packet size is randomly selected between given minimum and maximum packet size. random-discrete: The injected packet size is randomly selected among given district valuse."; - if($traffictype eq "Synthetic"){ - my $min=$self->object_get_attribute($sample,'MIN_PCK_SIZE'); my $max=$self->object_get_attribute($sample,'MAX_PCK_SIZE'); $min=5 if(!defined $min); $max=5 if(!defined $max); $max= $min if($max< $min); - my $avg=floor(($min+$max)/2); + my $avg=floor(($min+$max)/2); my $msg; - my $max_pck_size = get_MAX_PCK_SIZ(); - + my $max_pck_size = get_MAX_PCK_SIZ(); my $NE; my ($infobox,$info)= create_txview(); - - my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,hot spot,shuffle,bit rotation,neighbor,custom"; my @synthinfo = ( - - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - - { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>"Traffic name", param_name=>'traffic', type=>'Combo-box', default_val=>'random', content=>$traffics, info=>"Select traffic pattern", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - { label=>"Packet size (#flit)", param_name=>'PCK_SIZ_SEL', type=>'Combo-box', default_val=>'random-range', content=>"random-range,random-discrete", info=>$pck_info, param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - ); my $coltmp=0; - foreach my $d (@synthinfo) { - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } my $t=$self->object_get_attribute($sample,"PCK_SIZ_SEL"); if($t eq 'random-range' ){ - @synthinfo = ( { label=>"Min pck size :", param_name=>'MIN_PCK_SIZE', type=>'Spin-button', default_val=>5, content=>"1,$max,1", info=>"Minimum packet size in flit. The injected packet size is randomly selected between minimum and maximum packet size", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, { label=>"Max pck size :", param_name=>'MAX_PCK_SIZE', type=>'Spin-button', default_val=>5, content=>"$min,$max_pck_size,1", info=>"Maximum packet size in flit. The injected packet size is randomly selected between minimum and maximum packet size", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, { label=>"Avg. Packet size:", param_name=>'PCK_SIZE', type=>'Fixed', default_val=>$avg, content=>"$avg", info=>undef, param_parent=>$sample, ref_delay=>undef}, ); - }else{ #$self->object_add_attribute ($sample,"MIN_PCK_SIZE",2);#will be updated by get_district_avg my $vt=$self->object_get_attribute($sample,"DISCRETE_RANGE"); $vt = "2,3,4,5" unless (defined $vt); my $pt=$self->object_get_attribute($sample,"PROBEB_RANGE"); $pt= "25,25,25,25" unless (defined $pt); - - #($avg,$msg) = get_district_avg($self,$sample); - - - @synthinfo = ( + @synthinfo = ( { label=>"pck size discrete range: ", param_name=>'DISCRETE_RANGE', type=>'Entry', default_val=>$vt, content=>undef, info=>"Set discrete set of number as packet size separated by \",\" (v1,v2,v3 ..). The injected packet size is randomly selected among these discrete values", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, { label=>"pck size probebility(%): ", param_name=>'PROBEB_RANGE' , type=>'Entry', default_val=>$pt, content=>undef, info=>"Set the probability separated by \",\" (p1,p2,p3 ..). The probabilities pi must satisfy two requirements: every probability pi is a number between 0 and 100, and the sum of all the probabilities is 100.", param_parent=>$sample, ref_delay=>10, new_status=>'ref_set_win'}, - # { label=>"Avg. Packet size:", param_name=>'PCK_SIZE', type=>'Fixed', default_val=>$avg, content=>"$avg", info=>undef, param_parent=>$sample, ref_delay=>undef}, + # { label=>"Avg. Packet size:", param_name=>'PCK_SIZE', type=>'Fixed', default_val=>$avg, content=>"$avg", info=>undef, param_parent=>$sample, ref_delay=>undef}, ); - - - } - + } foreach my $d (@synthinfo){ - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); } if(defined $msg){ - my $error= def_image_button("icons/cancel.png"); - $table->attach ($error , 6, 7, $row-1,$row,'shrink','shrink',2,2); - } - - + my $error= def_image_button("icons/cancel.png"); + $table->attach ($error , 6, 7, $row-1,$row,'shrink','shrink',2,2); + } my $traffic=$self->object_get_attribute($sample,"traffic"); - my $st = check_sim_sample($self,$sample,$info); if ($st==0){ $NE=100; }else{ my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); my ($NEe, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - $NE=$NEe; + $NE=$NEe; } - - if ($traffic eq 'custom'){ - - my $htable=def_table(10,2,FALSE); - my $d= { label=>'number of active nodes:', param_name=>'CUSTOM_SRC_NUM', type=>'Spin-button', default_val=>1, content=>"1,$NE,1", info=>"Number of active nodes which injects packets to the NoC", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); $htable->attach ( gen_label_in_left ("Source "), 0, 1, $row,$row+1,'fill','shrink',2,2); $htable->attach ( gen_label_in_left (" -> "), 1, 2, $row,$row+1,'fill','shrink',2,2); $htable->attach ( gen_label_in_left ("Destination"), 2, 3, $row,$row+1,'fill','shrink',2,2); - $row++; - - my $tiles="0"; for (my $i=1;$i<$NE;$i++){$tiles.=",$i";} - - for (my $i=0;$i<$num;$i++){ my $w1 = gen_combobox_object ($self,$sample,"SRC_$i",$tiles, $i,undef,undef); my $w2 = gen_combobox_object ($self,$sample,"DST_$i",$tiles, $i+1,undef,undef); $htable->attach ($w1 , 0, 1, $row,$row+1,'shrink','shrink',2,2); $htable->attach ($w2 , 2, 3, $row,$row+1,'shrink','shrink',2,2); $row++; - - } + } $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; - } - - if ($cast_type ne '"UNICAST"'){ my $min=$self->object_get_attribute($sample,'MCAST_PCK_SIZ_MIN'); my $max=$self->object_get_attribute($sample,'MCAST_PCK_SIZ_MAX'); $min=5 if(!defined $min); $max=5 if(!defined $max); $max= $min if($max< $min); - - my $s = ($cast_type eq '"BROADCAST_FULL"' || $cast_type eq '"BROADCAST_PARTIAL"')? "Broadcast" : "Milticast"; my $info1= "Define the percentage ratio of $s traffic towards Unicast traffic"; my $info2= "Define how destinations is selected in Multicast packets"; ($row,$coltmp)=add_param_widget ($self, "$s Node Select" , "MCAST_TRAFFIC_TYPE" , "Uniform-Random", 'Combo-box', "Uniform-Random", $info1, $table,$row,undef,1, $sample); ($row,$coltmp)=add_param_widget ($self, "$s Traffic Ratio", "MCAST_TRAFFIC_RATIO", 5 , 'Spin-button', "0,100,1" , $info2, $table,$row,undef,1, $sample); - ($row,$coltmp)=add_param_widget ($self, "$s min pck size", "MCAST_PCK_SIZ_MIN", 5 , 'Spin-button', "1,$max,1" , $info2, $table,$row,undef,1, $sample,1,'ref_set_win'); - ($row,$coltmp)=add_param_widget ($self, "$s max pck size", "MCAST_PCK_SIZ_MAX", 5 , 'Spin-button', "$min,100,1" , $info2, $table,$row,undef,1, $sample,1,'ref_set_win'); - - - } - - - - my $d= { label=>'number of message class:', param_name=>'MESSAGE_CLASS', type=>'Spin-button', default_val=>0, content=>"0,256,1", info=>"Number of packet message classes. Each message class can be configured to use specefic subset of avilable VCs", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); my $num=$self->object_get_attribute($sample,"MESSAGE_CLASS"); @@ -605,7 +492,6 @@ sub get_simulator_noc_configuration{ $htable->attach ( gen_label_in_left (" - "), 1, 2, $row,$row+1,'fill','shrink',2,2); $htable->attach ( gen_label_in_left ("Traffic(%)"), 2, 3, $row,$row+1,'fill','shrink',2,2); $row++; - for (my $i=0;$i<$num;$i++){ $htable->attach ( gen_label_in_left ("$i"), 0, 1, $row,$row+1,'fill','shrink',2,2); my $w1 = gen_spin_object ($self,$sample,"CLASS_$i","0,100,1", 100/$num,undef,undef); @@ -614,24 +500,17 @@ sub get_simulator_noc_configuration{ } $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; } - - - if ($traffic eq 'hot spot'){ my $htable=def_table(10,2,FALSE); - my $d= { label=>'number of Hot Spot nodes:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, content=>"1,256,1", info=>"Number of hot spot nodes in the network", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}; ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - my $l1=gen_label_help("Define the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node"," Hot Spot tile number \%"); my $l2=gen_label_help("If it is set as \"n\" then each node sends n % of its traffic to each hotspot node"," Hot Spot traffic \%"); my $l3=gen_label_help("If it is checked then hot spot node also sends packets to other nodes otherwise it only receives packets from other nodes"," send enable"); - $htable->attach ($l1 , 0, 1, $row,$row+1,'fill','shrink',2,2); $htable->attach ($l2 , 1, 2, $row,$row+1,'fill','shrink',2,2); $htable->attach ($l3 , 2,3, $row,$row+1,'fill','shrink',2,2); $row++; - my $num=$self->object_get_attribute($sample,"HOTSPOT_NUM"); for (my $i=0;$i<$num;$i++){ my $w1 = gen_spin_object ($self,$sample,"HOTSPOT_CORE_$i","0,256,1", $i,undef,undef); @@ -641,110 +520,74 @@ sub get_simulator_noc_configuration{ $htable->attach ($w2 ,1, 2, $row,$row+1,'fill','shrink',2,2); $htable->attach ($w3 , 2,3, $row,$row+1,'fill','shrink',2,2); $row++; - } - $table->attach ($htable , 0, 3, $row,$row+1,'shrink','shrink',2,2); $row++; - - - - - - - } my $l= "Define injection ratios. You can define individual ratios separating by comma (\',\') or define a range of injection ratios with \$min:\$max:\$step format. As an example defining 2,3,4:10:2 will result in (2,3,4,6,8,10) injection ratios." ; my $u=get_injection_ratios ($self,$sample,"ratios"); - attach_widget_to_table ($table,$row,gen_label_in_left(" Injection ratios:"),gen_button_message ($l,"icons/help.png") , $u); $row++; - $ok->signal_connect("clicked"=> sub{ #check if sof file has been selected my $s=$self->object_get_attribute($sample,"sof_file"); #check if injection ratios are valid my $r=$self->object_get_attribute($sample,"ratios"); - my $h; - my $t=$self->object_get_attribute($sample,"PCK_SIZ_SEL"); unless ($t eq 'random-range' ){ ($avg,$msg) = get_district_avg($self,$sample); if(defined $msg){ - message_dialog($msg); - return; + message_dialog($msg); + return; } - } - + } if ($traffic eq 'hot spot'){ - $h= check_hotspot_parameters($self,$sample); + $h= check_hotspot_parameters($self,$sample); } - my $v; if(defined $r ){ $v=check_inserted_ratios($r); } - if(defined $s && defined $r && defined $v && !defined $h) { #$set_win->destroy; $set_win->hide(); $self->object_add_attribute("active_setting",undef,undef); set_gui_status($self,"ref",1); } else { - if(!defined $s){ my $m= "Please select NoC verilated file"; message_dialog($m); } elsif (! defined $r) { - message_dialog("Please define valid injection ratio(s)!"); + message_dialog("Please define valid injection ratio(s)!"); } elsif (defined $h){ - message_dialog("$h"); + message_dialog("$h"); } } }); - - } - - + } if($traffictype eq "Task-graph"){ - my @custominfo = ( #{ label=>"Verilated Model", param_name=>'sof_file', type=>'Combo-box', default_val=>undef, content=>$exe_files, info=>"Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - - { label=>"Number of Files", param_name=>"TRAFFIC_FILE_NUM", type=>'Spin-button', default_val=>1, content=>"1,100,1", info=>"Select number of input files", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, - + { label=>"Number of Files", param_name=>"TRAFFIC_FILE_NUM", type=>'Spin-button', default_val=>1, content=>"1,100,1", info=>"Select number of input files", param_parent=>$sample, ref_delay=>1, new_status=>'ref_set_win'}, { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, ); - foreach my $d (@custominfo) { ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - - + } my $open_in = "$ENV{'PRONOC_WORK'}/traffic_pattern"; - - - - my $num=$self->object_get_attribute($sample,"TRAFFIC_FILE_NUM"); - for (my $i=0; $i<$num; $i++){ - attach_widget_to_table ($table,$row,gen_label_in_left("traffic pattern file $i:"),gen_button_message ("Select the traffic pattern input file. Any custom traffic based on application task graphs can be generated using ProNoC Trace Generator tool.","icons/help.png"), get_file_name_object ($self,$sample,"traffic_file$i",undef,$open_in)); $row++; - } - - - - - + my $num=$self->object_get_attribute($sample,"TRAFFIC_FILE_NUM"); + for (my $i=0; $i<$num; $i++){ + attach_widget_to_table ($table,$row,gen_label_in_left("traffic pattern file $i:"),gen_button_message ("Select the traffic pattern input file. Any custom traffic based on application task graphs can be generated using ProNoC Trace Generator tool.","icons/help.png"), get_file_name_object ($self,$sample,"traffic_file$i",undef,$open_in)); $row++; + } $ok->signal_connect("clicked"=> sub{ #check if sof file has been selected my $s=$self->object_get_attribute($sample,"sof_file"); if(!defined $s){ - message_dialog("Please select NoC verilated file"); - return; + message_dialog("Please select NoC verilated file"); + return; } - #check if traffic files have been selected for (my $i=0; $i<$num; $i++){ my $f=$self->object_get_attribute($sample,"traffic_file$i"); @@ -753,31 +596,20 @@ sub get_simulator_noc_configuration{ message_dialog($m); return; } - } #$set_win->destroy; $set_win->hide(); $self->object_add_attribute("active_setting",undef,undef); set_gui_status($self,"ref",1); - }); - - } - - if($traffictype eq "SynFull"){ #get the synful model names my $models_dir = get_project_dir()."/mpsoc/src_c/synfull/generated-models/"; my ($flist)=get_file_list_by_extention ("$models_dir",".model"); - - my $model_obj = gen_combobox_object ($self,$sample, "MODEL_NAME", $flist, undef,undef,undef); attach_widget_to_table ($table,$row,gen_label_in_left(" Traffic Model name:"),gen_button_message ("Select an application traffic model.","icons/help.png"), $model_obj); $row++; - - - my @custominfo = ( { label=>"Synful Flit-size:(Bytes)", param_name=>'SYNFUL_FLITw', type=>'Spin-button', default_val=>4, content=>"4,72,4", info=>"The synful flit size in Byte. It defines the number of flits that should be set to ProNoC for each synful packets. The ProNoC packet size is : \t Ceil( synful packet size/synful flit size). ", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, @@ -786,18 +618,11 @@ sub get_simulator_noc_configuration{ { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,$max_sim_clk,1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, { label=>"Markov Chain Random seed:", param_name=>'RND_SEED', type=>'Spin-button', default_val=>53432145, content=>"0,999999999,1", info=>"The seed valus is passe to synfull random number generator.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, { label=>"Exit at steady state:", param_name=>'EXIT_STEADY', type=>'Check-box', default_val=>0, content=>"1", info=>"Exit the simulation when it reaches to a steady state.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - - ); - - - foreach my $d (@custominfo) { ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); } - $ok->signal_connect("clicked"=> sub{ #check if sof file has been selected my $s=$self->object_get_attribute($sample,"MODEL_NAME"); @@ -805,39 +630,24 @@ sub get_simulator_noc_configuration{ message_dialog("Please select a SynFull traffic model"); return; } - - #$set_win->destroy; $set_win->hide(); $self->object_add_attribute("active_setting",undef,undef); set_gui_status($self,"ref",1); - }); - - - }#SynFull - if($traffictype eq "Netrace"){ #get the synful model names my $models_dir = "$ENV{PRONOC_WORK}/simulate/netrace"; my ($flist)=get_file_list_by_extention ("$models_dir",".bz2"); - my $model_obj = gen_combobox_object ($self,$sample, "MODEL_NAME", $flist, undef,undef,undef); my $download=def_image_button("icons/download.png",'Download'); my $box =def_hbox(FALSE, 0); $box->pack_start( $model_obj , 1,1, 0); $box->pack_start( $download, 0, 1, 3); - - attach_widget_to_table ($table,$row,gen_label_in_left(" Trace name:"),gen_button_message ("Select a netrace trace file. You can download traces using download button.","icons/help.png"), - $box); - - + attach_widget_to_table ($table,$row,gen_label_in_left(" Trace name:"),gen_button_message ("Select a netrace trace file. You can download traces using download button.","icons/help.png"), $box); $row++; - - - my @custominfo = ( { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configuration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, { label=>"Total packet number limit:", param_name=>'PCK_NUM_LIMIT', type=>'Spin-button', default_val=>200000, content=>"2,$max_pck_num,1", info=>"Simulation will stop when total number of sent packets by all nodes reaches packet number limit or total simulation clock reach its limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, @@ -847,61 +657,31 @@ sub get_simulator_noc_configuration{ which simplifies the code in the network simulator.", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, { label=>"trace file start region:", param_name=>'START_RGN', type=>'Spin-button', default_val=>0, content=>"0,10000,1", info=>undef, param_parent=>$sample, ref_delay=>undef, new_status=>undef}, { label=>"Netrace to Pronoc clk ratio:", param_name=>'SPEED_UP', type=>'Spin-button', default_val=>1, content=>"1,99,1", info=>"The ratio of netrace frequency to pronoc.The higher value results in higher injection ratio to the NoC. Default is one\n", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, - - - - - - ); - - - foreach my $d (@custominfo) { ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - $ok->signal_connect("clicked"=> sub{ #check if sof file has been selected my $s=$self->object_get_attribute($sample,"MODEL_NAME"); if(!defined $s){ - message_dialog("Please select a SynFull traffic model"); - return; + message_dialog("Please select a SynFull traffic model"); + return; } - - #$set_win->destroy; $set_win->hide(); $self->object_add_attribute("active_setting",undef,undef); set_gui_status($self,"ref",1); - }); - $download->signal_connect("clicked"=> sub{ download_netrace("$models_dir") }); - - - }#netrace - - - - - - add_widget_to_scrolled_win ($mtable,$set_win); - $set_win->show_all(); - - } - - ############ # run_simulator ########### - sub run_simulator { my ($simulate,$info)=@_; #return if(!check_samples($emulate,$info)); @@ -909,9 +689,7 @@ sub run_simulator { set_gui_status($simulate,"ref",1); show_info($info, "Start Simulation\n"); my $name=$simulate->object_get_attribute ("simulate_name",undef); - #unlink $log; # remove old log file - my @samples =$simulate->object_get_attribute_order("samples"); foreach my $sample (@samples){ my $status=$simulate->object_get_attribute ($sample,"status"); @@ -921,20 +699,16 @@ sub run_simulator { if($traffictype eq "Synthetic") {run_synthetic_simulation($simulate,$info,$sample,$name);} elsif($traffictype eq "Task-graph"){run_task_simulation($simulate,$info,$sample,$name) ;} else {run_trace_simulation($simulate,$info,$sample,$name);} - } - add_info($info, "Simulation is done!\n"); printf "Simulation is done!\n"; $simulate->object_add_attribute('status',undef,'ideal'); set_gui_status($simulate,"ref",1); -} +} sub run_synthetic_simulation { my ($simulate,$info,$sample,$name)=@_; - - my %traffic= ( 'tornado' => 'TORNADO', 'transposed 1' => "TRANSPOSE1", @@ -946,7 +720,7 @@ sub run_synthetic_simulation { 'shuffle' => "SHUFFLE", 'bit rotation' => "BIT_ROTATE", 'neighbor' => "NEIGHBOR", - 'custom' => "CUSTOM" + 'custom' => "CUSTOM" ); my $simulator =$simulate->object_get_attribute("Simulator"); @@ -956,15 +730,12 @@ sub run_synthetic_simulation { my @ratios=@{check_inserted_ratios($r)}; #$emulate->object_add_attribute ("sample$i","status","run"); my $bin=get_sim_bin_path($simulate,$sample,$info); - #load traffic configuration my $patern=$simulate->object_get_attribute ($sample,'traffic'); my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); my $MIN_PCK_SIZE=$simulate->object_get_attribute ($sample,"MIN_PCK_SIZE"); my $MAX_PCK_SIZE=$simulate->object_get_attribute ($sample,"MAX_PCK_SIZE"); - - #hotspot my $custom=""; my $custom_sv=""; @@ -976,13 +747,10 @@ sub run_synthetic_simulation { for (my $i=0;$i<$num; $i++){ my $src = $simulate->object_get_attribute($sample,"SRC_$i"); my $dst = $simulate->object_get_attribute($sample,"DST_$i"); - $custom.=($i==0)? "-H \"$src,$dst" : ",$src,$dst"; - } my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($simulate,$sample); my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - for (my $i=0;$i<$NE; $i++){ my ($src,$dst) = custom_traffic_dest ($simulate,$sample,$i); $custom_sv.="\tassign custom_traffic_t[$src]=$dst;\n"; @@ -990,11 +758,10 @@ sub run_synthetic_simulation { $custom_sv.=($dst==-1)? "1'b0;//off \n" : "1'b1;\n" } $custom.="\""; - } else{ $custom_sv.="localparam CUSTOM_NODE_NUM=0;\n\twire [NEw-1 : 0] custom_traffic_t [NE-1 : 0];\n\twire [NE-1 : 0] custom_traffic_en; - "; + "; } #multicast my $mcast=""; @@ -1006,7 +773,6 @@ sub run_synthetic_simulation { my $mr = $simulate->object_get_attribute ($sample, "MCAST_TRAFFIC_RATIO"); my $mmax = $simulate->object_get_attribute ($sample, "MCAST_PCK_SIZ_MAX"); my $mmin = $simulate->object_get_attribute ($sample, "MCAST_PCK_SIZ_MIN"); - $mcast = "-u \"$mr,$mmin,$mmax\""; $mcast_sv.= "localparam MCAST_TRAFFIC_RATIO = $mr;\n"; $mcast_sv.= "localparam MCAST_PCK_SIZ_MAX = $mmax;\n"; @@ -1016,20 +782,13 @@ sub run_synthetic_simulation { $mcast_sv.= "localparam MCAST_PCK_SIZ_MAX = 0;\n"; $mcast_sv.= "localparam MCAST_PCK_SIZ_MIN = 0;\n"; } - - - - - my $classes; my $num=$simulate->object_get_attribute($sample,"MESSAGE_CLASS"); $classes.="-p 100" if($num==0); for (my $i=0;$i<$num;$i++){ my $w1 = $simulate->object_get_attribute($sample,"CLASS_$i"); $classes.= ($i==0)? "-p $w1" : ",$w1" ; - } - my $discrete_sv=""; my $hotspot=""; my $hotspot_sv=""; @@ -1038,10 +797,8 @@ sub run_synthetic_simulation { my $num=$simulate->object_get_attribute($sample,"HOTSPOT_NUM"); if (defined $num){ $hotspot.=" $num"; - $hotspot_sv.="localparam HOTSPOT_NODE_NUM=$num;\n\thotspot_t hotspot_info [HOTSPOT_NODE_NUM-1 : 0];\n"; my $acum=0; - for (my $i=0;$i<$num;$i++){ my $w1 = $simulate->object_get_attribute($sample,"HOTSPOT_CORE_$i"); my $w2 = $simulate->object_get_attribute($sample,"HOTSPOT_PERCENT_$i"); @@ -1049,28 +806,21 @@ sub run_synthetic_simulation { my $w3 = $simulate->object_get_attribute($sample,"HOTSPOT_SEND_EN_$i"); $hotspot.=",$w1,$w3,$w2"; $acum+=$w2; - $hotspot_sv.=" assign hotspot_info[$i].ip_num=$w1; assign hotspot_info[$i].send_enable=$w3; - assign hotspot_info[$i].percentage=$acum; // $w2 -"; } - + assign hotspot_info[$i].percentage=$acum; // $w2\n"; + } } - $hotspot.=" \""; - } else{ $hotspot_sv.="localparam HOTSPOT_NODE_NUM = 0;\n\thotspot_t hotspot_info [0:0];\n" } - my $pck_size; my $t=$simulate->object_get_attribute($sample,"PCK_SIZ_SEL"); if($t eq 'random-range' ){ - $pck_size = "-m \"R,$MIN_PCK_SIZE,$MAX_PCK_SIZE\""; $discrete_sv="\t localparam DISCRETE_PCK_SIZ_NUM=1; \t rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1:0];\n"; - }else{ my $vt=$simulate->object_get_attribute($sample,"DISCRETE_RANGE"); my $pt=$simulate->object_get_attribute($sample,"PROBEB_RANGE"); @@ -1088,19 +838,12 @@ sub run_synthetic_simulation { $discrete_sv="\t localparam DISCRETE_PCK_SIZ_NUM=$i; \t rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1: 0];\n".$discrete_sv; } - my $modelsim_bin= $ENV{MODELSIM_BIN}; my $vsim = (! defined $modelsim_bin)? "vsim" : "$modelsim_bin/vsim"; - - - - my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); $cpu_num = 1 if (!defined $cpu_num); - my $thread_num = $simulate->object_get_attribute('compile', 'thread_num'); $thread_num = 1 if (!defined $thread_num); - if ($simulator ne 'Verilator'){ for (my $i=0; $i<$cpu_num; $i++ ){ my $out="$out_path/modelsim/work$i"; @@ -1134,13 +877,10 @@ sub run_synthetic_simulation { `endif "; save_file("$out/sim_param.sv",$param); - - #Get the list of all verilog files in src_verilog folder my @files = File::Find::Rule->file() ->name( '*.v','*.V','*.sv' ) ->in( "$out_path/modelsim/src_verilog" ); - #get list of all verilog files in src_sim folder my @sim_files = File::Find::Rule->file() ->name( '*.v','*.V','*.sv' ) @@ -1151,7 +891,6 @@ sub run_synthetic_simulation { save_file("$out/file_list.f", "$tt"); my $tcl="#!/usr/bin/tclsh - transcript on if {[file exists rtl_work]} { vdel -lib rtl_work -all @@ -1170,9 +909,7 @@ sub run_synthetic_simulation { run -all quit "; - save_file ("$out/model.tcl",$tcl); - my $cmd="cd $out; rm -Rf rtl_work; $vsim -do $out/model.tcl "; save_file ("$out/run.sh",'#!/bin/bash'." sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=\$1/\" $out/sim_param.sv @@ -1180,85 +917,62 @@ sub run_synthetic_simulation { add_info($info, "model.tcl is created in $out\n"); }#for } - - - my @paralel_ratio; my $total=scalar @ratios; my $jobs=0; my $c=0; my $cmds=""; - - foreach my $ratio_in (@ratios){ - #my $r= $ratio_in * MAX_RATIO/100; - my $cmd; - - if ($simulator eq 'Modelsim'){ - add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); - my $out="$out_path/modelsim/work$c"; - $cmd=" xterm -e bash -c ' cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -c -do $out/model.tcl -l $out_path/sim_out$ratio_in;' &\n "; - - }elsif ($simulator eq 'Modelsim gui'){ - add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); - my $out="$out_path/modelsim/work$c"; - $cmd="cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -do $out/model.tcl -l $out_path/sim_out$ratio_in; "; - - }else{ - add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); - $cmd="$bin -t \"$patern\" $pck_size -T $thread_num -n $PCK_NUM_LIMIT -c $SIM_CLOCK_LIMIT -i $ratio_in $classes $hotspot $custom $mcast > $out_path/sim_out$ratio_in & "; - - } - $cmds .=$cmd; - add_info($info, "$cmd \n"); - - my $time_strg = localtime; - #append_text_to_file($log,"started at:$time_strg\n"); #save simulation output - $jobs++; - - push (@paralel_ratio,$ratio_in); - $c++; - if($jobs % $cpu_num ==0 || $jobs == $total){ - - #run paralle simulation - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmds\n wait\n"); - if($exit || (length $stderr >4)){ - add_colored_info($info, "Error in running simulation: $stderr \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - #save results - for (my $i=0; $i<$c; $i++){ - my $r = $paralel_ratio[$i]; - - my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); - if (scalar @errors ){ - add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); - $simulate->object_add_attribute ($sample,"status","failed"); - $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - - - my $stdout = load_file("$out_path/sim_out$r"); - - extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); - + #my $r= $ratio_in * MAX_RATIO/100; + my $cmd; + if ($simulator eq 'Modelsim'){ + add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); + my $out="$out_path/modelsim/work$c"; + $cmd=" xterm -e bash -c ' cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -c -do $out/model.tcl -l $out_path/sim_out$ratio_in;' &\n "; + }elsif ($simulator eq 'Modelsim gui'){ + add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); + my $out="$out_path/modelsim/work$c"; + $cmd="cd $out; sed -i \"s/ INJRATIO=\[\[:digit:\]\]\\+/ INJRATIO=$ratio_in/\" $out/sim_param.sv; rm -Rf rtl_work; $vsim -do $out/model.tcl -l $out_path/sim_out$ratio_in; "; + }else{ + add_info($info, "Run $bin with injection ratio of $ratio_in \% \n"); + $cmd="$bin -t \"$patern\" $pck_size -T $thread_num -n $PCK_NUM_LIMIT -c $SIM_CLOCK_LIMIT -i $ratio_in $classes $hotspot $custom $mcast > $out_path/sim_out$ratio_in & "; + } + $cmds .=$cmd; + add_info($info, "$cmd \n"); + my $time_strg = localtime; + #append_text_to_file($log,"started at:$time_strg\n"); #save simulation output + $jobs++; + push (@paralel_ratio,$ratio_in); + $c++; + if($jobs % $cpu_num ==0 || $jobs == $total){ + #run paralle simulation + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmds\n wait\n"); + if($exit || (length $stderr >4)){ + add_colored_info($info, "Error in running simulation: $stderr \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; } - - $cmds=""; - @paralel_ratio=(); - $c=0; - - set_gui_status($simulate,"ref",2); - } - - }#@ratios - - $simulate->object_add_attribute ($sample,"status","done"); - + #save results + for (my $i=0; $i<$c; $i++){ + my $r = $paralel_ratio[$i]; + my @errors = unix_grep("$out_path/sim_out$r","ERROR:"); + if (scalar @errors ){ + add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); + $simulate->object_add_attribute ($sample,"status","failed"); + $simulate->object_add_attribute('status',undef,'ideal'); + return; + } + my $stdout = load_file("$out_path/sim_out$r"); + extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); + } + $cmds=""; + @paralel_ratio=(); + $c=0; + set_gui_status($simulate,"ref",2); + } + }#@ratios + $simulate->object_add_attribute ($sample,"status","done"); } sub extract_st_by_name{ @@ -1300,11 +1014,10 @@ sub extract_st_by_name{ } #print Dumper(\%statistcs); - return %statistcs; + return %statistcs; } - sub extract_and_update_noc_sim_statistic { my ($simulate,$sample,$ratio_in,$stdout)=@_; my $total_time =capture_number_after("Simulation clock cycles:",$stdout); @@ -1328,14 +1041,11 @@ sub extract_and_update_noc_sim_statistic { update_result($simulate,$sample,"worst_delay_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.worst_latency'}); update_result($simulate,$sample,"flit_rsvd_result",$ratio_in,$p,$statistcs{$p}{'rsvd_stat.flit_num'}); update_result($simulate,$sample,"flit_sent_result",$ratio_in,$p,$statistcs{$p}{'sent_stat.flit_num'}); - } - + } my %st1 = extract_st_by_name("Endp_to_Endp flit_num:",$stdout); update_result($simulate,$sample,"endp-endp-flit_result",$ratio_in,\%st1); - my %st2 = extract_st_by_name("Endp_to_Endp pck_num:",$stdout); update_result($simulate,$sample,"endp-endp-pck_result",$ratio_in,\%st2); - my %st3 = extract_st_by_name("Routers Statistics:",$stdout); foreach my $p (sort keys %st3){ update_result($simulate,$sample,"flit_per_router_result",$ratio_in,$p,$st3{$p}{'flit_in'}); @@ -1345,13 +1055,10 @@ sub extract_and_update_noc_sim_statistic { update_result($simulate,$sample,"flit_buffered_router_ratio",$ratio_in,$p,$tmp); $tmp= ($st3{$p}{'flit_in'}==0)? 0 : ($st3{$p}{'flit_in_bypassed'}*100) / $st3{$p}{'flit_in'}; update_result($simulate,$sample,"flit_bypass_router_ratio",$ratio_in,$p,$tmp); - } - #my $p= $simulate->object_get_attribute ($sample,"noc_info"); # my $TOPOLOGY=$p->{"TOPOLOGY"}; #print "$TOPOLOGY\n"; - } @@ -1359,24 +1066,19 @@ sub run_task_simulation{ my ($simulate,$info,$sample,$name)=@_; my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); - my $bin=get_sim_bin_path($simulate,$sample,$info); - my $dir = Cwd::getcwd(); my $project_dir = abs_path("$dir/../.."); #mpsoc directory address $bin= "$project_dir/$bin" if(!(-f $bin)); my $num=$simulate->object_get_attribute($sample,"TRAFFIC_FILE_NUM"); - my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); $cpu_num = 1 if (!defined $cpu_num); - my @paralel_ratio; my $total=$num; my $jobs=0; my $c=0; my $cmds=""; my $out_path ="$ENV{PRONOC_WORK}/simulate/"; - for (my $i=0; $i<$num; $i++){ my $f=$simulate->object_get_attribute($sample,"traffic_file$i"); add_info($info, "Run $bin for $f file \n"); @@ -1396,7 +1098,6 @@ sub run_task_simulation{ $simulate->object_add_attribute('status',undef,'ideal'); return; } - #save results for (my $j=0; $j<$c; $j++){ my $r = $paralel_ratio[$j]; @@ -1406,54 +1107,36 @@ sub run_task_simulation{ add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); $simulate->object_add_attribute ($sample,"status","failed"); $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - + return; + } extract_and_update_noc_sim_statistic ($simulate,$sample,$r,$stdout); } - $cmds=""; @paralel_ratio=(); $c=0; set_gui_status($simulate,"ref",2); - } - + } }#for i - $simulate->object_add_attribute ($sample,"status","done"); -} - - - +} sub run_trace_simulation{ my ($simulate,$info,$sample,$name)=@_; my $log= (defined $name)? "$ENV{PRONOC_WORK}/simulate/$name.log": "$ENV{PRONOC_WORK}/simulate/sim.log"; - - my $bin=get_sim_bin_path($simulate,$sample,$info); - - - my $project_dir = get_project_dir(); + my $project_dir = get_project_dir(); $bin= "$project_dir/$bin" if(!(-f $bin)); - - my $cpu_num = $simulate->object_get_attribute('compile', 'cpu_num'); $cpu_num = 1 if (!defined $cpu_num); - my @paralel_ratio; - my $jobs=0; my $c=0; my $cmds=""; my $out_path ="$ENV{PRONOC_WORK}/simulate/"; my $thread_num = $simulate->object_get_attribute('compile', 'thread_num'); $thread_num = 1 if (!defined $thread_num); - my $model= $simulate->object_get_attribute($sample,'MODEL_NAME'); - add_info($info, "Run $bin for $model model \n"); - my $cmd="$bin -T $thread_num "; my $traffictype=$simulate->object_get_attribute($sample,"TRAFFIC_TYPE"); if($traffictype eq "Netrace"){ @@ -1462,35 +1145,22 @@ sub run_trace_simulation{ my $READER_THRL=$simulate->object_get_attribute ($sample,"READER_THRL"); my $START_RGN=$simulate->object_get_attribute ($sample,"START_RGN"); my $SPEED_UP=$simulate->object_get_attribute ($sample,"SPEED_UP"); - my $models_dir = "$ENV{PRONOC_WORK}/simulate/netrace"; - $cmd .="-F $models_dir/$model.bz2 -n $PCK_NUM_LIMIT -r $START_RGN -v 0 -s $SPEED_UP"; $cmd .=" -l " if ($READER_THRL eq "1\'b1" ); $cmd .=" -d " if ($IGNORE_DPNDCY eq "1\'b1"); - - - - - }else{#synful my $SIM_CLOCK_LIMIT=$simulate->object_get_attribute ($sample,"SIM_CLOCK_LIMIT"); my $PCK_NUM_LIMIT=$simulate->object_get_attribute ($sample,"PCK_NUM_LIMIT"); my $RND_SEED=$simulate->object_get_attribute ($sample,"RND_SEED"); my $EXIT_STEADY=$simulate->object_get_attribute ($sample,"EXIT_STEADY"); my $FLITw=$simulate->object_get_attribute ($sample,"SYNFUL_FLITw"); - - my $models_dir = get_project_dir()."/mpsoc/src_c/synfull/generated-models/"; $cmd .=" -S $models_dir/$model.model -n $PCK_NUM_LIMIT -r $RND_SEED -c $SIM_CLOCK_LIMIT -v 0 -w $FLITw"; $cmd .=" -s " if ($EXIT_STEADY eq "1\'b1"); - - - } $cmd .=" > $out_path/sim_out"; add_info($info, "$cmd \n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("$cmd\n wait\n"); if($exit || (length $stderr >4)){ add_colored_info($info, "Error in running simulation: $stderr \n",'red'); @@ -1505,25 +1175,17 @@ sub run_trace_simulation{ add_colored_info($info, "Error in running simulation:\n @errors \n",'red'); $simulate->object_add_attribute ($sample,"status","failed"); $simulate->object_add_attribute('status',undef,'ideal'); - return; - } - + return; + } extract_and_update_noc_sim_statistic ($simulate,$sample,0,$stdout); - - set_gui_status($simulate,"ref",2); - - $simulate->object_add_attribute ($sample,"status","done"); -} - - +} ########## # check_sample ########## - sub get_sim_bin_path { my ($self,$sample,$info)=@_; my $bin_path=$self->object_get_attribute ($sample,"sof_path"); @@ -1544,7 +1206,6 @@ sub check_sim_sample{ my ($self,$sample,$info)=@_; my $status=1; my $sof=get_sim_bin_path($self,$sample,$info); - # ckeck if sample have sof file if(!defined $sof){ add_colored_info($info, "Error: bin file has not set for $sample!\n",'red'); @@ -1560,20 +1221,15 @@ sub check_sim_sample{ $status=0; }else { #add info my $pp= do $sof_info ; - my $p=$pp->{'noc_param'}; - $status=0 if $@; message_dialog("Error reading: $@") if $@; if ($status==1){ $self->object_add_attribute ($sample,"noc_info",$p) ; - - - } - } + } + } } #check if sample min packet size matches in simulation - my $p= $self->object_get_attribute ($sample,"noc_info"); my $HW_MIN_PCK_SIZE=$p->{"MIN_PCK_SIZE"}; my $HW_PCK_TYPE=$p->{"PCK_TYPE"}; @@ -1592,216 +1248,122 @@ sub check_sim_sample{ if( $HW_PCK_TYPE eq '"SINGLE_FLIT"' && $SIM_MAX_PCK_SIZE !=1){ #print "$HW_PCK_TYPE \n"; add_colored_info($info, "Error: The maximum packet size is set as $SIM_MAX_PCK_SIZE however, the selected NoC model only support single-flit packet injection! Please redefine it to one\n",'red'); - $self->object_add_attribute ($sample,"status","failed"); $status=0; } - return $status; } sub noc_sim_ctrl{ my ($simulate,$info)=@_; - my $generate = def_image_button('icons/forward.png','R_un all',FALSE,1); - my $open = def_image_button('icons/browse.png',"_Load",FALSE,1); - my $save = def_image_button('icons/save.png','Sav_e',FALSE,1); + my ($entrybox,$entry ) =gen_save_load_widget ( + $simulate, #the object + "Name",#the label shown for setting configuration + "simulate_name",#the key name for saveing the setting configuration in object + "Experiment name",#the label full name show in tool tips + undef,#Where the generted RTL files are loacted. Undef if not aplicaple + 0,#check the given name match the SoC or mpsoc name rules + "lib/simulate",#where the current configuration seting file is saved + "SIM",#the extenstion given for configuration seting file + \&load_simulation, + $info); my $save_all_results = def_image_button('icons/copy.png',"E_xtract all results",FALSE,1); my $cpus=select_parallel_process_num($simulate); - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - my $compiler =def_pack_hbox('FALSE',0, gen_label_in_center('Simulator:'), gen_combobox_object($simulate,'Simulator',undef,"Modelsim gui,Modelsim,Verilator","Verilator",'ref',1)); - - - my $entry = gen_entry_object($simulate,'simulate_name',undef,undef,undef,undef); - my $entrybox=gen_label_info(" Save as:",$entry); - $entrybox->pack_start( $save, FALSE, FALSE, 0); - my $simulator =$simulate->object_get_attribute("Simulator"); - - my $thread=select_parallel_thread_num($simulate); - - my $table = def_table (1, 12, FALSE); - $table->attach ($open, 0, 1, 0,1,'expand','shrink',2,2); $table->attach ($compiler, 1, 2, 0,1,'expand','shrink',2,2); - - $table->attach ($cpus, 2, 4, 0,1,'expand','shrink',2,2); + $table->attach ($cpus, 2, 4, 0,1,'expand','shrink',2,2); if($simulator eq "Verilator"){ - $table->attach ($thread, 4, 5, 0,1,'expand','shrink',2,2); + $table->attach ($thread, 4, 5, 0,1,'expand','shrink',2,2); } - $table->attach ($entrybox, 5, 7, 0,1,'expand','shrink',2,2); $table->attach ($save_all_results, 7, 8, 0,1,'shrink','shrink',2,2); $table->attach ($generate, 8, 9, 0,1,'expand','shrink',2,2); - $generate-> signal_connect("clicked" => sub{ - my @samples =$simulate->object_get_attribute_order("samples"); + my @samples =$simulate->object_get_attribute_order("samples"); foreach my $sample (@samples){ - $simulate->object_add_attribute ("$sample","status","run"); + $simulate->object_add_attribute ("$sample","status","run"); } run_simulator($simulate,$info); - #set_gui_status($emulate,"ideal",2); - }); - -# $wb-> signal_connect("clicked" => sub{ -# wb_address_setting($mpsoc); -# -# }); - - $open-> signal_connect("clicked" => sub{ - - load_simulation($simulate,$info); - #print Dumper($simulate); - set_gui_status($simulate,"ref",5); - - }); - - $save-> signal_connect("clicked" => sub{ - save_simulation($simulate); - set_gui_status($simulate,"ref",5); - - - }); - $save_all_results-> signal_connect("clicked" => sub{ #Get the path where to save all the simulation results my $open_in = $simulate->object_get_attribute ('sim_param','BIN_DIR'); - get_dir_name($simulate,"Select the target directory","sim_param","ALL_RESULT_DIR",$open_in,'ref',1); + get_dir_name($simulate,"Select the target directory","sim_param","ALL_RESULT_DIR",$open_in,'ref',1); $simulate->object_add_attribute ("graph_save","save_all_result",1); - - }); - - + }); return add_widget_to_scrolled_win($table,gen_scr_win_with_adjst($simulate,"ctrl_sc_win")); - } - ############ # main ############ sub simulator_main{ - add_color_to_gd(); my $simulate= emulator->emulator_new(); set_gui_status($simulate,"ideal",0); - - my $main_table = def_table (25, 12, FALSE); $main_table->show_all; my ($infobox,$info)= create_txview(); - - - -my @pages =( - {page_name=>" Average/Total ", page_num=>0}, - {page_name=>" Per node ", page_num=>1}, - #{page_name=>" Worst-Case Delay ",page_num=>2}, - #{page_name=>" Execution Time ",page_num=>3}, - {page_name=>" Heat-Map. ",page_num=>4}, -); - - - -my @charts = ( - { type=>"2D_line", page_num=>0, graph_name=> "Avg. packet Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Packet Latency (clock)', Z_Title=>undef, Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency", result_name => "latency_flit_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency (clock)', Z_Title=>undef, Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency per hop", result_name => "latency_perhop_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency per hop (clock)', Z_Title=>undef, Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Avg. throughput", result_name => "throughput_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Throughput (flits/clock (%))', Z_Title=>undef,Y_Max=>100}, - { type=>"2D_line", page_num=>0, graph_name=> "Avg. SD latency", result_name => "sd_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Latency Standard Deviation (clock)', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Worst pck latency (clk)", result_name => "worst_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Worst Packet Latency (clock)', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Min pck latency (clk)", result_name => "min_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Minimum Packet Latency (clock)', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Total injected pck", result_name =>"injected_pck_total" , X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected packets', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Total injected flit",result_name =>"injected_flit_total", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected Fslits', Z_Title=>undef}, - { type=>"2D_line", page_num=>0, graph_name=> "Execuation Cycles", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Simulation Time (clk)', Z_Title=>undef}, - - - - { type=>"3D_bar", page_num=>1, graph_name=> "Received packets per Endp", result_name => "packet_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Packets Per Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Sent packets per Endp", result_name => "packet_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Per Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Received flits per Endp", result_name => "flit_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Flits Per Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Sent flits per Endp", result_name => "flit_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Flits Endpoint', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Flits per Router", result_name => "flit_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Flits Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Packets per Router", result_name => "packet_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Worst Received pck latency per Endp", result_name => "worst_delay_rsvd_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Worst Sent pck latency per Endp", result_name => "worst_delay_sent_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, - - { type=>"3D_bar", page_num=>1, graph_name=> "Buffered Flit in Ratio Per Router", result_name => "flit_buffered_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in buffered in router/Flit in (%)', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "Bypassed Flit in Ratio Per Router", result_name => "flit_bypass_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in bypassed in router/Flit in (%)', Z_Title=>undef}, - - - - - - - - - - - - - { type=>"Heat-map", page_num=>4, graph_name=> "Select", result_name => "undef",X_Title=>'-' , Y_Title=> undef, Z_Title=>undef}, - { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Flit-num", result_name => "endp-endp-flit_result",X_Title=>'total flit number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, - { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Packet-num", result_name => "endp-endp-pck_result",X_Title=>'total packet number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, - - + my @pages =( + {page_name=>" Average/Total ", page_num=>0}, + {page_name=>" Per node ", page_num=>1}, + #{page_name=>" Worst-Case Delay ",page_num=>2}, + #{page_name=>" Execution Time ",page_num=>3}, + {page_name=>" Heat-Map. ",page_num=>4}, + ); + my @charts = ( + { type=>"2D_line", page_num=>0, graph_name=> "Avg. packet Latency", result_name => "latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Packet Latency (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency", result_name => "latency_flit_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Avg. flit Latency per hop", result_name => "latency_perhop_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Flit Latency per hop (clock)', Z_Title=>undef, Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Avg. throughput", result_name => "throughput_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Avg. Throughput (flits/clock (%))', Z_Title=>undef,Y_Max=>100}, + { type=>"2D_line", page_num=>0, graph_name=> "Avg. SD latency", result_name => "sd_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Latency Standard Deviation (clock)', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Worst pck latency (clk)", result_name => "worst_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Worst Packet Latency (clock)', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Min pck latency (clk)", result_name => "min_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Minimum Packet Latency (clock)', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Total injected pck", result_name =>"injected_pck_total" , X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected packets', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Total injected flit",result_name =>"injected_flit_total", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Total Injected Fslits', Z_Title=>undef}, + { type=>"2D_line", page_num=>0, graph_name=> "Execuation Cycles", result_name => "exe_time_result",X_Title=>'Desired Avg. Injected Load Per Router (flits/clock (%))' , Y_Title=>'Total Simulation Time (clk)', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Received packets per Endp", result_name => "packet_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Packets Per Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Sent packets per Endp", result_name => "packet_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Per Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Received flits per Endp", result_name => "flit_rsvd_result", X_Title=>'Endpoint ID' , Y_Title=>'Received Flits Per Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Sent flits per Endp", result_name => "flit_sent_result", X_Title=>'Endpoint ID' , Y_Title=>'Sent Packets Flits Endpoint', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Flits per Router", result_name => "flit_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Flits Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Packets per Router", result_name => "packet_per_router_result", X_Title=>'Router ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Worst Received pck latency per Endp", result_name => "worst_delay_rsvd_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Worst Sent pck latency per Endp", result_name => "worst_delay_sent_result",X_Title=>'Endpoint ID' , Y_Title=>'Worst-Case Delay (clk)', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Buffered Flit in Ratio Per Router", result_name => "flit_buffered_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in buffered in router/Flit in (%)', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "Bypassed Flit in Ratio Per Router", result_name => "flit_bypass_router_ratio",X_Title=>'Router ID' , Y_Title=>'Flit in bypassed in router/Flit in (%)', Z_Title=>undef}, + { type=>"Heat-map", page_num=>4, graph_name=> "Select", result_name => "undef",X_Title=>'-' , Y_Title=> undef, Z_Title=>undef}, + { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Flit-num", result_name => "endp-endp-flit_result",X_Title=>'total flit number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, + { type=>"Heat-map", page_num=>4, graph_name=> "Endp-2-Endp Packet-num", result_name => "endp-endp-pck_result",X_Title=>'total packet number sent from an endpoint to another' , Y_Title=> undef, Z_Title=>undef}, ); - - my ($conf_box,$set_win)=process_notebook_gen($simulate,$info,"simulate",undef,@charts); my $chart =gen_multiple_charts ($simulate,\@pages,\@charts,0.4); - - - $main_table->set_row_spacings (4); $main_table->set_col_spacings (1); - - - #my $device_win=show_active_dev($soc,$soc,$infc,$soc_state,\$refresh,$info); - - - - my $image = get_status_gif($simulate); my $ctrl = noc_sim_ctrl ($simulate,$info); - my $v1=gen_vpaned($conf_box,.45,$image); my $v2=gen_vpaned($infobox,.2,$chart); my $h1=gen_hpaned($v1,.4,$v2); - - - $main_table->attach_defaults ($h1 , 0, 12, 0,24); $main_table->attach ($ctrl, 0,12, 24,25,'fill','fill',2,2); - my $sc_win=add_widget_to_scrolled_win($main_table); - - #check soc status every 0.5 second. refresh device table if there is any changes Glib::Timeout->add (100, sub{ - my ($state,$timeout)= get_gui_status($simulate); - if ($timeout>0){ $timeout--; set_gui_status($simulate,$state,$timeout); return TRUE; - } if($state eq "ideal"){ return TRUE; - } - - - - #refresh GUI - - - $ctrl->destroy(); + $ctrl->destroy(); $conf_box->destroy(); $chart->destroy(); $image->destroy(); @@ -1810,43 +1372,26 @@ sub simulator_main{ $chart = gen_multiple_charts ($simulate,\@pages,\@charts,0.4); $ctrl = noc_sim_ctrl ($simulate,$info); $main_table->attach ($ctrl,0, 12, 24,25,'fill','fill',2,2); - $v1 -> pack1($conf_box, TRUE, TRUE); - $v1 -> pack2($image, TRUE, TRUE); - $v2 -> pack2($chart, TRUE, TRUE); - - - - + $v1 -> pack1($conf_box, TRUE, TRUE); + $v1 -> pack2($image, TRUE, TRUE); + $v2 -> pack2($chart, TRUE, TRUE); $conf_box->show_all(); - $main_table->show_all(); + $main_table->show_all(); set_gui_status($simulate,"ideal",0); - - return TRUE; - } ); - - - - - - return $sc_win; - - - } sub custom_traffic_dest{ my ($self,$sample,$core_num) =@_; - my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); for (my $i=0;$i<$num;$i++){ my $src = $self->object_get_attribute($sample,"SRC_$i"); my $dst = $self->object_get_attribute($sample,"DST_$i"); return ($core_num,$dst) if($src == $core_num); } - return ($core_num, -1);#off + return ($core_num, -1);#off } sub download_netrace{ @@ -1858,56 +1403,44 @@ sub download_netrace{ my $window = def_popwin_size(30,85,"Netrace download",'percent'); my $table = def_table(1, 1, FALSE); my $scrolled_win = add_widget_to_scrolled_win($table); - - -my @links =( -{ label=>"blackscholes simlarge (907M) ",name=>"blackscholes_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simlarge.tra.bz2"}, -{ label=>"blackscholes simmedium (182M)",name=>"blackscholes_64c_simmedium.tra.bz2",url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simmedium.tra.bz2"}, -{ label=>"blackscholes simsmall (55M) ",name=>"blackscholes_64c_simsmall.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simsmall.tra.bz2"}, -{ label=>"bodytrack simlarge (3.5G) ",name=>"bodytrack_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/bodytrack_64c_simlarge.tra.bz2"}, -{ label=>"canneal simmedium (3.5G) ",name=>"canneal_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/canneal_64c_simmedium.tra.bz2"}, -{ label=>"dedup simmedium (4.1G) ",name=>"dedup_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/dedup_64c_simmedium.tra.bz2"}, -{ label=>"ferret simmedium (2.7G) ",name=>"ferret_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/ferret_64c_simmedium.tra.bz2"}, -{ label=>"fluidanimate simlarge (1.8G) ",name=>"fluidanimate_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/fluidanimate_64c_simlarge.tra.bz2"}, -{ label=>"fluidanimate simmedium (677M)",name=>"fluidanimate_64c_simmedium.tra.bz2",url=>"https://www.cs.utexas.edu/~netrace/download/fluidanimate_64c_simmedium.tra.bz2"}, -{ label=>"fluidanimate simsmall (317M) ",name=>"fluidanimate_64c_simsmall.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/fluidanimate_64c_simsmall.tra.bz2"}, -{ label=>"swaptions simlarge (3.0G) ",name=>"swaptions_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/swaptions_64c_simlarge.tra.bz2"}, -{ label=>"vips simmedium (3.1G) ",name=>"vips_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/vips_64c_simmedium.tra.bz2"}, -{ label=>"x264 simmedium (5.1G) ",name=>"x264_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/x264_64c_simmedium.tra.bz2"}, -{ label=>"x264 simsmall (1.2G) ",name=>"x264_64c_simsmall.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/x264_64c_simsmall.tra.bz2"}, -); - + my @links =( + { label=>"blackscholes simlarge (907M) ",name=>"blackscholes_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simlarge.tra.bz2"}, + { label=>"blackscholes simmedium (182M)",name=>"blackscholes_64c_simmedium.tra.bz2",url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simmedium.tra.bz2"}, + { label=>"blackscholes simsmall (55M) ",name=>"blackscholes_64c_simsmall.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/blackscholes_64c_simsmall.tra.bz2"}, + { label=>"bodytrack simlarge (3.5G) ",name=>"bodytrack_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/bodytrack_64c_simlarge.tra.bz2"}, + { label=>"canneal simmedium (3.5G) ",name=>"canneal_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/canneal_64c_simmedium.tra.bz2"}, + { label=>"dedup simmedium (4.1G) ",name=>"dedup_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/dedup_64c_simmedium.tra.bz2"}, + { label=>"ferret simmedium (2.7G) ",name=>"ferret_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/ferret_64c_simmedium.tra.bz2"}, + { label=>"fluidanimate simlarge (1.8G) ",name=>"fluidanimate_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/fluidanimate_64c_simlarge.tra.bz2"}, + { label=>"fluidanimate simmedium (677M)",name=>"fluidanimate_64c_simmedium.tra.bz2",url=>"https://www.cs.utexas.edu/~netrace/download/fluidanimate_64c_simmedium.tra.bz2"}, + { label=>"fluidanimate simsmall (317M) ",name=>"fluidanimate_64c_simsmall.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/fluidanimate_64c_simsmall.tra.bz2"}, + { label=>"swaptions simlarge (3.0G) ",name=>"swaptions_64c_simlarge.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/swaptions_64c_simlarge.tra.bz2"}, + { label=>"vips simmedium (3.1G) ",name=>"vips_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/vips_64c_simmedium.tra.bz2"}, + { label=>"x264 simmedium (5.1G) ",name=>"x264_64c_simmedium.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/x264_64c_simmedium.tra.bz2"}, + { label=>"x264 simsmall (1.2G) ",name=>"x264_64c_simsmall.tra.bz2" ,url=>"https://www.cs.utexas.edu/~netrace/download/x264_64c_simsmall.tra.bz2"}, + ); my $row=0; - - foreach my $d (@links){ my $srow=$row; $table-> attach (gen_label_in_left($d->{label}) , 0, 1, $row,$row+1,'expand','shrink',2,2); my $file="$path/$d->{name}"; if (-f $file){ - }else{ my $download=def_image_button("icons/download.png",'Download'); $table-> attach ($download , 2, 3, $row,$row+1,'expand','shrink',2,2); $download->signal_connect("clicked"=> sub{ - $download ->set_sensitive (FALSE); - my $load= show_gif("icons/load.gif"); - $table->attach ($load, 1, 2, $srow,$srow+ 1,'shrink','shrink',0,0); - $load->show_all; - my $o=$d->{name}; - download_from_google_drive("$d->{url}" ,"$path/$o" ); - $load->destroy; - $download->destroy if (-f $file); + $download ->set_sensitive (FALSE); + my $load= show_gif("icons/load.gif"); + $table->attach ($load, 1, 2, $srow,$srow+ 1,'shrink','shrink',0,0); + $load->show_all; + my $o=$d->{name}; + download_from_google_drive("$d->{url}" ,"$path/$o" ); + $load->destroy; + $download->destroy if (-f $file); }); } $row++; } - - - - - -$window ->add($scrolled_win); -$window->show_all; - -} + $window ->add($scrolled_win); + $window->show_all; +} \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index 734639a..5f436b2 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -5,15 +5,10 @@ use lib $FindBin::Bin; - - sub generate_topology_top_v { my ($self,$info,$dir)=@_; - - #create topology top file my $name=$self->object_get_attribute('save_as'); - my $r; my $top="$dir/${name}_noc.sv"; open my $fd, ">$top" or $r = "$!\n"; @@ -26,79 +21,58 @@ sub generate_topology_top_v { print $fd ' `include "pronoc_def.v" '; - - my $param_str ="\tparameter TOPOLOGY = \"$name\", -\tparameter ROUTE_NAME = \"${name}_DETERMINISTIC\""; - - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; - my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - + my $param_str =" parameter TOPOLOGY = \"$name\", + parameter ROUTE_NAME = \"${name}_DETERMINISTIC\""; + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; # foreach my $d (@parameters){ -# $param_str = $param_str.",\n\tparameter $d->{param_name} = $d->{value}"; +# $param_str = $param_str.",\n parameter $d->{param_name} = $d->{value}"; # } - my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - my $MAX_P=0; foreach my $p (@routers){ my $Pnum=$self->object_get_attribute("$p",'PNUM'); $MAX_P =$Pnum if($Pnum>$MAX_P ); } - my $NE= scalar @ends; my $NR= scalar @routers; - - - - - #step 2 add routers my @nodes=get_list_of_all_routers($self); my $i=0; - - my $ports="\treset, -\tclk"; + my $ports=" reset, + clk"; my $wires='', my $routers=''; - foreach my $p (@ends){ my $instance= $self->object_get_attribute("$p","NAME"); - $ports=$ports.",\n\t//$instance"; + $ports=$ports.",\n //$instance"; $wires=$wires." /******************* * $instance *******************/ "; - - $wires=$wires."\tinput smartflit_chanel_t ${instance}_chan_in;\n"; - $wires=$wires."\toutput smartflit_chanel_t ${instance}_chan_out;\n"; - $wires=$wires."\toutput router_event_t ${instance}_router_event;\n"; - $ports=$ports.",\n\t${instance}_chan_in,\n\t${instance}_chan_out,\n\t${instance}_router_event"; - + $wires=$wires." input smartflit_chanel_t ${instance}_chan_in;\n"; + $wires=$wires." output smartflit_chanel_t ${instance}_chan_out;\n"; + $wires=$wires." output router_event_t ${instance}_router_event;\n"; + $ports=$ports.",\n ${instance}_chan_in,\n ${instance}_chan_out,\n ${instance}_router_event"; foreach my $d (@ports){ my $range = ($d->{pwidth} eq 1)? " " : " [$d->{pwidth}-1 : 0]"; my $type=$d->{type}; my $ctype= ($type eq 'input')? 'output' : 'input'; if( $d->{endp} eq "yes"){ - #$wires=$wires."\t$type $range ${instance}_$d->{pname};\n"; - #$wires=$wires."\t$ctype $range ${instance}_$d->{pconnect};\n"; - #$ports=$ports.",\n\t${instance}_$d->{pname},\n\t${instance}_$d->{pconnect}"; + #$wires=$wires." $type $range ${instance}_$d->{pname};\n"; + #$wires=$wires." $ctype $range ${instance}_$d->{pconnect};\n"; + #$ports=$ports.",\n ${instance}_$d->{pname},\n ${instance}_$d->{pconnect}"; } } } - - foreach my $p (@nodes){ - my ($wire,$router) = get_router_instance_v($self,$p,$i,$NE,$NR,$MAX_P); $wires=$wires.$wire, $routers=$routers.$router; - - $i++; } - my $assign=""; foreach my $p (@ends){ my $instance= $self->object_get_attribute("$p","NAME"); @@ -110,8 +84,6 @@ sub generate_topology_top_v { my ($cp)= sscanf("Port[%u]","$pnode"); #$assign = $assign."//Connect $instance output ports 0 to $cinstance input ports $cp\n"; my $cpplus=$cp+1; - - foreach my $p (@ports){ my $w=$p->{pwidth}; my $range = ($w eq 1)? " " : "[$w-1 : 0 ]"; @@ -119,76 +91,56 @@ sub generate_topology_top_v { my $cport = "${cinstance}_$p->{connect}"; my $port ="${instance}_$p->{pconnect}"; if($p->{type} eq 'input' ){ - # $assign= $assign."\t\tassign $port $range = $cport $crange;\n" if($p->{endp} eq "yes"); + # $assign= $assign." assign $port $range = $cport $crange;\n" if($p->{endp} eq "yes"); }else{ - # $assign= $assign."\t\tassign $cport $crange= $port $range;\n" if($p->{endp} eq "yes"); + # $assign= $assign." assign $cport $crange= $port $range;\n" if($p->{endp} eq "yes"); } - - } #@port + } #@port } - } - - - - - print $fd " + + print $fd " module ${name}_noc #( parameter NOC_ID=0 -) -( +)( $ports ); - `NOC_CONF - + input reset,clk; - + $wires $routers $assign - + endmodule "; add_info($info,"$top file is created\n "); close $fd; - - } - - sub get_router_instance_v { my ($self,$rname,$current_r,$NE,$NR,$MAX_P)=@_; - - my $instance= $self->object_get_attribute("$rname","NAME"); my $Pnum=$self->object_get_attribute("$rname",'PNUM'); - #read ruter parameters and ports - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; - my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; my $wires_v=" /******************* * $instance *******************/ -\twire ${instance}_clk; -\twire ${instance}_reset; - -\twire [RAw-1 : 0] ${instance}_current_r_addr; - -\tsmartflit_chanel_t ${instance}_chan_in [$Pnum-1 : 0]; -\tsmartflit_chanel_t ${instance}_chan_out [$Pnum-1 : 0]; -\trouter_event_t ${instance}_router_event [$Pnum-1 : 0]; - + wire ${instance}_clk; + wire ${instance}_reset; + wire [RAw-1 : 0] ${instance}_current_r_addr; + smartflit_chanel_t ${instance}_chan_in [$Pnum-1 : 0]; + smartflit_chanel_t ${instance}_chan_out [$Pnum-1 : 0]; + router_event_t ${instance}_router_event [$Pnum-1 : 0]; "; - - my $router_v=" /******************* * $instance @@ -207,15 +159,12 @@ sub get_router_instance_v { .router_event (${instance}_router_event) ); "; - - -$router_v= $router_v." -\t\tassign ${instance}_clk = clk; -\t\tassign ${instance}_reset = reset; -\t\tassign ${instance}_current_r_addr = $current_r; + $router_v= $router_v." + assign ${instance}_clk = clk; + assign ${instance}_reset = reset; + assign ${instance}_current_r_addr = $current_r; "; - for (my $i=0;$i<$Pnum; $i++){ my $pname= "Port[${i}]"; my $connect = $self->{$rname}{'PCONNECT'}{$pname}; @@ -227,19 +176,15 @@ sub get_router_instance_v { my ($cp)= sscanf("Port[%u]","$pnode"); $router_v = $router_v."//Connect $instance port $i to $cinstance port $cp\n"; if($ctype ne 'ENDP'){ - $router_v.=" \t\tassign ${instance}_chan_in [$i] = ${cinstance}_chan_out [$cp];\n"; + $router_v.=" assign ${instance}_chan_in [$i] = ${cinstance}_chan_out [$cp];\n"; }else{ - $router_v.=" \t\tassign ${instance}_chan_in [$i] = ${cinstance}_chan_in;\n"; - $router_v.=" \t\tassign ${cinstance}_chan_out = ${instance}_chan_out [$i];\n"; - $router_v.=" \t\tassign ${cinstance}_router_event = ${instance}_router_event [$i];\n"; + $router_v.=" assign ${instance}_chan_in [$i] = ${cinstance}_chan_in;\n"; + $router_v.=" assign ${cinstance}_chan_out = ${instance}_chan_out [$i];\n"; + $router_v.=" assign ${cinstance}_router_event = ${instance}_router_event [$i];\n"; } my $cpplus=$cp+1; - #{name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw" }, - - - foreach my $p (@ports){ my $w=$p->{pwidth}; my $range = ($w eq 1)? "[$i]" : "[($iplus*$w)-1 : $i*$w ]"; @@ -248,47 +193,35 @@ sub get_router_instance_v { my $cport = ($ctype eq 'ENDP') ? "${cinstance}_$p->{pname}" : "${cinstance}_$p->{connect}"; my $port ="${instance}_$p->{name}"; if($ctype eq 'ENDP' && $p->{endp} eq "no" && $p->{type} eq 'input' ){ - # $router_v= $router_v."\t\tassign $port $range = 0;\n"; - + # $router_v= $router_v." assign $port $range = 0;\n"; }else{ if($p->{type} eq 'input' ){ - # $router_v= $router_v."\t\tassign $port $range = $cport $crange;\n"; + # $router_v= $router_v." assign $port $range = $cport $crange;\n"; }else{ - # $router_v= $router_v."\t\tassign $cport $crange= $port $range;\n"; + # $router_v= $router_v." assign $cport $crange= $port $range;\n"; } } - } #@port - + } #@port }else { $router_v = $router_v."//Connect $instance port $i to ground -\t assign ${instance}_chan_in [$i]= {SMARTFLIT_CHANEL_w{1'b0}};\n"; - + assign ${instance}_chan_in [$i]= {SMARTFLIT_CHANEL_w{1'b0}};\n"; foreach my $p (@ports){ my $w=$p->{pwidth}; my $range = ($w eq 1)? "[$i]" : "[($iplus*$w)-1 : $i*$w ]"; if($p->{type} eq 'input' ){ - # $router_v= $router_v."\t\tassign ${instance}_$p->{name} $range = \{$w\{1'b0\}\};\n"; + # $router_v= $router_v." assign ${instance}_$p->{name} $range = \{$w\{1'b0\}\};\n"; } - } - } - -} - - - return ($wires_v,$router_v); + } + } + } + return ($wires_v,$router_v); } - - #******************* # generate_topology_top_genvar_v #******************** - - sub generate_topology_top_genvar_v{ my ($self,$info,$dir)=@_; - - #create topology top file my $name=$self->object_get_attribute('save_as'); my $r; @@ -303,65 +236,47 @@ sub generate_topology_top_genvar_v{ print $fd ' `include "pronoc_def.v" '; - - my $param_str ="\tparameter TOPOLOGY = \"$name\", -\tparameter ROUTE_NAME = \"${name}_DETERMINISTIC\""; + my $param_str =" parameter TOPOLOGY = \"$name\", + parameter ROUTE_NAME = \"${name}_DETERMINISTIC\""; - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; - my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; foreach my $d (@parameters){ - $param_str = $param_str.",\n\tparameter $d->{param_name} = $d->{value}"; + $param_str = $param_str.",\n parameter $d->{param_name} = $d->{value}"; } - my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - my $MAX_P=0; foreach my $p (@routers){ my $Pnum=$self->object_get_attribute("$p",'PNUM'); $MAX_P =$Pnum if($Pnum>$MAX_P ); } - my $NE= scalar @ends; my $NR= scalar @routers; - - - my @nodes=get_list_of_all_routers($self); my $i=0; - - my $ports="\treset, -\tclk, -\tchan_in_all, -\tchan_out_all, -\trouter_event + my $ports=" reset, + clk, + chan_in_all, + chan_out_all, + router_event "; my $ports_def=" -\tinput reset; -\tinput clk; -\tinput smartflit_chanel_t chan_in_all [NE-1 : 0]; -\toutput smartflit_chanel_t chan_out_all [NE-1 : 0]; + input reset; + input clk; + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; //Events -\toutput router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; //all routers port -\tsmartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; -\tsmartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; - - -\twire [RAw-1 : 0] current_r_addr [NR-1 : 0]; - - + smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; + smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; + wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; "; my $router_wires=""; my $endps_wires=""; - - - - foreach my $d (@ports){ my $range = ($d->{width} eq 1)? " " : " [$d->{width}-1 : 0]"; my $pdef_range = ($d->{pwidth} eq 1)? "[NE-1 : 0]" : "[(NE*$d->{pwidth})-1 : 0]"; @@ -369,35 +284,30 @@ sub generate_topology_top_genvar_v{ my $type=$d->{type}; my $ctype= ($type eq 'input')? 'output' : 'input'; if( $d->{endp} eq "yes"){ - #$ports_def=$ports_def."\t$type $pdef_range $d->{name};\n"; - #$ports_def=$ports_def."\t$ctype $pdef_range $d->{connect};\n"; - #$ports=$ports.",\n\t$d->{name},\n\t$d->{connect}"; + #$ports_def=$ports_def." $type $pdef_range $d->{name};\n"; + #$ports_def=$ports_def." $ctype $pdef_range $d->{connect};\n"; + #$ports=$ports.",\n $d->{name},\n $d->{connect}"; } if($d->{width} eq 1){ - #$router_wires=$router_wires. "\twire [NR-1 :0] router_$d->{name};\n"; - #$router_wires=$router_wires. "\twire [NR-1 :0] router_$d->{connect};\n"; + #$router_wires=$router_wires. " wire [NR-1 :0] router_$d->{name};\n"; + #$router_wires=$router_wires. " wire [NR-1 :0] router_$d->{connect};\n"; }else{ - #$router_wires=$router_wires. "\twire $range router_$d->{name} [NR-1 :0];\n"; - #$router_wires=$router_wires. "\twire $range router_$d->{connect} [NR-1 :0];\n"; + #$router_wires=$router_wires. " wire $range router_$d->{name} [NR-1 :0];\n"; + #$router_wires=$router_wires. " wire $range router_$d->{connect} [NR-1 :0];\n"; } if( $d->{endp} eq "yes"){ if($d->{pwidth} eq 1){ - #$endps_wires=$endps_wires. "\twire [NE-1 :0] ni_$d->{pname};\n"; - #$endps_wires=$endps_wires. "\twire [NE-1 :0] ni_$d->{pconnect};\n"; + #$endps_wires=$endps_wires. " wire [NE-1 :0] ni_$d->{pname};\n"; + #$endps_wires=$endps_wires. " wire [NE-1 :0] ni_$d->{pconnect};\n"; }else{ - #$endps_wires=$endps_wires. "\twire $endp_range ni_$d->{pname} [NE-1 :0];\n"; - #$endps_wires=$endps_wires. "\twire $endp_range ni_$d->{pconnect} [NE-1 :0];\n"; + #$endps_wires=$endps_wires. " wire $endp_range ni_$d->{pname} [NE-1 :0];\n"; + #$endps_wires=$endps_wires. " wire $endp_range ni_$d->{pconnect} [NE-1 :0];\n"; } } } - - - - #step 2 add routers my $Tnum=1; - my $routers=' genvar i; generate @@ -428,13 +338,6 @@ sub generate_topology_top_genvar_v{ $Tnum++; } } - - - - - - - $offset=0; my $R_num=0; for ( my $i=2;$i<=12; $i++){ @@ -445,60 +348,43 @@ sub generate_topology_top_genvar_v{ #my $instant=get_router_genvar_instance_v($self,$i,$router_pos,$NE,$NR,$MAX_P); my $p = $i-1; $routers=$routers." -\tfor( i=0; i<$n; i=i+1) begin : router_${i}_port_lp - localparam RID = $router_pos; - assign current_r_addr [RID] = RID[RAw-1: 0]; - - router_top #( - .NOC_ID(NOC_ID), - .ROUTER_ID(RID), - .P($i) - ) router_${i}_port ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr\[RID\]), - .chan_in (router_chan_in \[RID\] \[$p : 0\]), - .chan_out (router_chan_out\[RID\] \[$p : 0\]), - .router_event(router_event\[RID\] \[$p : 0\]) - ); - - - -\tend - "; - + for( i=0; i<$n; i=i+1) begin : router_${i}_port_lp + localparam RID = $router_pos; + assign current_r_addr [RID] = RID[RAw-1: 0]; + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P($i) + ) router_${i}_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr\[RID\]), + .chan_in (router_chan_in \[RID\] \[$p : 0\]), + .chan_out (router_chan_out\[RID\] \[$p : 0\]), + .router_event(router_event\[RID\] \[$p : 0\]) + ); + end +"; for ( my $j=0;$j<$n; $j++){ my $rname ="ROUTER${i}_$j"; my ($ass_v,$r2r_h,$r2e_h, $int_h,$gnd_h); ($ass_v,$r2r_h,$r2e_h, $int_h,$gnd_h,$R_num) = get_wires_assignment_genvar_v($self,$rname,0,\%new_h,$R_num); - $assign=$assign.$ass_v; $assign_r2r.=$r2r_h; $assign_r2e.=$r2e_h; $init_h.=$int_h; $init_gnd_h.=$gnd_h; } - $offset+= $n; - - } + } } - - -$routers.="endgenerate\n"; - - - - - - - print $fd " + $routers.="endgenerate\n"; + print $fd " module ${name}_noc_genvar #( parameter NOC_ID=0 )( - reset, clk, chan_in_all, @@ -507,25 +393,21 @@ sub generate_topology_top_genvar_v{ ); `NOC_CONF - + $ports_def $router_wires $endps_wires - + $routers $assign - - endmodule "; - close $fd; add_info($info,"$top file is created\n "); - my $project_dir = get_project_dir(); $project_dir= "$project_dir/mpsoc"; my $src_verilator_dir="$project_dir/src_verilator/topology/custom"; @@ -536,42 +418,33 @@ sub generate_topology_top_genvar_v{ add_colored_info($info,"Error in creating $top: $r",'red'); return; } - - my $fr2r=""; - for (my $i=0;$i<$R_num ; $i++){ - $fr2r.="\n" if($i%10==0); - $fr2r.=($i==0) ? "single_r2r$i" : ",single_r2r$i"; - - } - - my $fr2e=""; - for (my $i=0;$i<$NE ; $i++){ - $fr2e.="\n" if($i%10==0); - $fr2e.=($i==0) ? "single_r2e$i" : ",single_r2e$i"; - } - - + my $fr2r=""; + for (my $i=0;$i<$R_num ; $i++){ + $fr2r.="\n" if($i%10==0); + $fr2r.=($i==0) ? "single_r2r$i" : ",single_r2r$i"; + } + my $fr2e=""; + for (my $i=0;$i<$NE ; $i++){ + $fr2e.="\n" if($i%10==0); + $fr2e.=($i==0) ? "single_r2e$i" : ",single_r2e$i"; + } print $fd " - $assign_r2r $assign_r2e - void (*r2r_func_ptr[$R_num])() = {$fr2r}; void (*r2e_func_ptr[$NE])() = {$fr2e}; void topology_connect_r2r (int n){ - (*r2r_func_ptr[n])(); + (*r2r_func_ptr[n])(); } void topology_connect_r2e (int n){ - (*r2e_func_ptr[n])(); + (*r2e_func_ptr[n])(); } - - void topology_init(void){ $init_h R2R_TABLE_SIZ=$R_num; @@ -580,23 +453,14 @@ sub generate_topology_top_genvar_v{ "; close $fd; add_info($info,"$top file is created\n "); - } - - - sub get_router_genvar_instance_v{ my ($self,$Pnum,$router_pos,$NE,$NR,$MAX_P)=@_; - #read ruter parameters and ports my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - - - my $router_v=" - router_top #( .NOC_ID(NOC_ID), .ROUTER_ID($router_pos), @@ -610,12 +474,9 @@ sub get_router_genvar_instance_v{ .chan_out(router_chan_out\[$router_pos\]), .router_event(router_event\[$router_pos\]) ); - "; return $router_v; - - } @@ -624,120 +485,84 @@ sub get_wires_assignment_genvar_v{ $reverse = 0 if(!defined $reverse); my $instance= $self->object_get_attribute("$rname","NAME"); my $Pnum=$self->object_get_attribute("$rname",'PNUM'); - #read ruter parameters and ports - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; - my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; my $assign=""; my $r2e_h=""; my $r2r_h=""; my $init_h=""; my $gnd_h=""; - - - my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - my $pos = get_scolar_pos($rname,@routers); my $type = "ROUTER"; if(!defined $pos){ $pos = get_scolar_pos($rname,@ends); $type = "ENDP"; } - my %rinfo = %{$cref} if (defined $cref); - -for (my $i=0;$i<$Pnum; $i++){ - my $pname= "Port[${i}]"; - my $connect = $self->{$rname}{'PCONNECT'}{$pname}; - my $iplus=$i+1; - if(defined $connect){ - my ($cname,$pnode)=split(/\s*,\s*/,$connect); - my $cinstance= $self->object_get_attribute("$cname","NAME"); - my $ctype = $self->object_get_attribute("$cname",'TYPE'); - my ($cp)= sscanf("Port[%u]","$pnode"); - $assign.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; - - - my $cpos =($ctype eq 'ENDP')? get_scolar_pos($cname,@ends) : get_scolar_pos($cname,@routers); - - my $cpplus=$cp+1; - my $cposplus = $cpos+1; - my $posplus=$pos+1; - #{name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw" }, - - my $TNUM_pos = $rinfo{"TNUM_${pos}"}; - my $RNUM_pos = $rinfo{"RNUM_${pos}"}; - my $TNUM_cpos = $rinfo{"TNUM_${cpos}"}; - my $RNUM_cpos = $rinfo{"RNUM_${cpos}"}; - - #$assign = $assign."//connet $instance input port $i to $cinstance output port $cp\n"; - if($type ne 'ENDP' && $ctype eq 'ENDP'){ - - $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] = chan_in_all \[$cpos\];\n" if($reverse==0); - $assign= $assign."\t\tassign chan_in_all \[$cpos\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); - - $assign= $assign."\t\tassign chan_out_all \[$cpos\] = router_chan_out \[$pos\]\[$i\];\n" if($reverse==0); - $assign= $assign."\t\tassign router_chan_out \[$pos\]\[$i\] = chan_out_all \[$cpos\];\n" if($reverse==1); - - $r2e_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; - $r2e_h.= "void single_r2e$cpos(void) {connect_r2e($TNUM_pos,$RNUM_pos,$i,$cpos);}\n" if (defined $TNUM_pos); - - - }elsif ($type ne 'ENDP' && $ctype ne 'ENDP'){ - $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] = router_chan_out \[$cpos\]\[$cp\];\n" if($reverse==0); - $assign= $assign."\t\tassign router_chan_out \[$cpos\]\[$cp\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); - $r2r_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; - $r2r_h.= "void single_r2r$R_num(void){conect_r2r($TNUM_pos,$RNUM_pos,$i,$TNUM_cpos,$RNUM_cpos,$cp);}\n" if (defined $TNUM_pos); - $init_h.="\tr2r_cnt_all[$R_num] =(r2r_cnt_table_t){.id1=$pos, .t1=$TNUM_pos, .r1=$RNUM_pos, .p1=$i,.id2=$cpos, .t2=$TNUM_cpos, .r2=$RNUM_cpos, .p2=$cp };\n"; - $R_num++; + for (my $i=0;$i<$Pnum; $i++){ + my $pname= "Port[${i}]"; + my $connect = $self->{$rname}{'PCONNECT'}{$pname}; + my $iplus=$i+1; + if(defined $connect){ + my ($cname,$pnode)=split(/\s*,\s*/,$connect); + my $cinstance= $self->object_get_attribute("$cname","NAME"); + my $ctype = $self->object_get_attribute("$cname",'TYPE'); + my ($cp)= sscanf("Port[%u]","$pnode"); + $assign.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + my $cpos =($ctype eq 'ENDP')? get_scolar_pos($cname,@ends) : get_scolar_pos($cname,@routers); + my $cpplus=$cp+1; + my $cposplus = $cpos+1; + my $posplus=$pos+1; + #{name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw" }, + my $TNUM_pos = $rinfo{"TNUM_${pos}"}; + my $RNUM_pos = $rinfo{"RNUM_${pos}"}; + my $TNUM_cpos = $rinfo{"TNUM_${cpos}"}; + my $RNUM_cpos = $rinfo{"RNUM_${cpos}"}; + #$assign = $assign."//connet $instance input port $i to $cinstance output port $cp\n"; + if($type ne 'ENDP' && $ctype eq 'ENDP'){ + $assign= $assign." assign router_chan_in \[$pos\]\[$i\] = chan_in_all \[$cpos\];\n" if($reverse==0); + $assign= $assign." assign chan_in_all \[$cpos\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); + $assign= $assign." assign chan_out_all \[$cpos\] = router_chan_out \[$pos\]\[$i\];\n" if($reverse==0); + $assign= $assign." assign router_chan_out \[$pos\]\[$i\] = chan_out_all \[$cpos\];\n" if($reverse==1); + $r2e_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + $r2e_h.= "void single_r2e$cpos(void) {connect_r2e($TNUM_pos,$RNUM_pos,$i,$cpos);}\n" if (defined $TNUM_pos); + }elsif ($type ne 'ENDP' && $ctype ne 'ENDP'){ + $assign= $assign." assign router_chan_in \[$pos\]\[$i\] = router_chan_out \[$cpos\]\[$cp\];\n" if($reverse==0); + $assign= $assign." assign router_chan_out \[$cpos\]\[$cp\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); + $r2r_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + $r2r_h.= "void single_r2r$R_num(void){conect_r2r($TNUM_pos,$RNUM_pos,$i,$TNUM_cpos,$RNUM_cpos,$cp);}\n" if (defined $TNUM_pos); + $init_h.=" r2r_cnt_all[$R_num] =(r2r_cnt_table_t){.id1=$pos, .t1=$TNUM_pos, .r1=$RNUM_pos, .p1=$i,.id2=$cpos, .t2=$TNUM_cpos, .r2=$RNUM_cpos, .p2=$cp };\n"; + $R_num++; + } + }else { + my $TNUM_pos = $rinfo{"TNUM_${pos}" }; + my $RNUM_pos = $rinfo{"RNUM_${pos}" }; + $assign = $assign."//Connect $instance port $i to ground\n"; + $assign= $assign." assign router_chan_in \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==0); + $assign= $assign." assign router_chan_out \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==1); + $gnd_h.="//Connect $instance port $i to ground\n"; + $gnd_h.= " connect_r2gnd($TNUM_pos,$RNUM_pos,$i);\n" if (defined $TNUM_pos); } - - - - - - }else { - my $TNUM_pos = $rinfo{"TNUM_${pos}" }; - my $RNUM_pos = $rinfo{"RNUM_${pos}" }; - - $assign = $assign."//Connect $instance port $i to ground\n"; - $assign= $assign."\t\tassign router_chan_in \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==0); - $assign= $assign."\t\tassign router_chan_out \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==1); - - $gnd_h.="//Connect $instance port $i to ground\n"; - $gnd_h.= "\tconnect_r2gnd($TNUM_pos,$RNUM_pos,$i);\n" if (defined $TNUM_pos); - } - -} - - - + } return ($assign,$r2r_h,$r2e_h,$init_h,$gnd_h,$R_num); } - - sub generate_routing_v { my ($self,$info,$dir)=@_; - my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - -######################### -# conventional_routing -######################### - - + ######################### + # conventional_routing + ######################### #create routing file my $name=$self->object_get_attribute('save_as'); my $rname=$self->object_get_attribute('routing_name'); my $Vname="T${name}R${rname}"; - my $r; my $top="$dir/${Vname}_conventional_routing.v"; open my $fd, ">$top" or $r = "$!\n"; @@ -747,74 +572,60 @@ sub generate_routing_v { } print $fd autogen_warning(); print $fd get_license_header($top); - - - - - - my $route_str="\talways@(*)begin -\t\tdestport=0; -\t\tcase(src_e_addr) //source address of each individual NI is fixed. So this CASE will be optimized by the synthesizer for each endpoint. + my $route_str=" always@(*)begin + destport=0; + case(src_e_addr) //source address of each individual NI is fixed. So this CASE will be optimized by the synthesizer for each endpoint. "; - foreach my $src (@ends){ my $PNUM=$self->object_get_attribute($src,"PNUM"); my $src_num=get_scolar_pos($src,@ends); my %route; - $route_str=$route_str."\t\t$src_num: begin -\t\t\tcase(dest_e_addr) + $route_str=$route_str." $src_num: begin + case(dest_e_addr) "; - foreach my $dst (@ends){ - my $dest_num = get_scolar_pos($dst,@ends); - my $ref = $self->object_get_attribute('Route',"${src}::$dst"); - next if(!defined $ref); - my @path = @{$ref}; - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); - #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; - $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; + my $dest_num = get_scolar_pos($dst,@ends); + my $ref = $self->object_get_attribute('Route',"${src}::$dst"); + next if(!defined $ref); + my @path = @{$ref}; + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); + #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; + $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; } foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin -\t\t\t\tdestport= $q; -\t\t\tend + $route_str=$route_str." $route{$q}: begin + destport= $q; + end "; } $route_str=$route_str." -\t\t\tdefault: begin -\t\t\t\tdestport= {DSTPw{1\'bX}}; -\t\t\tend -\t\t\tendcase\n\t\tend//$src_num\n"; + default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end//$src_num\n"; } $route_str=$route_str." -\t\tdefault: begin -\t\t\tdestport= {DSTPw{1\'bX}}; -\t\tend -\t\tendcase\n\tend\n"; - - - - print $fd "module ${Vname}_conventional_routing #( -\tparameter RAw = 3, -\tparameter EAw = 3, -\tparameter DSTPw=4 + default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end\n"; + print $fd "module ${Vname}_conventional_routing #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 ) ( -\tdest_e_addr, -\tsrc_e_addr, -\tdestport + dest_e_addr, + src_e_addr, + destport ); - -\tinput [EAw-1 :0] dest_e_addr; -\tinput [EAw-1 :0] src_e_addr; -\toutput reg [DSTPw-1 :0] destport; - + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output reg [DSTPw-1 :0] destport; $route_str - endmodule - "; close($fd); add_info($info,"$top file is created\n "); @@ -832,21 +643,17 @@ sub generate_routing_v { } print $fd autogen_warning(); print $fd get_license_header($top); - - - $route_str="\talways@(*)begin -\t\tdestport=0; -\t\tcase(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. + $route_str=" always@(*)begin + destport=0; + case(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. "; - - foreach my $router (@routers){ - my $PNUM=$self->object_get_attribute($router,"PNUM"); - my $router_num=get_scolar_pos($router,@routers); - my %route; - $route_str=$route_str."\t\t$router_num: begin -\t\t\tcase({src_e_addr,dest_e_addr}) + my $PNUM=$self->object_get_attribute($router,"PNUM"); + my $router_num=get_scolar_pos($router,@routers); + my %route; + $route_str=$route_str." $router_num: begin + case({src_e_addr,dest_e_addr}) "; # for each src-dest check if $router include in path foreach my $src (@ends){ @@ -864,130 +671,106 @@ sub generate_routing_v { my $src_num=get_scolar_pos($src,@ends); my $dest_num = get_scolar_pos($dst,@ends); $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; - #print "@path\n"; #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; #print"***************************\n"; - } } foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin -\t\t\t\tdestport= $q; -\t\t\tend + $route_str=$route_str." $route{$q}: begin + destport= $q; + end "; - } - - $route_str.="\t\t\tdefault: begin -\t\t\t\tdestport= {DSTPw{1\'bX}}; -\t\t\tend -\t\t\tendcase\n\t\tend//$router_num\n"; + $route_str.=" default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end//$router_num\n"; } -$route_str.="\t\tdefault: begin -\t\t\tdestport= {DSTPw{1\'bX}}; -\t\tend -\t\tendcase\n\tend\n"; + $route_str.=" default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end\n"; - - -my $localparam=""; + my $localparam=""; my $i=0; foreach my $src (@ends){ - $localparam= $localparam."localparam [EAw-1 : 0]\tE$i=$i;\n"; + $localparam= $localparam."localparam [EAw-1 : 0] E$i=$i;\n"; $i++; } + print $fd " - - - - print $fd " - - `include \"pronoc_def.v\" +`include \"pronoc_def.v\" /******************* * ${Vname}_look_ahead_routing *******************/ module ${Vname}_look_ahead_routing #( -\tparameter RAw = 3, -\tparameter EAw = 3, -\tparameter DSTPw=4 -) -( -\treset, -\tclk, -\tcurrent_r_addr, -\tdest_e_addr, -\tsrc_e_addr, -\tdestport + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + reset, + clk, + current_r_addr, + dest_e_addr, + src_e_addr, + destport ); - -\tinput [RAw-1 :0] current_r_addr; -\tinput [EAw-1 :0] dest_e_addr; -\tinput [EAw-1 :0] src_e_addr; -\toutput [DSTPw-1 :0] destport; -\tinput reset,clk; - + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output [DSTPw-1 :0] destport; + input reset,clk; reg [EAw-1 :0] dest_e_addr_delay; reg [EAw-1 :0] src_e_addr_delay; - + always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset)begin dest_e_addr_delay<={EAw{1'b0}}; - src_e_addr_delay<={EAw{1'b0}}; + src_e_addr_delay<={EAw{1'b0}}; end else begin dest_e_addr_delay<=dest_e_addr; - src_e_addr_delay<=src_e_addr; + src_e_addr_delay<=src_e_addr; end end - + ${Vname}_look_ahead_routing_comb #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) - ) - lkp_cmb - ( + ) lkp_cmb ( .current_r_addr(current_r_addr), .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), .destport(destport) ); - - - endmodule - + /******************* * ${Vname}_look_ahead_routing_comb *******************/ - - module ${Vname}_look_ahead_routing_comb #( -\tparameter RAw = 3, -\tparameter EAw = 3, -\tparameter DSTPw=4 -) -( -\tcurrent_r_addr, -\tdest_e_addr, -\tsrc_e_addr, -\tdestport +module ${Vname}_look_ahead_routing_comb #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + current_r_addr, + dest_e_addr, + src_e_addr, + destport ); - -\tinput [RAw-1 :0] current_r_addr; -\tinput [EAw-1 :0] dest_e_addr; -\tinput [EAw-1 :0] src_e_addr; -\toutput reg [DSTPw-1 :0] destport; + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output reg [DSTPw-1 :0] destport; $localparam - -$route_str - - -endmodule +$route_str +endmodule "; close($fd); @@ -996,8 +779,6 @@ sub generate_routing_v { ######################### # conventional_routing_genvar ######################### - - #create routing file $top="$dir/${Vname}_conventional_routing_genvar.v"; open $fd, ">$top" or $r = "$!\n"; @@ -1007,70 +788,54 @@ sub generate_routing_v { } print $fd autogen_warning(); print $fd get_license_header($top); - - - - - - $route_str="\tgenerate - + $route_str=" generate "; - foreach my $src (@ends){ my $PNUM=$self->object_get_attribute($src,"PNUM"); my $src_num=get_scolar_pos($src,@ends); my %route; - $route_str=$route_str."\tif(SRC_E_ADDR == $src_num) begin : SRC$src_num -\t\talways@(*)begin -\t\t\tdestport= 0; -\t\t\tcase(dest_e_addr) + $route_str=$route_str." if(SRC_E_ADDR == $src_num) begin : SRC$src_num + always@(*)begin + destport= 0; + case(dest_e_addr) "; foreach my $dst (@ends){ - my $dest_num = get_scolar_pos($dst,@ends); - my $ref = $self->object_get_attribute('Route',"${src}::$dst"); - next if(!defined $ref); - my @path = @{$ref}; - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); - #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; - $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; + my $dest_num = get_scolar_pos($dst,@ends); + my $ref = $self->object_get_attribute('Route',"${src}::$dst"); + next if(!defined $ref); + my @path = @{$ref}; + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); + #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; + $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; } foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin -\t\t\t\tdestport= $q; -\t\t\tend + $route_str=$route_str." $route{$q}: begin + destport= $q; + end "; } - $route_str=$route_str."\t\t\tdefault: begin -\t\t\t\tdestport= {DSTPw{1\'bX}}; -\t\t\tend - -\t\t\tendcase\n\t\tend\n\tend//SRC$src_num\n\n"; + $route_str=$route_str." default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end\n end//SRC$src_num\n\n"; } - $route_str=$route_str."\tendgenerate\n"; - - - - print $fd "module ${Vname}_conventional_routing_genvar #( -\tparameter RAw = 3, -\tparameter EAw = 3, -\tparameter DSTPw=4, -\tparameter SRC_E_ADDR=0 -) -( -\tdest_e_addr, -\tdestport + $route_str=$route_str." endgenerate\n"; + print $fd "module ${Vname}_conventional_routing_genvar #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter SRC_E_ADDR=0 +) ( + dest_e_addr, + destport ); - -\tinput [EAw-1 :0] dest_e_addr; -\toutput reg [DSTPw-1 :0] destport; - + input [EAw-1 :0] dest_e_addr; + output reg [DSTPw-1 :0] destport; $route_str - - -endmodule +endmodule "; close($fd); add_info($info,"$top file is created\n "); @@ -1078,7 +843,6 @@ sub generate_routing_v { ################## # look_ahead_routing_genvar ################### - #create routing file $top="$dir/${Vname}_look_ahead_routing_genvar.v"; open $fd, ">$top" or $r = "$!\n"; @@ -1088,25 +852,21 @@ sub generate_routing_v { } print $fd autogen_warning(); print $fd get_license_header($top); - - - - $route_str="\talways@(*)begin -\t\tdestport=0; -\t\tcase(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. + $route_str=" always@(*)begin + destport=0; + case(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. "; -$route_str="\tgenerate\n"; + $route_str=" generate\n"; - -foreach my $router (@routers){ + foreach my $router (@routers){ my $PNUM=$self->object_get_attribute($router,"PNUM"); my $router_num=get_scolar_pos($router,@routers); my %route; - $route_str=$route_str."\tif(CURRENT_R_ADDR == $router_num) begin :R$router_num -\t\talways@(*)begin -\t\t\tdestport= 0; -\t\t\tcase({src_e_addr,dest_e_addr}) + $route_str=$route_str." if(CURRENT_R_ADDR == $router_num) begin :R$router_num + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) "; # for each src-dest check if $router include in path foreach my $src (@ends){ @@ -1124,130 +884,101 @@ sub generate_routing_v { my $src_num=get_scolar_pos($src,@ends); my $dest_num = get_scolar_pos($dst,@ends); $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; - #print "@path\n"; #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; #print"***************************\n"; - } } foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str."\t\t\t$route{$q}: begin -\t\t\t\tdestport= $q; -\t\t\tend -"; - - } - - $route_str=$route_str."\t\t\tendcase\n\t\tend\n\tend//R$router_num\n\n"; + $route_str=$route_str." $route{$q}: begin + destport= $q; + end +"; } - $route_str=$route_str."\tendgenerate\n"; - - - - print $fd " - `include \"pronoc_def.v\" - + $route_str=$route_str." endcase\n end\n end//R$router_num\n\n"; + } + $route_str=$route_str." endgenerate\n"; + print $fd " +`include \"pronoc_def.v\" /***************************** * ${Vname}_look_ahead_routing_genvar ******************************/ module ${Vname}_look_ahead_routing_genvar #( -\tparameter RAw = 3, -\tparameter EAw = 3, -\tparameter DSTPw=4, -\tparameter CURRENT_R_ADDR=0 -) -( -\tdest_e_addr, -\tsrc_e_addr, -\tdestport, -\treset, -\tclk + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter CURRENT_R_ADDR=0 +)( + dest_e_addr, + src_e_addr, + destport, + reset, + clk ); - -\tinput [EAw-1 :0] dest_e_addr; -\tinput [EAw-1 :0] src_e_addr; -\toutput [DSTPw-1 :0] destport; -\tinput reset,clk; - + + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output [DSTPw-1 :0] destport; + input reset,clk; + reg [EAw-1 :0] dest_e_addr_delay; reg [EAw-1 :0] src_e_addr_delay; - - always @ (`pronoc_clk_reset_edge )begin + + always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin dest_e_addr_delay<={EAw{1'b0}}; - src_e_addr_delay<={EAw{1'b0}}; + src_e_addr_delay<={EAw{1'b0}}; end else begin dest_e_addr_delay<=dest_e_addr; - src_e_addr_delay<=src_e_addr; - end + src_e_addr_delay<=src_e_addr; + end end - ${name}_look_ahead_routing_genvar_comb #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw), .CURRENT_R_ADDR(CURRENT_R_ADDR) - ) - lkp_cmb - ( - + ) lkp_cmb ( .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), .destport(destport) ); +endmodule - - -endmodule - /******************* * ${Vname}_look_ahead_routing_genvar_comb ********************/ - - - module ${Vname}_look_ahead_routing_genvar_comb #( -\tparameter RAw = 3, -\tparameter EAw = 3, -\tparameter DSTPw=4, -\tparameter CURRENT_R_ADDR=0 -) -( -\tdest_e_addr, -\tsrc_e_addr, -\tdestport +module ${Vname}_look_ahead_routing_genvar_comb #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter CURRENT_R_ADDR=0 +) ( + dest_e_addr, + src_e_addr, + destport ); - -\tinput [EAw-1 :0] dest_e_addr; -\tinput [EAw-1 :0] src_e_addr; -\toutput reg [DSTPw-1 :0] destport; - + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output reg [DSTPw-1 :0] destport; $localparam - + $route_str - endmodule - - "; - - -close($fd); -add_info($info,"$top file is created\n "); - + close($fd); + add_info($info,"$top file is created\n "); } sub generate_connection_v{ my($self,$info,$dir)=@_; - #create connection top file my $name=$self->object_get_attribute('save_as'); - my $r; my $top="$dir/${name}_connection.sv"; open my $fd, ">$top" or $r = "$!\n"; @@ -1257,96 +988,69 @@ sub generate_connection_v{ } print $fd autogen_warning(); print $fd get_license_header($top); -print $fd ' + print $fd ' `include "pronoc_def.v" '; - - - - - - - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; - my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; - - - + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; + my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - my $MAX_P=0; foreach my $p (@routers){ my $Pnum=$self->object_get_attribute("$p",'PNUM'); $MAX_P =$Pnum if($Pnum>$MAX_P ); } - my $NE= scalar @ends; my $NR= scalar @routers; - - - my @nodes=get_list_of_all_routers($self); my $i=0; - - my $ports="\treset, -\tclk, -\tstart_i, -\tstart_o, -\ter_addr, -\tcurrent_r_addr, -\tchan_in_all, -\tchan_out_all, -\trouter_chan_in, -\trouter_chan_out + my $ports=" reset, + clk, + start_i, + start_o, + er_addr, + current_r_addr, + chan_in_all, + chan_out_all, + router_chan_in, + router_chan_out "; - my $ports_def=" -\tinput reset; -\tinput clk; -\tinput start_i; -\toutput [RAw-1 : 0] er_addr [NE-1 : 0]; // provide router address for each connected endpoint -\toutput [RAw-1 : 0] current_r_addr [NR-1 : 0]; // provide each router current address ; -\toutput [NE-1 : 0] start_o; -\toutput smartflit_chanel_t chan_in_all [NE-1 : 0]; -\tinput smartflit_chanel_t chan_out_all [NE-1 : 0]; -\tinput smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; -\toutput smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; + input reset; + input clk; + input start_i; + output [RAw-1 : 0] er_addr [NE-1 : 0]; // provide router address for each connected endpoint + output [RAw-1 : 0] current_r_addr [NR-1 : 0]; // provide each router current address ; + output [NE-1 : 0] start_o; + output smartflit_chanel_t chan_in_all [NE-1 : 0]; + input smartflit_chanel_t chan_out_all [NE-1 : 0]; + input smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; + output smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; "; - my $router_wires=""; my $endps_wires=""; - - - - foreach my $d (@ports){ my $range = ($d->{width} eq 1)? " " : " [$d->{width}-1 : 0]"; my $pdef_range = ($d->{pwidth} eq 1)? "[NE-1 : 0]" : "[$d->{pwidth}-1 : 0]"; my $pdef_range2 = ($d->{pwidth} eq 1)? "" : "[NE-1 : 0]"; - #$ports=$ports.",\n\trouter_$d->{name},\n\trouter_$d->{connect}"; + #$ports=$ports.",\n router_$d->{name},\n router_$d->{connect}"; my $type=$d->{type}; my $ctype= ($type eq 'input')? 'output' : 'input'; if( $d->{endp} eq "yes"){ - #$ports_def=$ports_def."\t$type\t$pdef_range ni_$d->{pname} $pdef_range2;\n"; - #$ports_def=$ports_def."\t$ctype\t$pdef_range ni_$d->{pconnect} $pdef_range2;\n"; - #$ports=$ports.",\n\tni_$d->{pname},\n\tni_$d->{pconnect}"; + #$ports_def=$ports_def." $type $pdef_range ni_$d->{pname} $pdef_range2;\n"; + #$ports_def=$ports_def." $ctype $pdef_range ni_$d->{pconnect} $pdef_range2;\n"; + #$ports=$ports.",\n ni_$d->{pname},\n ni_$d->{pconnect}"; } if($d->{width} eq 1){ - #$ports_def=$ports_def. "\t$type\t[NR-1 :0] router_$d->{name};\n"; - #$ports_def=$ports_def. "\t$ctype\t[NR-1 :0] router_$d->{connect};\n"; + #$ports_def=$ports_def. " $type [NR-1 :0] router_$d->{name};\n"; + #$ports_def=$ports_def. " $ctype [NR-1 :0] router_$d->{connect};\n"; }else{ - #$ports_def=$ports_def. "\t$type\t$range router_$d->{name} [NR-1 :0];\n"; - #$ports_def=$ports_def. "\t$ctype\t$range router_$d->{connect} [NR-1 :0];\n"; + #$ports_def=$ports_def. " $type $range router_$d->{name} [NR-1 :0];\n"; + #$ports_def=$ports_def. " $ctype $range router_$d->{connect} [NR-1 :0];\n"; } - - - } - - - - + } my $routers=' genvar i; generate @@ -1360,34 +1064,24 @@ sub generate_connection_v{ if($n>0){ my $router_pos= ($offset==0)? 'i' : "i+$offset"; my $instant=get_router_genvar_instance_v($self,$i,$router_pos,$NE,$NR,$MAX_P); - $routers=$routers." -\tfor( i=0; i<$n; i=i+1) begin : router_${i}_port_lp -\t\t$instant + for( i=0; i<$n; i=i+1) begin : router_${i}_port_lp + $instant -\tend + end "; - for ( my $j=0;$j<$n; $j++){ my $rname ="ROUTER${i}_$j"; my ($ass_v, $r2r_h,$r2e_h, $int_h,$gnd_h,$R_num)= get_wires_assignment_genvar_v($self,$rname,1,undef,$R_num); $assign=$assign.$ass_v; } - - $offset+= $n; - - } + $offset+= $n; + } } - - - foreach my $end (@ends){ #$assign=$assign.get_wires_assignment_genvar_v($self,$end,1); } - $assign=$assign."\n"; - - my $pos=0; $assign.="//The router address connected to each endpoint\n"; foreach my $end (@ends){ @@ -1396,32 +1090,24 @@ sub generate_connection_v{ my $R = get_scolar_pos($Rname,@routers); my $rname = $self->object_get_attribute("$Rname","NAME"); my $tname = $self->object_get_attribute("$end","NAME"); - $assign=$assign."\tassign er_addr [$pos] = $R; //$tname -> $rname\n"; - $pos++; + $assign=$assign." assign er_addr [$pos] = $R; //$tname -> $rname\n"; + $pos++; } - $assign=$assign."\n"; - $pos=0; foreach my $router (@routers){ my $rname = $self->object_get_attribute("$router","NAME"); - $assign=$assign."\tassign current_r_addr [$pos] = $pos; // $rname\n"; - $pos++; + $assign=$assign." assign current_r_addr [$pos] = $pos; // $rname\n"; + $pos++; } - - - - - print $fd " + print $fd " module ${name}_connection #( parameter NOC_ID=0 )( $ports ); - `NOC_CONF - localparam P= MAX_P, @@ -1431,35 +1117,25 @@ sub generate_connection_v{ PRAw = P * RAw; $ports_def - + $router_wires - + $endps_wires - - -$assign - - + +$assign + start_delay_gen #( .NC(NE) - ) - delay_gen - ( + ) delay_gen ( .clk(clk), .reset(reset), .start_i(start_i), .start_o(start_o) ); - - endmodule "; - add_info($info,"$top file is created\n "); close $fd; - - - } sub add_noc_custom_h{ @@ -1471,8 +1147,6 @@ sub add_noc_custom_h{ #include \"${name}_noc.h\" #endif "; - - my $file = "$dir/../../../src_verilator/topology/custom/custom.h"; #check if ***$name**** exist in the file unless (-f $file){ @@ -1482,19 +1156,14 @@ sub add_noc_custom_h{ my $r = check_file_has_string($file, "===${name}==="); if ($r==1){ add_info($info,"The instance ${name}_noc exists in $file. This file is not modified\n ",'blue'); - }else{ my $text = read_file_cntent($file,' '); my @a = split('endgenerate',$text); save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${name}_noc has been added to the file\n ",'blue'); - } - } - - sub add_routing_instance_v{ my ($self,$info,$dir)=@_; my $name=$self->object_get_attribute('save_as'); @@ -1506,26 +1175,20 @@ sub add_routing_instance_v{ my $str=" //do not modify this line ===${Vname}=== if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : $Vname - ${Vname}_conventional_routing #( - .RAw(RAw), + .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) - ) - the_conventional_routing - ( + ) the_conventional_routing ( .dest_e_addr(dest_e_addr), .src_e_addr(src_e_addr), - .destport(destport) - ); - - end - + .destport(destport) + ); + end endgenerate - "; - my $file = "$dir/../common/custom_ni_routing.v"; + my $file = "$dir/../common/custom_ni_routing.v"; #check if ***$name**** exist in the file unless (-f $file){ add_colored_info($info,"$file dose not exist\n",'red'); @@ -1540,41 +1203,29 @@ sub add_routing_instance_v{ my @a = split('endgenerate',$text); save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${Vname}_conventional_routing has been added to the file\n ",'blue'); - } - - - ##################################### # custom_lkh_routing #################################### - $str=" + $str=" //do not modify this line ===${Vname}=== if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : ${Vname} - - ${Vname}_look_ahead_routing #( + ${Vname}_look_ahead_routing #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) - ) - the_lkh_routing - ( + ) the_lkh_routing ( .current_r_addr(current_r_addr), .dest_e_addr(dest_e_addr), .src_e_addr(src_e_addr), .destport(destport), .reset(reset), - .clk(clk) - ); - - end - + .clk(clk) + ); + end endgenerate - "; - $file = "$dir/../common/custom_lkh_routing.v"; - unless (-f $file){ add_colored_info($info,"$file dose not exist\n",'red'); return; @@ -1588,94 +1239,52 @@ sub add_routing_instance_v{ my @a = split('endgenerate',$text); save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${Vname}_look_ahead_routing has been added to the file\n ",'blue'); - } - - } sub add_noc_instance_v{ my ($self,$info,$dir)=@_; my $name=$self->object_get_attribute('save_as'); - ##################################### # add connection #################################### - - my $ports="\t\t.reset(reset), -\t\t.clk(clk), -\t\t.start_i(start_i), -\t\t.start_o(start_o), -\t\t.er_addr(er_addr), -\t\t.current_r_addr(current_r_addr), -\t\t.chan_in_all(chan_in_all), -\t\t.chan_out_all(chan_out_all), -\t\t.router_chan_in(router_chan_in), -\t\t.router_chan_out(router_chan_out) - - + my $ports=" .reset(reset), + .clk(clk), + .start_i(start_i), + .start_o(start_o), + .er_addr(er_addr), + .current_r_addr(current_r_addr), + .chan_in_all(chan_in_all), + .chan_out_all(chan_out_all), + .router_chan_in(router_chan_in), + .router_chan_out(router_chan_out) "; - - - - my $str=" //do not modify this line ===${name}=== if(TOPOLOGY == \"$name\" ) begin : T$name - ${name}_connection #( .NOC_ID(NOC_ID) ) connection ( -$ports - ); - - end - +$ports + ); + end endgenerate - "; - - #my $file = "$dir/../common/custom_noc_connection.sv"; - #check if ***$name**** exist in the file - #unless (-f $file){ - # add_colored_info($info,"$file dose not exist\n",'red'); - # return; - #} - #my $r = check_file_has_string($file, "===${name}==="); - #if ($r==1){ - #add_info($info,"The instance ${name}_connection exists in $file. This file is not modified\n ",'blue'); - - #}else{ - #my $text = read_file_cntent($file,' '); - # my @a = split('endgenerate',$text); - # save_file($file,"$a[0] $str $a[1]"); - # add_info($info,"$file has been modified. The ${name}_connection has been added to the file\n ",'blue'); - - #} - - ##################################### # add NoC #################################### - - - my $param_str ="\t\t.TOPOLOGY(TOPOLOGY), -\t\t.ROUTE_NAME(ROUTE_NAME)"; - - my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; - + my $param_str =" .TOPOLOGY(TOPOLOGY), + .ROUTE_NAME(ROUTE_NAME)"; + my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; foreach my $d (@parameters){ - $param_str = $param_str.",\n\t\t.$d->{param_name}($d->{param_name})"; + $param_str = $param_str.",\n .$d->{param_name}($d->{param_name})"; } - - $ports="\t\t.reset(reset), -\t\t.clk(clk)"; - + $ports=" .reset(reset), + .clk(clk)"; $str=" //do not modify this line ===${name}=== if(TOPOLOGY == \"$name\" ) begin : T$name - ${name}_noc_genvar #( .NOC_ID(NOC_ID) ) the_noc ( @@ -1686,12 +1295,8 @@ sub add_noc_instance_v{ .router_event(router_event) ); end - endgenerate - - "; - - +"; my $file = "$dir/../common/custom_noc_top.sv"; #check if ***$name**** exist in the file @@ -1709,18 +1314,5 @@ sub add_noc_instance_v{ save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${name}_noc has been added to the file\n ",'blue'); } - - - - - - - - - - - } - - -1 +1 \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/debug.v b/mpsoc/rtl/src_noc/debug.v index 0b0f0d5..7236635 100644 --- a/mpsoc/rtl/src_noc/debug.v +++ b/mpsoc/rtl/src_noc/debug.v @@ -550,7 +550,7 @@ module check_pck_size #( wire [V-1 : 0] vc_hdr_wr_en; wire [V-1 : 0] onehot; localparam MIN_B = (B 0); pronoc_register #(.W(Bw+1)) reg1 (.in(counter_next), .reset(reset), .clk(clk), .out(counter)); -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/routing.v b/mpsoc/rtl/src_noc/routing.v index 6a7cdad..258ad2a 100755 --- a/mpsoc/rtl/src_noc/routing.v +++ b/mpsoc/rtl/src_noc/routing.v @@ -37,6 +37,7 @@ module conventional_routing #( parameter T3 = 4, parameter RAw = 3, parameter EAw = 3, + parameter DAw = EAw, parameter DSTPw = 4, parameter LOCATED_IN_NI = 1 // only needed for mesh and odd-even routing )( @@ -60,7 +61,7 @@ module conventional_routing #( input reset,clk; input [RAw-1 :0] current_r_addr; input [EAw-1 :0] src_e_addr; - input [EAw-1 :0] dest_e_addr; + input [DAw-1 :0] dest_e_addr; output [DSTPw-1 :0] destport; generate @@ -512,4 +513,4 @@ module next_router_addr_selector_bin #( .mux_out(next_ry), .sel(destport_bin) ); -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index a06adf9..cd103aa 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -7,7 +7,18 @@ * Description: ***************************************/ `ifdef INCLUDE_TOPOLOGY_LOCALPARAM - //MESH, TORUS Topology p=5 + localparam [0:0] + /* verilator lint_off WIDTH */ + IS_LINE = (TOPOLOGY == "LINE"), + IS_RING = (TOPOLOGY == "RING"), + IS_MESH = (TOPOLOGY == "MESH"), + IS_FMESH= (TOPOLOGY == "FMESH"), + IS_TORUS= (TOPOLOGY == "TORUS"), + IS_FATTREE=(TOPOLOGY == "FATTREE"), + IS_TREE= (TOPOLOGY == "TREE"), + IS_STAR= (TOPOLOGY == "STAR"); + /* verilator lint_on WIDTH */ + //MESH, TORUS Topology p=5 localparam LOCAL = 0, EAST = 1, @@ -15,7 +26,7 @@ WEST = 3, SOUTH = 4; - //LINE RING Topology p=3 + //LINE RING Topology p=3 localparam FORWARD = 1, BACKWARD= 2; @@ -23,11 +34,11 @@ function automatic integer log2; input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 4 ) port_buffer_size = LB; - end + end end endfunction @@ -123,11 +124,11 @@ ROUTE_TYPE_MESH_TORI = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", - R2R_CHANELS_MESH_TORI= (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? 2 : 4, + R2R_CHANELS_MESH_TORI= (IS_RING || IS_LINE)? 2 : 4, R2E_CHANELS_MESH_TORI= NL, - RAw_MESH_TORI = ( TOPOLOGY == "RING" || TOPOLOGY == "LINE")? NXw : NXw + NYw, + RAw_MESH_TORI = ( IS_RING || IS_LINE)? NXw : NXw + NYw, EAw_MESH_TORI = (NL==1) ? RAw_MESH_TORI : RAw_MESH_TORI + NLw, - NR_MESH_TORI = (TOPOLOGY=="RING" || TOPOLOGY=="LINE")? NX : NX*NY, + NR_MESH_TORI = (IS_RING || IS_LINE)? NX : NX*NY, NE_MESH_TORI = NR_MESH_TORI * NL, MAX_P_MESH_TORI = R2R_CHANELS_MESH_TORI + R2E_CHANELS_MESH_TORI, DSTPw_MESH_TORI = R2R_CHANELS_MESH_TORI; // P-1 @@ -195,52 +196,52 @@ DSTPw_CUSTOM = log2(MAX_P_CUSTOM); /* verilator lint_off WIDTH */ localparam - PPSw = PPSw_MESH_TORI, + PPSw = PPSw_MESH_TORI, // maximum number of port in a router in the topology MAX_P = - (TOPOLOGY == "FATTREE")? MAX_P_FATTREE: - (TOPOLOGY == "TREE")? MAX_P_TREE: - (TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")? MAX_P_MESH_TORI: - (TOPOLOGY == "FMESH")? MAX_P_MESH_TORI: - (TOPOLOGY == "STAR") ? MAX_P_STAR: + (IS_FATTREE)? MAX_P_FATTREE: + (IS_TREE)? MAX_P_TREE: + (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? MAX_P_MESH_TORI: + (IS_FMESH)? MAX_P_MESH_TORI: + (IS_STAR) ? MAX_P_STAR: MAX_P_CUSTOM, - // destination port width in header flit + // destination port width in header flit DSTPw = // Each asserted bit indicats that the flit should be sent to that port - (TOPOLOGY == "FATTREE")? DSTPw_FATTREE: - (TOPOLOGY == "TREE")? DSTPw_TREE: + (IS_FATTREE)? DSTPw_FATTREE: + (IS_TREE)? DSTPw_TREE: (CAST_TYPE!= "UNICAST")? MAX_P: - (TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")? DSTPw_MESH_TORI: - (TOPOLOGY == "FMESH")? DSTPw_MESH_TORI: - (TOPOLOGY == "STAR") ? DSTPw_STAR: + (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? DSTPw_MESH_TORI: + (IS_FMESH)? DSTPw_MESH_TORI: + (IS_STAR) ? DSTPw_STAR: DSTPw_CUSTOM, - //router address width + //router address width RAw = - (TOPOLOGY == "FATTREE")? RAw_FATTREE: - (TOPOLOGY == "TREE")? RAw_TREE: - (TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")? RAw_MESH_TORI: - (TOPOLOGY == "FMESH")? RAw_MESH_TORI: - (TOPOLOGY == "STAR") ? RAw_STAR: + (IS_FATTREE)? RAw_FATTREE: + (IS_TREE)? RAw_TREE: + (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? RAw_MESH_TORI: + (IS_FMESH)? RAw_MESH_TORI: + (IS_STAR) ? RAw_STAR: RAw_CUSTOM, //endpoint address width EAw = - (TOPOLOGY == "FATTREE")? EAw_FATTREE: - (TOPOLOGY == "TREE")? EAw_TREE: - (TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")? EAw_MESH_TORI: - (TOPOLOGY == "FMESH")? EAw_FMESH: - (TOPOLOGY == "STAR") ? EAw_STAR: - EAw_CUSTOM, - // total number of endpoints + (IS_FATTREE)? EAw_FATTREE: + (IS_TREE)? EAw_TREE: + (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? EAw_MESH_TORI: + (IS_FMESH)? EAw_FMESH: + (IS_STAR) ? EAw_STAR: + EAw_CUSTOM, + // total number of endpoints NE = - (TOPOLOGY == "FATTREE")? NE_FATTREE: - (TOPOLOGY == "TREE")? NE_TREE: - (TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")? NE_MESH_TORI: - (TOPOLOGY == "FMESH")? NE_FMESH: - (TOPOLOGY == "STAR")? NE_STAR: + (IS_FATTREE)? NE_FATTREE: + (IS_TREE)? NE_TREE: + (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? NE_MESH_TORI: + (IS_FMESH)? NE_FMESH: + (IS_STAR)? NE_STAR: NE_CUSTOM, //Destination endpoint(s) address width - DAw_OFFSETw = (TOPOLOGY=="MESH" || TOPOLOGY=="TORUS" || TOPOLOGY=="FMESH")? NX : 0, + DAw_OFFSETw = (IS_MESH || IS_TORUS || IS_FMESH)? NX : 0, MCAST_PRTLw = mcast_partial_width( MCAST_ENDP_LIST), MCASTw = (CAST_TYPE == "MULTICAST_FULL") ? NE : @@ -249,24 +250,24 @@ EAw +1, //broadcast DAw = (CAST_TYPE == "UNICAST") ? EAw: - MCASTw + DAw_OFFSETw, - //total number of routers + MCASTw + DAw_OFFSETw, + //total number of routers NR = - (TOPOLOGY == "FATTREE")? NR_FATTREE: - (TOPOLOGY == "TREE")? NR_TREE: - (TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")? NR_MESH_TORI: - (TOPOLOGY == "FMESH")? NR_FMESH: - (TOPOLOGY == "STAR") ? NR_STAR: + (IS_FATTREE)? NR_FATTREE: + (IS_TREE)? NR_TREE: + (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? NR_MESH_TORI: + (IS_FMESH)? NR_FMESH: + (IS_STAR) ? NR_STAR: NR_CUSTOM, - //routing algorithm type + //routing algorithm type ROUTE_TYPE = - (TOPOLOGY == "FATTREE")? ROUTE_TYPE_FATTREE: - (TOPOLOGY == "TREE")? ROUTE_TYPE_TREE: - (TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")? ROUTE_TYPE_MESH_TORI: - (TOPOLOGY == "FMESH")? ROUTE_TYPE_MESH_TORI: - (TOPOLOGY == "STAR") ? ROUTE_TYPE_STAR: + (IS_FATTREE)? ROUTE_TYPE_FATTREE: + (IS_TREE)? ROUTE_TYPE_TREE: + (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? ROUTE_TYPE_MESH_TORI: + (IS_FMESH)? ROUTE_TYPE_MESH_TORI: + (IS_STAR) ? ROUTE_TYPE_STAR: ROUTE_TYPE_CUSTOM; - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ function automatic integer mcast_id_to_endp_id; input integer mcast_id; reg [NE-1 : 0] mcast_list; @@ -280,11 +281,11 @@ /* verilator lint_on WIDTH */ mcast_id_to_endp_id =mcast_id; end else begin - while( k!=mcast_id+1) begin + while( k!=mcast_id+1) begin if( mcast_list[mcast_id_to_endp_id]==1'b1) begin - k=k+1; + k=k+1; end - mcast_id_to_endp_id= mcast_id_to_endp_id+1; + mcast_id_to_endp_id= mcast_id_to_endp_id+1; end end end @@ -324,12 +325,12 @@ input integer in; integer y, x, l,p, diff,mul; begin - mul = NX*NY*NL; + mul = NX*NY*NL; if(in < mul) begin y = ((in/NL) / NX ); x = ((in/NL) % NX ); l = (in % NL); - p = (l==0)? LOCAL : 4+l; + p = (l==0)? LOCAL : 4+l; end else begin diff = in - mul ; if( diff < NX) begin //top mesh edge @@ -350,9 +351,9 @@ p = EAST; end end//else - fmesh_addrencode = ( p<<(NXw+NYw) | (y<. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: multi-chanel DMA-based network interface for +** Description: multi-chanel DMA-based network interface for ** handling packetizing/depacketizing data to/form NoC. ** Can support CRC32 -** +** ** *******************************************************************/ @@ -34,7 +34,7 @@ module ni_master - #( + #( parameter NOC_ID=0, parameter MAX_TRANSACTION_WIDTH=10, // Maximum transaction size will be 2 power of MAX_DMA_TRANSACTION_WIDTH words parameter MAX_BURST_SIZE =256, // in words @@ -43,7 +43,6 @@ module ni_master // The header Data pre capture width. It Will be enabled when it is larger than zero. The header data can optionally carry a short width Data. This data can be pre-captured (completely/partially) // by the NI before saving the packet in a memory buffer. This can give some hints to the software regarding the incoming // packet such as its type, or source port so the software can store the packet in its appropriate buffer. - //wishbone port parameters parameter Dw = 32, parameter S_Aw = 7, @@ -55,13 +54,11 @@ module ni_master //general reset, clk, - //noc interface current_r_addr, current_e_addr, chan_in, chan_out, - //wishbone slave interface signals s_dat_i, s_sel_i, @@ -72,7 +69,6 @@ module ni_master s_we_i, s_dat_o, s_ack_o, - //wishbone master rd interface signals m_send_sel_o, m_send_addr_o, @@ -82,7 +78,6 @@ module ni_master m_send_we_o, m_send_dat_i, m_send_ack_i, - //wishbone master wr interface signals m_receive_sel_o, m_receive_dat_o, @@ -92,28 +87,18 @@ module ni_master m_receive_cyc_o, m_receive_we_o, m_receive_ack_i, - //interrupt interface irq - ); - `NOC_CONF - - - +`NOC_CONF input reset,clk; - - - // NOC interfaces + // NOC interfaces input [RAw-1 : 0] current_r_addr; input [EAw-1 : 0] current_e_addr; - - input smartflit_chanel_t chan_in; - output smartflit_chanel_t chan_out; - - - //wishbone slave interface signals + input smartflit_chanel_t chan_in; + output smartflit_chanel_t chan_out; + //wishbone slave interface signals input [Dw-1 : 0] s_dat_i; input [SELw-1 : 0] s_sel_i; input [S_Aw-1 : 0] s_addr_i; @@ -134,7 +119,7 @@ module ni_master output m_send_we_o; input [Dw-1 : 0] m_send_dat_i; input m_send_ack_i; - + //wishbone write master interface signals output [SELw-1 : 0] m_receive_sel_o; output [Dw-1 : 0] m_receive_dat_o; @@ -145,14 +130,10 @@ module ni_master output m_receive_we_o; input m_receive_ack_i; - //Interrupt interface + //Interrupt interface output irq; - wire s_ack_o_next; - - - logic [Fw-1 : 0] flit_out; logic flit_out_wr; logic [V-1 : 0] credit_in; @@ -160,68 +141,55 @@ module ni_master logic flit_in_wr; logic [V-1 : 0] credit_out; - - assign chan_out.flit_chanel.flit = flit_out; + assign chan_out.flit_chanel.flit = flit_out; assign chan_out.flit_chanel.flit_wr = flit_out_wr; assign chan_out.flit_chanel.credit = credit_out; - - assign flit_in = chan_in.flit_chanel.flit; assign flit_in_wr= chan_in.flit_chanel.flit_wr; assign credit_in = chan_in.flit_chanel.credit; //old ni.v file - localparam CTRL_FLGw=14, CHw=log2(V), BURST_SIZE_w= log2(MAX_BURST_SIZE+1), STATUS1w= 2 * CHw + 4; - /* Wishbone bus slave address : - - VC specific registers - address bits - [4+Vw:4] [3:0] +VC specific registers + address bits + [4+Vw:4] [3:0] 1 : CTRL_FLAGS : {invalid_send_req_err,burst_size_err_isr,send_data_size_err_isr,crc_miss_match_isr,rcive_buff_ovrflw_err_isr,got_packet_isr, packet_is_saved_isr, packet_is_sent_isr,got_any_errorint_en,got_packet_int_en, packet_is_saved_int_en, packet_is_sent_int_en,receive_is_busy, send_is_busy}; - 2 : SEND_DEST_WB_ADDR // The destination router address 3 : SEND_POINTER_WB_ADDR, // The address of data to be sent in byte - Virtual 4 : SEND_DATA_SIZE, // The size of data to be sent in byte - chanel 5 : SEND_HDR_DATA // The short width data that can be sent by header flit - number - 8 : RECEIVE_SRC_WB_ADDR // The source router (the router which is sent this packet). + Virtual 4 : SEND_DATA_SIZE, // The size of data to be sent in byte + chanel 5 : SEND_HDR_DATA // The short width data that can be sent by header flit + number 8 : RECEIVE_SRC_WB_ADDR // The source router (the router which is sent this packet). 9 : RECEIVE_POINTER_WB_ADDR // The address pointer of receiver memory in byte 10 : RECEIVE_DATA_SIZE_WB_ADDR // The size of received data in byte 11 : RECEIVE_MAX_BUFF_SIZ // The receiver allocated buffer size in words. If the packet size is bigger than the buffer size the rest of it will be discarded 12 : RECEIVE_START_INDEX_WB_ADDR // The received data is written on RECEIVE_POINTER_WB_ADDR + RECEIVE_START_INDEX_WB_ADDR. If the write address reach to the end of buffer pointer, it starts at the RECEIVE_POINTER_WB_ADDR. 13 : RECEIVE_CTRL_WB_ADDR // The NI receiver control register 14 : RECEIVE_PRECAP_DATA_ADDR // The port address to the header flit data which can be pre-captured before buffering the actual data. - - Shared registers for all VCs - address bits - [5:0] - 0: STATUS_WB_ADDR // status1: {send_vc_enable_binary, receive_vc_enable_binary, any_err_isr_en,any_got_packet_isr_en,any_packet_is_saved_isr_en,any_packet_is_sent_isr_en} - 16: BURST_SIZE_WB_ADDR // The burst size in words - 32: reserved - +Shared registers for all VCs + address bits + [5:0] + 0: STATUS_WB_ADDR // status1: {send_vc_enable_binary, receive_vc_enable_binary, any_err_isr_en,any_got_packet_isr_en,any_packet_is_saved_isr_en,any_packet_is_sent_isr_en} + 16: BURST_SIZE_WB_ADDR // The burst size in words + 32: reserved */ localparam chanel_ADDRw= 4, chanel_REGw = 4, GENRL_ADRw=2; - - wire [CHw-1 : 0] vc_addr = s_addr_i [chanel_REGw+CHw-1 : chanel_REGw]; + wire [CHw-1 : 0] vc_addr = s_addr_i [chanel_REGw+CHw-1 : chanel_REGw]; wire [GENRL_ADRw-1 : 0] genrl_reg_addr = s_addr_i [chanel_REGw+GENRL_ADRw-1 : chanel_REGw]; wire [chanel_ADDRw-1 : 0] vc_s_addr_i = s_addr_i [chanel_ADDRw-1: 0]; - //general registers localparam [GENRL_ADRw-1 : 0] STATUS1_WB_ADDR = 0, // status1 - // STATUS2_WB_ADDR = 1, // status2 - // STATUS3_WB_ADDR = 3, // status3 - BURST_SIZE_WB_ADDR = 1; - + //STATUS2_WB_ADDR = 1, // status2 + //STATUS3_WB_ADDR = 3, // status3 + BURST_SIZE_WB_ADDR = 1; //Readonly registers per VC localparam [chanel_ADDRw-1 : 0] GENERAL_REGS_WB_ADDR=0, @@ -229,17 +197,13 @@ module ni_master RECEIVE_SRC_WB_ADDR =8, // The source router (the router which is sent this packet). RECEIVE_DATA_SIZE_WB_ADDR = 10, // The size of received data in byte RECEIVE_PRECAP_DATA_ADDR=14; - - localparam WORLD_SIZE = Dw/8, OFFSETw= log2(WORLD_SIZE), HDw = Fpay - (2*EAw) - DSTPw - WEIGHTw, PRE_Dw = (HDATA_PRECAPw>0)? HDATA_PRECAPw : 1, MAX_PCK_SIZE_IN_BYTE = MAX_TRANSACTION_WIDTH + log2(Fpay/8); - - - + reg [BURST_SIZE_w-1 : 0] burst_size, burst_size_next,burst_counter,burst_counter_next; wire [V-1 : 0] receive_vc_is_busy, send_vc_is_busy; wire [V-1 : 0] receive_vc_enable,send_vc_enable,vc_state_reg_enable; @@ -270,9 +234,6 @@ module ni_master wire [MAX_TRANSACTION_WIDTH-1 : 0] receive_vc_max_buff_siz [V-1 : 0]; wire [MAX_TRANSACTION_WIDTH-1 : 0] receive_vc_start_index [V-1 : 0]; wire [OFFSETw-1 : 0] receive_vc_start_index_offset [V-1 : 0]; - - - wire [V-1 : 0] send_vc_start, receive_vc_start; wire received_flit_is_tail,received_flit_is_hdr; wire [EAw-1 : 0] vc_dest_e_addr [V-1 : 0]; @@ -282,7 +243,6 @@ module ni_master wire [HDw-1 : 0] vc_hdr_data [V-1:0]; wire [V-1 : 0] send_vc_send_hdr,send_vc_send_tail; wire [V-1 : 0] send_vc_done,receive_vc_done; - wire [EAw-1 : 0] dest_e_addr; wire [Cw-1 : 0] pck_class; wire [BEw-1 : 0 ] be_in; @@ -292,11 +252,6 @@ module ni_master wire burst_counter_dec= | vc_burst_counter_dec; wire fifo_wr = | vc_fifo_wr; wire fifo_rd = | vc_fifo_rd; - - - - - wire last_burst = (burst_counter == 1); wire burst_is_set = (burst_size>0); wire [Cw-1 : 0] received_class_next; @@ -310,23 +265,16 @@ module ni_master reg [BEw-1 : 0] receive_vc_be [V-1 : 0]; wire [CTRL_FLGw-1 : 0] vc_ctrl_flags [V-1 : 0]; reg [V-1 : 0] crc_miss_match; - wire [V-1 : 0] burst_size_err,send_data_size_err,rcive_buff_ovrflw_err; wire [V-1 : 0] invalid_send_req_err; - wire [V-1 : 0] vc_irq; - - - - wire [STATUS1w-1 :0] status1; - // wire [STATUS2w-1 :0] status2; - // wire [STATUS3w-1 :0] status3; - + wire [STATUS1w-1 :0] status1; + // wire [STATUS2w-1 :0] status2; + // wire [STATUS3w-1 :0] status3; wire [DSTPw-1 : 0] destport; wire [WEIGHTw-1 : 0] weight; wire [HDw-1 : 0 ] hdr_data; - wire [V-1 :0] vc_any_err_isr ; wire [V-1 :0] vc_got_packet_isr ; wire [V-1 :0] vc_packet_is_saved_isr; @@ -338,21 +286,16 @@ module ni_master assign any_got_packet_isr = | vc_got_packet_isr ; assign any_packet_is_saved_isr = | vc_packet_is_saved_isr; assign any_packet_is_sent_isr = | vc_packet_is_sent_isr; - // assign status1= {vc_got_error_isr, receive_vc_got_packet_isr, receive_vc_packet_is_saved_isr, send_vc_packet_is_sent_isr}; - // assign status2= {vc_got_error_int_en, receive_vc_got_packet_int_en, receive_vc_packet_is_saved_int_en, send_vc_packet_is_sent_int_en}; + // assign status1= {vc_got_error_isr, receive_vc_got_packet_isr, receive_vc_packet_is_saved_isr, send_vc_packet_is_sent_isr}; + // assign status2= {vc_got_error_int_en, receive_vc_got_packet_int_en, receive_vc_packet_is_saved_int_en, send_vc_packet_is_sent_int_en}; assign status1= {send_vc_enable_binary, receive_vc_enable_binary, any_err_isr,any_got_packet_isr,any_packet_is_saved_isr,any_packet_is_sent_isr}; - - assign irq =|vc_irq; - wire [7: 0] temp; generate if (HDw >= 8) assign temp = rsv_hdr_dat [vc_addr][7:0]; else assign temp = {{(8-HDw){1'b0}},rsv_hdr_dat [vc_addr]}; endgenerate - - - //read wb registers + //read wb registers always @(*)begin s_dat_o ={Dw{1'b0}}; case(vc_s_addr_i) @@ -365,17 +308,15 @@ module ni_master s_dat_o = {{(Dw-BURST_SIZE_w){1'b0}}, burst_size}; end default: begin - s_dat_o ={Dw{1'b0}}; + s_dat_o ={Dw{1'b0}}; end endcase end//0 - + CTRL_FLAGS_WB_ADDR: begin - s_dat_o[CTRL_FLGw-1 : 0] = vc_ctrl_flags[vc_addr]; + s_dat_o[CTRL_FLGw-1 : 0] = vc_ctrl_flags[vc_addr]; end - RECEIVE_SRC_WB_ADDR: begin - s_dat_o[EAw-1: 0] = src_e_addr[vc_addr]; // first&second bytes s_dat_o[Cw+15: 16] = class_in[vc_addr]; //third byte s_dat_o[31: 24] = temp; // 4th byte @@ -383,19 +324,15 @@ module ni_master RECEIVE_DATA_SIZE_WB_ADDR: begin s_dat_o [MAX_PCK_SIZE_IN_BYTE-1 : 0] = receive_dat_size_in_byte[vc_addr]; - end - + end RECEIVE_PRECAP_DATA_ADDR: begin - s_dat_o[PRE_Dw-1 : 0 ] = (HDATA_PRECAPw>0)? recive_vc_precap_data[vc_addr][PRE_Dw-1 : 0 ]: {{PRE_Dw{1'b0}}}; + s_dat_o[PRE_Dw-1 : 0 ] = (HDATA_PRECAPw>0)? recive_vc_precap_data[vc_addr][PRE_Dw-1 : 0 ]: {{PRE_Dw{1'b0}}}; end default: begin - s_dat_o ={Dw{1'b0}}; - end - endcase - end - - - + s_dat_o ={Dw{1'b0}}; + end + endcase + end //write wb registers always @ (*)begin @@ -403,82 +340,59 @@ module ni_master burst_size_next= burst_size; if(burst_counter_ld) burst_counter_next = burst_size; if(burst_counter_dec) burst_counter_next= burst_counter- 1'b1; - if((s_stb_i & s_we_i) && (vc_s_addr_i == GENERAL_REGS_WB_ADDR)) begin // This is a general address. check the general address filed case(genrl_reg_addr) BURST_SIZE_WB_ADDR: begin if (send_vc_is_busy == {V{1'b0}}) burst_size_next=s_dat_i [BURST_SIZE_w-1 : 0]; end //BURST_SIZE_WB_ADDR - - default begin - - end + default begin + + end endcase - end// if(s_stb_i & s_we_i) - + end// if(s_stb_i & s_we_i) end - - - - -`ifdef SYNC_RESET_MODE + `ifdef SYNC_RESET_MODE always @ (posedge clk )begin -`else + `else always @ (posedge clk or posedge reset)begin -`endif - - - + `endif if(reset) begin burst_counter <= {BURST_SIZE_w{1'b0}}; burst_size <= {BURST_SIZE_w{1'b1}}; s_ack_o <= 1'b0; - - end else begin burst_counter<= burst_counter_next; burst_size <= burst_size_next; s_ack_o <= s_ack_o_next; - - end end - bin_to_one_hot #( .BIN_WIDTH(CHw), .ONE_HOT_WIDTH(V) - ) - convert - ( + ) convert ( .bin_code(vc_addr), .one_hot_code(vc_state_reg_enable) - ); - - assign s_ack_o_next = s_stb_i & (~s_ack_o); + ); + assign s_ack_o_next = s_stb_i & (~s_ack_o); genvar i; generate - wire [V-1 : 0 ] precap_hdr_flit_wr; - wire [HDATA_PRECAPw-1 : 0 ] precap_din; - wire [V-1 : 0] precap_hdr_flit_rd = (fifo_rd & received_flit_is_hdr) ? receive_vc_enable : {V{1'b0}}; - wire [HDATA_PRECAPw-1 : 0 ] precap_dout [V-1 : 0] ; - wire [V-1 : 0 ] precap_valid; + wire [V-1 : 0 ] precap_hdr_flit_wr; + wire [HDATA_PRECAPw-1 : 0 ] precap_din; + wire [V-1 : 0] precap_hdr_flit_rd = (fifo_rd & received_flit_is_hdr) ? receive_vc_enable : {V{1'b0}}; + wire [HDATA_PRECAPw-1 : 0 ] precap_dout [V-1 : 0] ; + wire [V-1 : 0 ] precap_valid; - //capture data before saving the actual flit in memory if(HDATA_PRECAPw > 0 ) begin : precap - wire [EAw-1 : 0] src_endp_addr; - extract_header_flit_info #( .NOC_ID(NOC_ID), .DATA_w(HDATA_PRECAPw) - ) - data_extractor - ( + ) data_extractor ( .flit_in(flit_in), .flit_in_wr(flit_in_wr), .src_e_addr_o(src_endp_addr ), @@ -493,90 +407,57 @@ module ni_master .hdr_flit_wr_o(precap_hdr_flit_wr), .data_o(precap_din) ); - - -//synthesis translate_off -//synopsys translate_off -`ifdef MONITOR_HDR_FLITS -always @(posedge clk) begin - - if(precap_hdr_flit_wr)begin - $display("%t: endp %d got a packet with port address %d from endp %d",$time,current_e_addr,precap_din,src_endp_addr); - end - - if(send_hdr & flit_out_wr)begin - $display("%t: endp %d sends a packet with port address %d to endp %d",$time,current_e_addr,hdr_data,dest_e_addr); - end - - -end -`endif + `ifdef SIMULATION + `ifdef MONITOR_HDR_FLITS + always @(posedge clk) begin + if(precap_hdr_flit_wr)begin + $display("%t: endp %d got a packet with port address %d from endp %d",$time,current_e_addr,precap_din,src_endp_addr); + end -`ifdef MONITOR_DAT_FLITS - always @(posedge clk) begin - if(flit_out_wr & ~send_hdr) begin - $display("%t: endp %u V %u sends %h",$time,current_e_addr, flit_out [Fpay+V-1 : Fpay], flit_out [Fpay-1 : 0 ]); + if(send_hdr & flit_out_wr)begin + $display("%t: endp %d sends a packet with port address %d to endp %d",$time,current_e_addr,hdr_data,dest_e_addr); + end end - end -`endif - -//synopsys translate_on -//synthesis translate_on - - - - for (i=0;i 1) begin : multi_chanel - // round roubin arbiter bus_arbiter # ( .M (V) - ) - receive_arbiter - ( + ) receive_arbiter ( .request (receive_vc_is_active), .grant (receive_vc_enable), .clk (clk), .reset (reset) ); - + bus_arbiter # ( .M (V) - ) - send_arbiter - ( + ) send_arbiter ( .request (send_vc_is_active), .grant (send_vc_enable), .clk (clk), .reset (reset) ); - one_hot_to_bin #( .ONE_HOT_WIDTH(V), .BIN_WIDTH(CHw) - ) - send_en_conv - ( + ) send_en_conv ( .one_hot_code(send_vc_enable), .bin_code(send_vc_enable_binary) ); - - - one_hot_to_bin #( + one_hot_to_bin #( .ONE_HOT_WIDTH(V), .BIN_WIDTH(CHw) - ) - receive_en_conv - ( + ) receive_en_conv ( .one_hot_code(receive_vc_enable), .bin_code(receive_vc_enable_binary) ); - - + end else begin : single_chanel // if we have just one chanel there is no need for arbitration assign receive_vc_enable = receive_vc_is_active; assign send_vc_enable = send_vc_is_active; @@ -875,9 +711,7 @@ end assign receive_vc_enable_binary = 1'b0; end endgenerate - - - + conventional_routing #( .NOC_ID(NOC_ID), .TOPOLOGY(TOPOLOGY), @@ -888,6 +722,7 @@ end .T3(T3), .RAw(RAw), .EAw(EAw), + .DAw(DAw), .DSTPw(DSTPw), .LOCATED_IN_NI(1) ) route_compute ( @@ -898,8 +733,7 @@ end .dest_e_addr(dest_e_addr), .destport(destport) ); - - + header_flit_generator #( .NOC_ID(NOC_ID), .DATA_w(HDw) @@ -915,25 +749,22 @@ end .data_in(hdr_data) ); - wire [V-1 : 0] wr_vc_send = (fifo_wr) ? send_vc_enable : {V{1'b0}}; - - - ovc_status #( - .V(V), - .B(LB), - .CRDTw(CRDTw) - ) - the_ovc_status - ( - .credit_init_val_in ( chan_in.ctrl_chanel.credit_init_val), - .wr_in(wr_vc_send), - .credit_in(credit_in), - .full_vc(vc_fifo_full), - .nearly_full_vc(vc_fifo_nearly_full), - .empty_vc( ), - .clk(clk), - .reset(reset) - ); + wire [V-1 : 0] wr_vc_send = (fifo_wr) ? send_vc_enable : {V{1'b0}}; + + ovc_status #( + .V(V), + .B(LB), + .CRDTw(CRDTw) + ) the_ovc_status ( + .credit_init_val_in ( chan_in.ctrl_chanel.credit_init_val), + .wr_in(wr_vc_send), + .credit_in(credit_in), + .full_vc(vc_fifo_full), + .nearly_full_vc(vc_fifo_nearly_full), + .empty_vc( ), + .clk(clk), + .reset(reset) + ); // header info mux assign dest_e_addr = vc_dest_e_addr[send_vc_enable_binary]; @@ -958,31 +789,24 @@ end assign m_receive_stb_o = vc_m_receive_stb_o[receive_vc_enable_binary]; assign m_receive_cyc_o = vc_m_receive_cyc_o[receive_vc_enable_binary]; assign m_receive_we_o = vc_m_receive_we_o[receive_vc_enable_binary]; - + wire [V-1 : 0] flit_in_vc_num = flit_in [Fpay+V-1 : Fpay]; wire [V-1 : 0] ififo_vc_not_empty; assign vc_fifo_empty = ~ ififo_vc_not_empty; assign receive_vc_got_packet = ififo_vc_not_empty; assign receive_vc_got_hdr_flit_at_head= ififo_vc_not_empty & receive_vc_fsm_is_ideal; - - - wire [Fw-1 : 0] fifo_dout; - localparam LBw = log2(LB); - flit_buffer #( .V(V), .B(LB), .SSA_EN("NO"), .Fw(Fw), - .PCK_TYPE(PCK_TYPE), - .CAST_TYPE(CAST_TYPE), - .DEBUG_EN(DEBUG_EN) - ) - the_ififo - ( + .PCK_TYPE(PCK_TYPE), + .CAST_TYPE(CAST_TYPE), + .DEBUG_EN(DEBUG_EN) + ) the_ififo ( .din(flit_in), // Data in .vc_num_wr(flit_in_vc_num),//write virtual chanel .wr_en(flit_in_wr), // Write enable @@ -997,12 +821,10 @@ end .sub_rd_ptr_ld() ); - extract_header_flit_info #( + extract_header_flit_info #( .NOC_ID(NOC_ID), .DATA_w (HDw) - ) - extractor - ( + ) extractor ( .flit_in(fifo_dout), .flit_in_wr(), .class_o(received_class_next), @@ -1017,43 +839,34 @@ end .be_o(received_be_next), .data_o(received_hdr_dat_next) ); - - - - assign m_receive_dat_o = fifo_dout[Dw-1 : 0]; - assign received_flit_is_tail = fifo_dout[Fw-2]; - assign received_flit_is_hdr = fifo_dout[Fw-1]; -// assign any_vc_got_pck = |receive_vc_got_packet; - + assign m_receive_dat_o = fifo_dout[Dw-1 : 0]; + assign received_flit_is_tail = fifo_dout[Fw-2]; + assign received_flit_is_hdr = fifo_dout[Fw-1]; + // assign any_vc_got_pck = |receive_vc_got_packet; localparam [1:0] HDR_FLAG = 2'b10, BDY_FLAG = 2'b00, TAIL_FLAG = 2'b01; - - assign credit_out = vc_fifo_rd; - assign flit_out_wr= fifo_wr; - assign flit_out [Fpay+V-1 : Fpay] = send_vc_enable; - assign flit_out [Fpay-1 : 0 ] = (send_hdr)? hdr_flit_out [Fpay-1 : 0] : - (send_tail)? tail_flit_out : m_send_dat_i [Fpay-1 : 0]; - assign flit_out [Fw-1 : Fw-2] = (send_hdr)? HDR_FLAG : - (send_tail)? TAIL_FLAG : BDY_FLAG; + assign credit_out = vc_fifo_rd; + assign flit_out_wr= fifo_wr; + assign flit_out [Fpay+V-1 : Fpay] = send_vc_enable; + assign flit_out [Fpay-1 : 0 ] = (send_hdr)? hdr_flit_out [Fpay-1 : 0] : + (send_tail)? tail_flit_out : m_send_dat_i [Fpay-1 : 0]; + assign flit_out [Fw-1 : Fw-2] = (send_hdr)? HDR_FLAG : + (send_tail)? TAIL_FLAG : BDY_FLAG; endmodule - - - + /****************** * ovc_status *******************/ - + module ovc_status #( parameter V = 4, parameter B = 16, parameter CRDTw =4 -) -( - - input [V-1 : 0] [CRDTw-1 : 0 ] credit_init_val_in, - input [V-1 :0] wr_in, +)( + input [V-1 : 0] [CRDTw-1 : 0 ] credit_init_val_in, + input [V-1 :0] wr_in, input [V-1 :0] credit_in, output [V-1 :0] full_vc, output [V-1 :0] nearly_full_vc, @@ -1062,45 +875,35 @@ endmodule input reset ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 Date: Wed, 12 Mar 2025 16:15:34 +0100 Subject: [PATCH 015/107] remove thermo_gen module and generate output in always block --- mpsoc/rtl/arbiter.v | 342 +++--- .../jtag_ram_test/src_verilog/lib/arbiter.v | 976 +++++++----------- 2 files changed, 529 insertions(+), 789 deletions(-) diff --git a/mpsoc/rtl/arbiter.v b/mpsoc/rtl/arbiter.v index 87a34f3..5c5af0b 100755 --- a/mpsoc/rtl/arbiter.v +++ b/mpsoc/rtl/arbiter.v @@ -43,11 +43,11 @@ module arbiter #( grant, any_grant ); - input [ARBITER_WIDTH-1 : 0] request; - output [ARBITER_WIDTH-1 : 0] grant; - output any_grant; - input clk; - input reset; + input [ARBITER_WIDTH-1 : 0] request; + output [ARBITER_WIDTH-1 : 0] grant; + output any_grant; + input clk; + input reset; generate if(ARBITER_WIDTH==1) begin: w1 @@ -95,12 +95,12 @@ module arbiter_priority_en #( any_grant, priority_en ); - input [ARBITER_WIDTH-1 : 0] request; - output [ARBITER_WIDTH-1 : 0] grant; - output any_grant; - input clk; - input reset; - input priority_en; + input [ARBITER_WIDTH-1 : 0] request; + output [ARBITER_WIDTH-1 : 0] grant; + output any_grant; + input clk; + input reset; + input priority_en; generate if(ARBITER_WIDTH==1) begin: w1 @@ -145,28 +145,28 @@ endmodule module my_one_hot_arbiter #( parameter ARBITER_WIDTH =4 )( - input [ARBITER_WIDTH-1 : 0] request, - output [ARBITER_WIDTH-1 : 0] grant, - output any_grant, - input clk, - input reset + input [ARBITER_WIDTH-1 : 0] request, + output [ARBITER_WIDTH-1 : 0] grant, + output any_grant, + input clk, + input reset ); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** ** -** Description: -** This file contains several Fixed prority and round robin -** arbiters +** Description: +** This file contains several Fixed prority and round robin +** arbiters ** ******************************************************************************/ /***************************************** -* * general round robin arbiter -* -* ******************************************/ +`ifndef PRONOC_ARBITER +`define PRONOC_ARBITER module arbiter #( parameter ARBITER_WIDTH =8 - -) -( - clk, - reset, - request, - grant, - any_grant +)( + clk, + reset, + request, + grant, + any_grant ); - + input [ARBITER_WIDTH-1 : 0] request; + output [ARBITER_WIDTH-1 : 0] grant; + output any_grant; + input clk; + input reset; - input [ARBITER_WIDTH-1 : 0] request; - output [ARBITER_WIDTH-1 : 0] grant; - output any_grant; - input clk; - input reset; - - - generate if(ARBITER_WIDTH==1) begin: w1 assign grant= request; @@ -64,23 +57,18 @@ module arbiter #( //my own arbiter my_one_hot_arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), .grant (grant), .any_grant (any_grant) ); - end else begin : wb4 thermo_arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), @@ -97,30 +85,22 @@ endmodule * RRA with external priority enable signal * ******************************************/ - module arbiter_priority_en #( - parameter ARBITER_WIDTH =8 - -) -( - clk, - reset, - request, - grant, - any_grant, - priority_en + parameter ARBITER_WIDTH =8 +)( + clk, + reset, + request, + grant, + any_grant, + priority_en ); - - - - - input [ARBITER_WIDTH-1 : 0] request; - output [ARBITER_WIDTH-1 : 0] grant; - output any_grant; - input clk; - input reset; - input priority_en; - + input [ARBITER_WIDTH-1 : 0] request; + output [ARBITER_WIDTH-1 : 0] grant; + output any_grant; + input clk; + input reset; + input priority_en; generate if(ARBITER_WIDTH==1) begin: w1 @@ -130,25 +110,19 @@ module arbiter_priority_en #( //my own arbiter my_one_hot_arbiter_priority_en #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), .grant (grant), .any_grant (any_grant), .priority_en (priority_en) - ); - end else begin :wb4 thermo_arbiter_priority_en #( .ARBITER_WIDTH (ARBITER_WIDTH) - ) - one_hot_arb - ( + ) one_hot_arb ( .clk (clk), .reset (reset), .request (request), @@ -161,657 +135,457 @@ endgenerate endmodule - /****************************************************** -* my_one_hot_arbiter +* my_one_hot_arbiter * RRA with binary-coded priority register. Binary-coded * Priority results in less area cost and CPD for arbire * width of 4 and smaller only. * ******************************************************/ - - - module my_one_hot_arbiter #( parameter ARBITER_WIDTH =4 - - -) -( - input [ARBITER_WIDTH-1 : 0] request, - output [ARBITER_WIDTH-1 : 0] grant, - output any_grant, - input clk, - input reset +)( + input [ARBITER_WIDTH-1 : 0] request, + output [ARBITER_WIDTH-1 : 0] grant, + output any_grant, + input clk, + input reset ); - + function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 Date: Wed, 12 Mar 2025 18:51:11 +0100 Subject: [PATCH 016/107] change class_table to ovc list --- mpsoc/rtl/src_noc/class_table.v | 104 ---------------------------- mpsoc/rtl/src_noc/input_ports.sv | 18 ++--- mpsoc/rtl/src_noc/noc_filelist.f | 2 +- mpsoc/rtl/src_noc/ovc_list.sv | 113 +++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 114 deletions(-) delete mode 100755 mpsoc/rtl/src_noc/class_table.v create mode 100755 mpsoc/rtl/src_noc/ovc_list.sv diff --git a/mpsoc/rtl/src_noc/class_table.v b/mpsoc/rtl/src_noc/class_table.v deleted file mode 100755 index 9bae283..0000000 --- a/mpsoc/rtl/src_noc/class_table.v +++ /dev/null @@ -1,104 +0,0 @@ -`include "pronoc_def.v" -/********************************************************************** -** File: class_table.v -** -** Copyright (C) 2014-2017 Alireza Monemi -** -** This file is part of ProNoC -** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. -** -** ProNoC 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 Lesser General -** Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . -** -** -** Description: -** -*************************************/ - - -module class_ovc_table #( - parameter C= 4,//number of class - parameter V= 4, //VC number per port - parameter CVw=(C==0)? V : C * V, - parameter [CVw-1: 0] CLASS_SETTING = {CVw{1'b1}} // shows how each class can use VCs - )( - class_in, - candidate_ovcs - ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21)? log2(C): 1; - - input [Cw-1 : 0] class_in; - output[V-1 : 0] candidate_ovcs; - - genvar i; - generate - if(C == 0 || C == 1) begin: no_class - assign candidate_ovcs={V{1'b1}}; - end else begin: width_class - - wire [V-1 : 0] class_table [C-1 : 0]; - for(i=0;i V )begin :b2 - for (i=0;i. +** +** +** Description: +** This module provides a list of available output VCs for the allocator +*************************************/ +module ovc_list #( + parameter SW_LOC=0, + parameter IVC_NUM=0, + parameter P=5 +)( + class_in, + destport_one_hot, + ovcs_out +); + `NOC_CONF + + input [Cw-1 : 0] class_in; + input [P-1 : 0] destport_one_hot; + output[V-1 : 0] ovcs_out; + + function automatic logic [V-1:0] get_vc_list_section(input int c); + begin + logic [CVw-1 : 0] shiftted = CLASS_SETTING >> c*V; + return shiftted[V-1 : 0]; + end + endfunction + + //Masks VCs acording to message classes + logic [V-1 : 0] class_table [C-1 : 0]; + logic [V-1 : 0] ovc_message_class, ovc_topology; + always_comb begin + for(int i=0; i V )begin :b2 + for (i=0;i Date: Thu, 13 Mar 2025 22:28:09 +0100 Subject: [PATCH 017/107] remove extra spaces --- mpsoc/perl_gui/lib/perl/compile.pl | 1 - mpsoc/perl_gui/lib/perl/diagram.pl | 60 +- mpsoc/perl_gui/lib/perl/drag_drop.pl | 50 +- mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl | 780 ++- mpsoc/perl_gui/lib/perl/emulator.pl | 492 +- mpsoc/perl_gui/lib/perl/emulator.pm | 135 +- mpsoc/perl_gui/lib/perl/gdown.pl | 128 +- mpsoc/perl_gui/lib/perl/graph.pl | 1914 +++---- mpsoc/perl_gui/lib/perl/hdr_file_gen.pl | 299 +- mpsoc/perl_gui/lib/perl/interface.pm | 418 +- mpsoc/perl_gui/lib/perl/interface_gen.pl | 1158 ++-- mpsoc/perl_gui/lib/perl/intfc_gen.pm | 111 +- mpsoc/perl_gui/lib/perl/ip.pm | 670 +-- mpsoc/perl_gui/lib/perl/ip_gen.pl | 3003 ++++------ mpsoc/perl_gui/lib/perl/ip_gen.pm | 901 ++- mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl | 1552 +++--- mpsoc/perl_gui/lib/perl/network_maker.pl | 4941 +++++++---------- mpsoc/perl_gui/lib/perl/orcc.pl | 2400 ++++---- mpsoc/perl_gui/lib/perl/phy_noc_gen.pl | 119 +- mpsoc/perl_gui/lib/perl/readme_gen.pl | 66 +- .../perl_gui/lib/perl/run_time_jtag_debug.pl | 1437 ++--- mpsoc/perl_gui/lib/perl/soc_gen.pl | 3124 +++++------ mpsoc/perl_gui/lib/perl/software_editor.pl | 1520 +++-- mpsoc/perl_gui/lib/perl/sv_parser.pl | 23 +- mpsoc/perl_gui/lib/perl/temp.pl | 34 +- mpsoc/perl_gui/lib/perl/topology.pl | 1227 ++-- .../perl_gui/lib/perl/topology_verilog_gen.pl | 57 +- mpsoc/perl_gui/lib/perl/trace_gen.pl | 3283 +++++------ mpsoc/perl_gui/lib/perl/traffic_pattern.pl | 358 +- mpsoc/perl_gui/lib/perl/tsort.pm | 53 +- mpsoc/perl_gui/lib/perl/uart.pl | 1185 ++-- mpsoc/perl_gui/lib/perl/verilog_gen.pl | 2091 +++---- mpsoc/perl_gui/lib/perl/widget.pl | 12 +- mpsoc/perl_gui/lib/perl/widget2.pl | 2855 ++++------ mpsoc/perl_gui/lib/perl/widget3.pl | 3118 +++++------ .../src_topology/common/custom_lkh_routing.v | 81 +- .../rtl/src_topology/common/custom_noc_top.sv | 78 +- .../Tcustom1Rcustom_conventional_routing.v | 568 +- ...stom1Rcustom_conventional_routing_genvar.v | 704 ++- .../Tcustom1Rcustom_look_ahead_routing.v | 800 ++- ...custom1Rcustom_look_ahead_routing_genvar.v | 823 ++- mpsoc/rtl/src_topology/custom1/custom1.png | Bin 137543 -> 103874 bytes mpsoc/rtl/src_topology/custom1/custom1_noc.h | 103 - mpsoc/rtl/src_topology/custom1/custom1_noc.sv | 924 ++- .../custom1/custom1_noc_genvar.sv | 473 +- mpsoc/rtl/src_topology/custom_flist.f | 12 +- mpsoc/rtl/src_topology/param.obj | 51 +- .../topology/custom/custom1_noc.h | 232 +- 48 files changed, 18823 insertions(+), 25601 deletions(-) delete mode 100644 mpsoc/rtl/src_topology/custom1/custom1_noc.h diff --git a/mpsoc/perl_gui/lib/perl/compile.pl b/mpsoc/perl_gui/lib/perl/compile.pl index a974f10..70a9380 100644 --- a/mpsoc/perl_gui/lib/perl/compile.pl +++ b/mpsoc/perl_gui/lib/perl/compile.pl @@ -2564,7 +2564,6 @@ sub verilator_testbench{ $window->destroy; verilator_compilation_win($self,$name,$top,$target_dir,$vendor); }); - $regen-> signal_connect("clicked" => sub{ my $response = yes_no_dialog("Are you sure you want to regenerate the testbench.cpp file? Note that any changes you have made will be lost"); if ($response eq 'yes') { diff --git a/mpsoc/perl_gui/lib/perl/diagram.pl b/mpsoc/perl_gui/lib/perl/diagram.pl index 319b120..2236c55 100644 --- a/mpsoc/perl_gui/lib/perl/diagram.pl +++ b/mpsoc/perl_gui/lib/perl/diagram.pl @@ -2,15 +2,12 @@ use constant::boolean; use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - use soc; require "widget.pl"; require "emulator.pl"; use File::Copy; - use Chart::Gnuplot; @@ -20,13 +17,11 @@ sub get_dot_file{ my $remove_clk = $self->object_get_attribute("tile_diagram","show_clk"); my $remove_reset = $self->object_get_attribute("tile_diagram","show_reset"); my $remove_unused = $self->object_get_attribute("tile_diagram","show_unused"); - my $dotfile= "digraph G { graph [rankdir = LR , splines=polyline, overlap = false]; node[shape=record]; "; - my @all_instances=$self->soc_get_all_instances(); #print "@all_instances\n"; my $graph_connect= ''; @@ -40,10 +35,7 @@ sub get_dot_file{ my @sockets= $self->soc_get_all_sockets_of_an_instance($instance_id); @sockets = remove_scolar_from_array(\@sockets,'clk') if ($remove_clk); @sockets = remove_scolar_from_array(\@sockets,'reset') if ($remove_reset); - - foreach my $socket (@sockets){ - my @nums=$self->soc_list_socket_nums($instance_id,$socket); foreach my $num (@nums){ my $name= $self->soc_get_socket_name ($instance_id,$socket,$num); @@ -66,21 +58,17 @@ sub get_dot_file{ } } - $dotfile=($first)? "$dotfile $instance_name" : "$dotfile}|$instance_name"; $first=1; my @plugs= $self->soc_get_all_plugs_of_an_instance($instance_id); @plugs = remove_scolar_from_array(\@plugs,'clk') if ($remove_clk); @plugs = remove_scolar_from_array(\@plugs,'reset') if ($remove_reset); - my %plug_order; my @noconnect; foreach my $plug (@plugs){ - my @nums=$self->soc_list_plug_nums($instance_id,$plug); foreach my $num (@nums){ my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$self->soc_get_plug($instance_id,$plug,$num); - if(defined $connect_socket || $remove_unused==0){ #$dotfile= ($first)? "$dotfile |{$name" : "$dotfile|$name"; if(defined $connect_id && defined $connect_socket){ @@ -92,57 +80,35 @@ sub get_dot_file{ $plug_order{$order_val}= "$name"; }else {push (@noconnect,"$name");} } - - #my $connect_name=$self->soc_get_instance_name($connect_id); #my $color = get_color_hex_string($n); #$n = ($n<30)? $n+1 : 0; - $graph_connect="$graph_connect $instance_id:plug_${plug}_${num} -> $connect_id:socket_${connect_socket}_${connect_socket_num} [ dir=none]\n" if(defined $connect_socket); - } } foreach my $p (sort {$a<=>$b} keys %plug_order){ - my $k=$plug_order{$p}; - #print "$instance_name : $k=\$plug_order{$p}\n"; - $dotfile= ($first) ? "$dotfile |{ ${k}": "$dotfile |${k}"; - $first=0; - - } - + my $k=$plug_order{$p}; + #print "$instance_name : $k=\$plug_order{$p}\n"; + $dotfile= ($first) ? "$dotfile |{ ${k}": "$dotfile |${k}"; + $first=0; + } foreach my $k (@noconnect){ $dotfile= ($first) ? "$dotfile |{ ${k}": "$dotfile |${k}"; $first=0; } - $dotfile= "$dotfile} }\"];"; - - - } $dotfile="$dotfile\n\n$graph_connect"; $dotfile="$dotfile\n\n}\n"; - - return $dotfile; - - } - - - - sub show_tile_diagram { my $self= shift; - my $table=def_table(20,20,FALSE); - my $window=def_popwin_size(80,80,"Processing Tile functional block diagram",'percent'); my $scrolled_win = add_widget_to_scrolled_win(); - $window->add ($table); - my $plus = def_image_button('icons/plus.png',undef,TRUE); my $minues = def_image_button('icons/minus.png',undef,TRUE); my $unused = gen_check_box_object ($self,"tile_diagram","show_unused",0,undef,undef); @@ -152,13 +118,8 @@ sub show_tile_diagram { my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); set_tip($dot_file, "Show dot file."); #my $save = def_image_button('icons/save.png',undef,TRUE); - my $scale=$self->object_get_attribute("tile_diagram","scale"); $scale= 1 if (!defined $scale); - - - - my $col=0; $table->attach ($plus , $col, $col+1,0,1,'shrink','shrink',2,2); $col++; $table->attach ($minues, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; @@ -170,15 +131,11 @@ sub show_tile_diagram { $table->attach (gen_label_in_left(" Remove Reset Interfaces"), $col, $col+1,0,1,'shrink','shrink',2,2); $col++; $table->attach ($reset, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; $table->attach ($dot_file, $col, $col+1,0,1,'shrink','shrink',2,2); $col++; - while ($col<20){ - my $tmp=gen_label_in_left(''); $table->attach_defaults ($tmp, $col, $col+1,0,1);$col++; } - $table->attach_defaults ($scrolled_win, 0, 20, 1, 20); #,'fill','shrink',2,2); - $plus -> signal_connect("clicked" => sub{ $scale*=1.1 if ($scale <10); $self->object_add_attribute("tile_diagram","scale", $scale ); @@ -196,24 +153,18 @@ sub show_tile_diagram { }); $unused-> signal_connect("toggled" => sub{ gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - }); $clk-> signal_connect("toggled" => sub{ gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - }); $reset-> signal_connect("toggled" => sub{ gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); - }); - $dot_file-> signal_connect("clicked" => sub{ my $dotfile = get_dot_file_text($self,'tile'); show_text_in_scrolled_win($self,$scrolled_win, $dotfile); }); - - gen_show_diagram($self,$scrolled_win,'tile',"tile_diagram"); $window->show_all(); } @@ -325,7 +276,6 @@ sub show_topology_diagram { show_topology_diagram($self); $window->destroy; }); - gen_show_diagram($self,$scrolled_win,'topology',"topology_diagram"); $window->show_all(); $notebook->set_current_page (0); diff --git a/mpsoc/perl_gui/lib/perl/drag_drop.pl b/mpsoc/perl_gui/lib/perl/drag_drop.pl index 2f802b3..32714d0 100644 --- a/mpsoc/perl_gui/lib/perl/drag_drop.pl +++ b/mpsoc/perl_gui/lib/perl/drag_drop.pl @@ -1,17 +1,13 @@ #! /usr/bin/perl -w - use strict; use constant::boolean; - use FindBin; use lib $FindBin::Bin; require "widget.pl"; use POSIX qw(ceil floor); - #Declare our columns use constant C_MARKUP => 0; use constant C_PIXBUF => 1; - #Declare our IDENDTIFIER ID's use constant ID_ICONVIEW => 48; @@ -25,19 +21,19 @@ sub drag_and_drop_page { my ($win,$list_store)=create_iconview($self,"$lb",'NO', $ref_source,$name,'ungrouped',undef); my $table = def_table($group_num%8,$group_num/8,FALSE); my $dim_y = floor(sqrt($group_num)); - my $gname=$self->object_get_attribute("$name",'group_name_root'); - my $editable =$self->object_get_attribute("$name",'group_name_editble'); + my $gname=$self->object_get_attribute("$name",'group_name_root'); + my $editable =$self->object_get_attribute("$name",'group_name_editble'); my $limit=$self->object_get_attribute($name,'map_limit'); for (my $i=0; $i<$group_num;$i++){ - my $ref_grp = $self->object_get_attribute("$name","$gname($i)"); + my $ref_grp = $self->object_get_attribute("$name","$gname($i)"); my ($gwin,$list_store)=create_iconview($self,"$gname($i)",$editable,$ref_grp,$name,"$gname($i)",$limit ); my $y= int($i/$dim_y); - my $x= $i % $dim_y; + my $x= $i % $dim_y; $table->attach_defaults ($gwin, $x, $x+1 , $y, $y+1); } my $sw = add_widget_to_scrolled_win($table); my $v_paned=gen_vpaned($win,.2,$sw); - my $h_paned= (defined $ctrl_box)? gen_hpaned_adj($self,$v_paned,.5,$ctrl_box, "drag.$name") : $v_paned; + my $h_paned= (defined $ctrl_box)? gen_hpaned_adj($self,$v_paned,.5,$ctrl_box, "drag.$name") : $v_paned; $vbox->add($h_paned); $vbox->show_all(); return $vbox; @@ -52,7 +48,7 @@ sub get_item_group_name{ my $gref = $self->object_get_attribute("$name","$gname($i)"); next if(! defined $gref); return $self->object_get_attribute("$name","$gname($i)".'_name') if( check_scolar_exist_in_array($item,$gref )); - } + } return $item; } @@ -67,7 +63,6 @@ sub get_items_in_a_group{ return undef; } - sub update_group_item_list{ my ($self,$group_num,$name,$items_ref)=@_; #get the list of current items @@ -79,16 +74,15 @@ sub update_group_item_list{ my $gref = $self->object_get_attribute("$name","$gname($i)"); next if(! defined $gref); my @grouped = @{$gref}; - @grouped=get_common_array(\@grouped,\@items); - $self->object_add_attribute("$name","$gname($i)",\@grouped); + @grouped=get_common_array(\@grouped,\@items); + $self->object_add_attribute("$name","$gname($i)",\@grouped); push (@items_grouped,@grouped); } #@items_ungroaped= @items - @items_groaped my @items_ungrouped= get_diff_array(\@items ,\@items_grouped); - $self->object_add_attribute("$name",'ungrouped',\@items_ungrouped); + $self->object_add_attribute("$name",'ungrouped',\@items_ungrouped); } - sub create_iconview { #--------------------------------------------------- #Creates an Iconview in a ScrolledWindow. This ----- @@ -104,7 +98,7 @@ sub create_iconview { #This is a nice to have. It changes the drag icon to that of the #icon which are now selected and dragged (single selection mode) my $saved; - $icon_view->signal_connect('drag-begin' => sub { + $icon_view->signal_connect('drag-begin' => sub { $icon_view->selected_foreach ( sub{ my $iter =$tree_model->get_iter($_[1]); $saved=$iter; @@ -115,20 +109,19 @@ sub create_iconview { } ); }); #set up the data which needs to be fed to the drag destination (drop) - $icon_view->signal_connect ('drag-data-get' => sub { + $icon_view->signal_connect ('drag-data-get' => sub { return if(! defined $saved); - $icon_string = $tree_model->get_value($saved,C_MARKUP); + $icon_string = $tree_model->get_value($saved,C_MARKUP); #print "\$icon_string=$icon_string\n"; my $no_markup = $icon_string; $no_markup =~ s/<[^>]*>//g; - my $gref = $self->object_get_attribute("$name",$param); + my $gref = $self->object_get_attribute("$name",$param); $tree_model->remove($saved); - source_drag_data_get(@_,$icon_string); + source_drag_data_get(@_,$icon_string); my @array=remove_scolar_from_array($gref,$no_markup ); $self->object_add_attribute("$name",$param,\@array); set_gui_status($self,"drag-data-get",0); } ); - #Standard scrolledwindow to allow growth my $sw = add_widget_to_scrolled_win($icon_view); $sw->set_policy('never','automatic'); @@ -146,7 +139,6 @@ sub create_iconview { return ($frame,$tree_model); } - sub target_drag_data_received { #--------------------------------------------------- #Extract the data which was set up during the ----- @@ -161,21 +153,20 @@ sub target_drag_data_received { my $pixbuf = get_icon_pixbuff ($icon ); my $no_markup = $data->get_text; #print Dumper ($widget, $context, $x, $y, $data, $info, $time,$no_markup); - $no_markup =~ s/<[^>]*>//g; + $no_markup =~ s/<[^>]*>//g; add_icon_to_tree($self,$name,$target,$no_markup) ; my $r=$self->object_get_attribute("$name","$param"); @array = defined ($r)? @{$r}:(); push (@array ,$no_markup); - $self->object_add_attribute("$name","$param",\@array); + $self->object_add_attribute("$name","$param",\@array); # check if the maximum number of dropped item is received $limit =655350 if(!defined $limit); - if( scalar @array >= $limit){ + if( scalar @array >= $limit){ stop_drag_dest( $widget); } call_gtk_drag_finish($context, 0, 0, $time); # $context->finish (0, 0, $time); } - sub source_drag_data_get { #--------------------------------------------------- #This sets up the data of the drag source. It is --- @@ -187,7 +178,6 @@ sub source_drag_data_get { $data->set_text("Unknown-event-name",-1) unless defined $string; } - sub add_icon_to_tree{ my ($self,$name,$list_store,$val)=@_; my $icon=$self->object_get_attribute($name,'trace_icon'); @@ -208,7 +198,6 @@ sub stop_drag_dest { $widget->drag_dest_unset (); } - sub add_drop_source { my ($widget,$target,$name,$param,$self,$limit)=@_; #Create a target table to receive drops @@ -218,7 +207,7 @@ sub add_drop_source { my @array = defined ($r)? @{$r}:(); # check if the maximum number of dropped item is received $limit =655350 if(!defined $limit); - if( scalar @array >= $limit){ + if( scalar @array >= $limit){ stop_drag_dest( $widget); } #do a callback as soon as drag data is received @@ -227,4 +216,5 @@ sub add_drop_source { $widget->signal_connect ('drag-data-get' => sub { add_drag_dest_set($widget, 'STRING',[],ID_ICONVIEW); }); -} \ No newline at end of file +} +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl b/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl index dc07e6a..b574571 100755 --- a/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl +++ b/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl @@ -2,513 +2,397 @@ use strict; use warnings; use List::Util 'shuffle'; -require "widget.pl"; +require "widget.pl"; require "traffic_pattern.pl"; - -use constant SIM_RAM_GEN => 0; - -use constant JTAG_STATIC_INDEX => 124; -use constant JTAG_RAM_INDEX => 125; +use constant SIM_RAM_GEN => 0; +use constant JTAG_STATIC_INDEX => 124; +use constant JTAG_RAM_INDEX => 125; use constant JTAG_COUNTER_INDEX=>126; -use constant JTAG_DONE_RESET_INDEX => 127; +use constant JTAG_DONE_RESET_INDEX => 127; use constant STATISTIC_NUM =>8; - -use constant CLK_CNTw=> 30; #log2(MAX_SIM_CLKs); - - -#use constant RESET_NOC => " $ENV{'JTAG_INTFC'} -n ".JTAG_DONE_RESET_INDEX." -d \"I:1,D:2:1,I:0\" "; -#use constant UNRESET_NOC => " $ENV{'JTAG_INTFC'} -n ".JTAG_DONE_RESET_INDEX." -d \"I:1,D:2:0,I:0\" "; - -use constant READ_DONE_CMD => " \" -n ".JTAG_DONE_RESET_INDEX." -d I:2,R:2:0,I:0 \" "; +use constant CLK_CNTw=> 30; #log2(MAX_SIM_CLKs); +#use constant RESET_NOC => " $ENV{'JTAG_INTFC'} -n ".JTAG_DONE_RESET_INDEX." -d \"I:1,D:2:1,I:0\" "; +#use constant UNRESET_NOC => " $ENV{'JTAG_INTFC'} -n ".JTAG_DONE_RESET_INDEX." -d \"I:1,D:2:0,I:0\" "; +use constant READ_DONE_CMD => " \" -n ".JTAG_DONE_RESET_INDEX." -d I:2,R:2:0,I:0 \" "; use constant READ_COUNTER_CMD => " \" -n ".JTAG_COUNTER_INDEX." -d I:2,R:".CLK_CNTw.":0,I:0 \" "; - - -use constant UPDATE_WB_ADDR => 0x7; +use constant UPDATE_WB_ADDR => 0x7; use constant UPDATE_WB_WR_DATA => 0x6; use constant UPDATE_WB_RD_DATA => 0x5; -use constant RD_WR_STATUS => 0x4; -use constant PROBE_ST => 0x2; -use constant SOURCE_ST => 0x1; -use constant BYPAS_ST => 0x0; -#use constant RAM_BIN_FILE => "$ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin"; -#use constant RAM_SIM_FILE => "$ENV{'PRONOC_WORK'}/emulate/ram"; - - - - +use constant RD_WR_STATUS => 0x4; +use constant PROBE_ST => 0x2; +use constant SOURCE_ST => 0x1; +use constant BYPAS_ST => 0x0; +#use constant RAM_BIN_FILE => "$ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin"; +#use constant RAM_SIM_FILE => "$ENV{'PRONOC_WORK'}/emulate/ram"; sub reset_cmd { - my ($ctrl_reset, $noc_reset,$jtag_intfc)=@_; - my $reset_vector= (($ctrl_reset & 0x1) << 1) + ($noc_reset & 0x1); - my $cmd = "bash $jtag_intfc \" -n ".JTAG_DONE_RESET_INDEX." -d I:1,D:2:$reset_vector,I:0 \" "; - #print "$cmd\n"; - return $cmd; + my ($ctrl_reset, $noc_reset,$jtag_intfc)=@_; + my $reset_vector= (($ctrl_reset & 0x1) << 1) + ($noc_reset & 0x1); + my $cmd = "bash $jtag_intfc \" -n ".JTAG_DONE_RESET_INDEX." -d I:1,D:2:$reset_vector,I:0 \" "; + #print "$cmd\n"; + return $cmd; } sub set_time_limit_cmd { - my ($time_limit,$jtag_intfc)=@_; - my $hex = sprintf("0x%X", $time_limit); - my $cmd = "bash $jtag_intfc \" -n ".JTAG_COUNTER_INDEX." -d I:1,D:".CLK_CNTw.":$hex,I:0 \" "; - #print "$cmd\n"; - return $cmd; + my ($time_limit,$jtag_intfc)=@_; + my $hex = sprintf("0x%X", $time_limit); + my $cmd = "bash $jtag_intfc \" -n ".JTAG_COUNTER_INDEX." -d I:1,D:".CLK_CNTw.":$hex,I:0 \" "; + #print "$cmd\n"; + return $cmd; } - sub help { - print -" usage: ./ram_gen X Y TRAFFIC - X: number of node in X direction 2object_get_attribute($sample,"traffic"); - - my $pck_num_to_send=$emulate->object_get_attribute($sample,"PCK_NUM_LIMIT"); - my $pck_size=$emulate->object_get_attribute($sample,"PCK_SIZE"); - my $pck_class_in=0; - - - if($line_num==0){ #first ram line shows how many times the ram content must be read - #In random traffic each node sends 2 packets to other NC-1 nodes for (pck_num_to_send/2) times - my $ram_cnt= ($traffic eq 'random')? ($pck_num_to_send/(2*($NE-1)))+1:0 ; - return (0,$ram_cnt); - - } - return (0,0) if($line_num>1 && $traffic ne 'random'); - return (0,0) if( $line_num>= $NE); - - #assign {pck_num_to_send_in,ratio_in, pck_size_in,dest_x_in, dest_y_in,pck_class_in, last_adr_in}= q_a; - my $last_adr = ( $traffic ne 'random') ? 1 : - ($line_num ==$NE-1)? 1 :0; - - my $dest_e_addr=synthetic_destination($emulate,$sample,$traffic,$endp,$line_num,$rnd); - #print "$endp->$dest_e_addr\n"; - - my $vs= ( $traffic eq 'random')? 2 : $pck_num_to_send; - $vs=($vs << 2 )+ ($ratio >>5) ; - - my $vl= ($ratio %32); - $vl=($vl << PCK_SIZw )+$pck_size; - $vl=($vl << MAX_EAw )+$dest_e_addr; - $vl=($vl << MAXCw )+$pck_class_in; - $vl=($vl << 1 )+$last_adr; - return ($vs,$vl); + my ($emulate, $endp, $sample,$ratio ,$line_num,$rnd)=@_; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my $traffic=$emulate->object_get_attribute($sample,"traffic"); + my $pck_num_to_send=$emulate->object_get_attribute($sample,"PCK_NUM_LIMIT"); + my $pck_size=$emulate->object_get_attribute($sample,"PCK_SIZE"); + my $pck_class_in=0; + if($line_num==0){ #first ram line shows how many times the ram content must be read + #In random traffic each node sends 2 packets to other NC-1 nodes for (pck_num_to_send/2) times + my $ram_cnt= ($traffic eq 'random')? ($pck_num_to_send/(2*($NE-1)))+1:0 ; + return (0,$ram_cnt); + } + return (0,0) if($line_num>1 && $traffic ne 'random'); + return (0,0) if( $line_num>= $NE); + #assign {pck_num_to_send_in,ratio_in, pck_size_in,dest_x_in, dest_y_in,pck_class_in, last_adr_in}= q_a; + my $last_adr = ( $traffic ne 'random') ? 1 : + ($line_num ==$NE-1)? 1 :0; + my $dest_e_addr=synthetic_destination($emulate,$sample,$traffic,$endp,$line_num,$rnd); + #print "$endp->$dest_e_addr\n"; + my $vs= ( $traffic eq 'random')? 2 : $pck_num_to_send; + $vs=($vs << 2 )+ ($ratio >>5) ; + my $vl= ($ratio %32); + $vl = ($vl << PCK_SIZw ) + $pck_size; + $vl = ($vl << MAX_EAw ) + $dest_e_addr; + $vl = ($vl << MAXCw ) + $pck_class_in; + $vl = ($vl << 1 ) + $last_adr; + return ($vs,$vl); } sub get_synthetic_traffic_pattern{ - my ($self, $sample)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - my $rnd=random_dest_gen_no_shuffle($NE); - my $traffic=$self->object_get_attribute($sample,"traffic"); - my @traffics=("tornado", "transposed 1", "transposed 2", "bit reverse", "bit complement","random", "hot spot", "shuffle", "neighbor", "bit rotation" ); - - #generate each node ram data - my $pattern="source->\t destination\n"; - $traffic=($traffic eq "hot spot") ? "random" : $traffic; - my $dest_num = ($traffic eq "hot spot" || $traffic eq "random" ) ? $NE-1 : 1; - for (my $endp=0; $endp<$NE; $endp++){ - $pattern = $pattern."$endp->\n"; - for (my $num= 0; $num<$dest_num; $num++ ) { - my $dest_e_addr=synthetic_destination($self,$sample,$traffic,$endp,$num,$rnd); - my $des_id=endp_addr_decoder($self,$dest_e_addr); - $pattern = ($des_id == $endp)?$pattern."\t$des_id (Off)\n" : $pattern."\t$des_id\n"; - }} - return $pattern; + my ($self, $sample)=@_; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my $rnd=random_dest_gen_no_shuffle($NE); + my $traffic=$self->object_get_attribute($sample,"traffic"); + my @traffics=("tornado", "transposed 1", "transposed 2", "bit reverse", "bit complement","random", "hot spot", "shuffle", "neighbor", "bit rotation" ); + #generate each node ram data + my $pattern="source->\t destination\n"; + $traffic=($traffic eq "hot spot") ? "random" : $traffic; + my $dest_num = ($traffic eq "hot spot" || $traffic eq "random" ) ? $NE-1 : 1; + for (my $endp=0; $endp<$NE; $endp++){ + $pattern = $pattern."$endp->\n"; + for (my $num= 0; $num<$dest_num; $num++ ) { + my $dest_e_addr=synthetic_destination($self,$sample,$traffic,$endp,$num,$rnd); + my $des_id=endp_addr_decoder($self,$dest_e_addr); + $pattern = ($des_id == $endp)?$pattern."\t$des_id (Off)\n" : $pattern."\t$des_id\n"; + }} + return $pattern; } - - sub generate_synthetic_traffic_ram{ - my ($emulate,$endp,$sample,$ratio , $file,$rnd)=@_; - - my $line_num; - my $line_value; - my $ram; - if(SIM_RAM_GEN){ - my $ext= sprintf("%02u.txt",$endp); - open( $ram, '>', "$ENV{'PRONOC_WORK'}/emulate/ram".$ext) || die "Can not create: \"$ENV{'PRONOC_WORK'}/emulate/ram.$ext\" $!"; - } - for ($line_num= 0; $line_num', "$ENV{'PRONOC_WORK'}/emulate/ram".$ext) || die "Can not create: \"$ENV{'PRONOC_WORK'}/emulate/ram.$ext\" $!"; + } + for ($line_num= 0; $line_num=0 ; $i-=8) { - my $byte= ($v >> $i ) & 0xFF; - print $file pack('C*',$byte); - #printf ("%02x\t",$byte); - } + my ($file,$v)=@_; + for (my $i= 24; $i >=0 ; $i-=8) { + my $byte= ($v >> $i ) & 0xFF; + print $file pack('C*',$byte); + #printf ("%02x\t",$byte); + } } - - sub generate_emulator_ram { - my ($emulate, $sample,$ratio_in,$info)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - - - - my $rnd=random_dest_gen($NE); # generate a matrix of sudo random number - my $traffic=$emulate->object_get_attribute($sample,"traffic"); - my @traffics=("tornado", "transposed 1", "transposed 2", "bit reverse", "bit complement","random", "hot spot", "shuffle", "neighbor", "bit rotation" ); - - #if ( !defined $xn || $xn!~ /\s*\d+\b/ ){ add_info($info,"programe_pck_gens:invalid X value\n"); help(); return 0;} - #if ( !defined $yn || $yn!~ /\s*\d+\b/ ){ add_info($info,"programe_pck_gens:invalid Y value\n"); help(); return 0;} - if ( !grep( /^$traffic$/, @traffics ) ){add_info($info,"programe_pck_gens:$traffic is an invalid Traffic name\n"); help(); return 0;} - if ( $EAw >8 ){ add_info($info,"Program_pck_gens:invalid EAw value: ($EAw). should be between 1 and 8 \n"); help(); return 0;} - #if ( $yn <2 || $yn >16 ){ add_info($info,"programe_pck_gens:invalid Y value:($yn). should be between 2 and 16 \n"); help(); return 0;} - #open file pointer - #open(my $file, '>', RAM_BIN_FILE) || die "Can not create: \">lib/emulate/emulate_ram.bin\" $!"; - open(my $file, '>', "$ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin") || die "Can not create: \"$ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin\" $!"; - - #generate each node ram data - for (my $endp=0; $endp<$NE; $endp++){ - #print "generate_synthetic_traffic_ram($emulate,$endp,$sample,$ratio_in, $file,$rnd);\n"; - generate_synthetic_traffic_ram($emulate,$endp,$sample,$ratio_in, $file,$rnd); - } - close($file); - return 1; - + my ($emulate, $sample,$ratio_in,$info)=@_; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my $rnd=random_dest_gen($NE); # generate a matrix of sudo random number + my $traffic=$emulate->object_get_attribute($sample,"traffic"); + my @traffics=("tornado", "transposed 1", "transposed 2", "bit reverse", "bit complement","random", "hot spot", "shuffle", "neighbor", "bit rotation" ); + #if ( !defined $xn || $xn!~ /\s*\d+\b/ ){ add_info($info,"programe_pck_gens:invalid X value\n"); help(); return 0;} + #if ( !defined $yn || $yn!~ /\s*\d+\b/ ){ add_info($info,"programe_pck_gens:invalid Y value\n"); help(); return 0;} + if ( !grep( /^$traffic$/, @traffics ) ){add_info($info,"programe_pck_gens:$traffic is an invalid Traffic name\n"); help(); return 0;} + if ( $EAw >8 ){ add_info($info,"Program_pck_gens:invalid EAw value: ($EAw). should be between 1 and 8 \n"); help(); return 0;} + #if ( $yn <2 || $yn >16 ){ add_info($info,"programe_pck_gens:invalid Y value:($yn). should be between 2 and 16 \n"); help(); return 0;} + #open file pointer + #open(my $file, '>', RAM_BIN_FILE) || die "Can not create: \">lib/emulate/emulate_ram.bin\" $!"; + open(my $file, '>', "$ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin") || die "Can not create: \"$ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin\" $!"; + #generate each node ram data + for (my $endp=0; $endp<$NE; $endp++){ + #print "generate_synthetic_traffic_ram($emulate,$endp,$sample,$ratio_in, $file,$rnd);\n"; + generate_synthetic_traffic_ram($emulate,$endp,$sample,$ratio_in, $file,$rnd); + } + close($file); + return 1; } sub programe_pck_gens{ - my ($emulate, $sample,$ratio_in,$info,$jtag_intfc)= @_; - - if(!generate_emulator_ram($emulate, $sample,$ratio_in,$info)){ - add_colored_info($info, "Error in generate_emulator_ram function\n",'red'); - return 0; - - } - - #reset the FPGA board - #run_cmd_in_back_ground("quartus_stp -t ./lib/tcl/mem.tcl reset"); - #print "#reset both noc and jtag\n"; - return 0 if(run_cmd_update_info(reset_cmd(1,1,$jtag_intfc),$info)); #reset both noc and jtag - #print "#enable jtag keep noc in reset\n"; - return 0 if(run_cmd_update_info(reset_cmd(0,1,$jtag_intfc),$info)); #enable jtag keep noc in reset - #print "#set time limit\n"; - #set time limit - my $time_limit = $emulate->object_get_attribute($sample,"SIM_CLOCK_LIMIT"); - return 0 if(run_cmd_update_info(set_time_limit_cmd($time_limit,$jtag_intfc),$info)); - - - - #program the packet generators rams - my $cmd= "bash $jtag_intfc \"-n ".JTAG_RAM_INDEX." -w 8 -i $ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin -c\" "; - #my ($result,$exit) = run_cmd_in_back_ground_get_stdout($cmd); - - return 0 if(run_cmd_update_info ($cmd,$info)); - #print $result; - - return 0 if(run_cmd_update_info(reset_cmd(1,1,$jtag_intfc),$info)); #reset both - return 0 if(run_cmd_update_info(reset_cmd(0,0,$jtag_intfc),$info)); #enable both + my ($emulate, $sample,$ratio_in,$info,$jtag_intfc)= @_; + if(!generate_emulator_ram($emulate, $sample,$ratio_in,$info)){ + add_colored_info($info, "Error in generate_emulator_ram function\n",'red'); + return 0; + } + #reset the FPGA board + #run_cmd_in_back_ground("quartus_stp -t ./lib/tcl/mem.tcl reset"); + #print "#reset both noc and jtag\n"; + return 0 if(run_cmd_update_info(reset_cmd(1,1,$jtag_intfc),$info)); #reset both noc and jtag + #print "#enable jtag keep noc in reset\n"; + return 0 if(run_cmd_update_info(reset_cmd(0,1,$jtag_intfc),$info)); #enable jtag keep noc in reset + #print "#set time limit\n"; + #set time limit + my $time_limit = $emulate->object_get_attribute($sample,"SIM_CLOCK_LIMIT"); + return 0 if(run_cmd_update_info(set_time_limit_cmd($time_limit,$jtag_intfc),$info)); + #program the packet generators rams + my $cmd= "bash $jtag_intfc \"-n ".JTAG_RAM_INDEX." -w 8 -i $ENV{'PRONOC_WORK'}/emulate/emulate_ram.bin -c\" "; + #my ($result,$exit) = run_cmd_in_back_ground_get_stdout($cmd); + return 0 if(run_cmd_update_info ($cmd,$info)); + #print $result; + return 0 if(run_cmd_update_info(reset_cmd(1,1,$jtag_intfc),$info)); #reset both + return 0 if(run_cmd_update_info(reset_cmd(0,0,$jtag_intfc),$info)); #enable both #run_cmd_in_back_ground("quartus_stp -t ./lib/tcl/mem.tcl unreset"); #add_info($info,"$r\n"); - return 1; - } - sub read_jtag_memory{ - my ($addr,$jtag_intfc,$info)=@_; - my $cmd= "bash $jtag_intfc \" -n ".JTAG_STATIC_INDEX." -w 8 -d I:".UPDATE_WB_ADDR.",D:64:$addr,I:5,R:64:$addr,I:0\""; - #print "$cmd\n"; - my ($result,$exit,$stderr) = run_cmd_in_back_ground_get_stdout($cmd); - if($exit){ - add_colored_info($info, "$result\n",'red') if(defined $result); - add_colored_info($info, "$stderr\n",'red') if(defined $stderr); - return undef; - - } - #print "$result\n"; - - my @q =split (/###read data#/,$result); - my $d=$q[1]; - my $s= substr $d,2; - #print "$s\n"; - return hex($s); + my ($addr,$jtag_intfc,$info)=@_; + my $cmd= "bash $jtag_intfc \" -n ".JTAG_STATIC_INDEX." -w 8 -d I:".UPDATE_WB_ADDR.",D:64:$addr,I:5,R:64:$addr,I:0\""; + #print "$cmd\n"; + my ($result,$exit,$stderr) = run_cmd_in_back_ground_get_stdout($cmd); + if($exit){ + add_colored_info($info, "$result\n",'red') if(defined $result); + add_colored_info($info, "$stderr\n",'red') if(defined $stderr); + return undef; + } + #print "$result\n"; + my @q =split (/###read data#/,$result); + my $d=$q[1]; + my $s= substr $d,2; + #print "$s\n"; + return hex($s); } - sub read_statistic_mem { - my($NE,$jtag_intfc,$info)=@_; - my %results; - my $sum_of_latency=0; - my $sum_of_pck=0; - my $total_router=0; - for (my $num=0; $num<$NE; $num++){ - - my $read_addr=($num * STATISTIC_NUM); - - my $sent_pck_addr= sprintf ("%X",$read_addr); - my $got_pck_addr = sprintf ("%X",$read_addr+1); - my $latency_addr = sprintf ("%X",$read_addr+2); - my $worst_latency_addr = sprintf ("%X",$read_addr+3); - - $results{$num}{sent_pck}=read_jtag_memory($sent_pck_addr,$jtag_intfc,$info); - $results{$num}{got_pck}=read_jtag_memory($got_pck_addr,$jtag_intfc,$info); - $results{$num}{latency}=read_jtag_memory($latency_addr,$jtag_intfc,$info); - $results{$num}{worst_latency}=read_jtag_memory($worst_latency_addr,$jtag_intfc,$info); - add_info($info, "$num, "); - - $sum_of_latency+=$results{$num}{latency}; - $sum_of_pck+=$results{$num}{got_pck}; - $total_router++ if($results{$num}{sent_pck}>0); - #$i=$i+2; - } - - - - add_info($info, "\n"); - - return (\%results,$sum_of_latency,$sum_of_pck,$total_router); - + my($NE,$jtag_intfc,$info)=@_; + my %results; + my $sum_of_latency=0; + my $sum_of_pck=0; + my $total_router=0; + for (my $num=0; $num<$NE; $num++){ + my $read_addr=($num * STATISTIC_NUM); + my $sent_pck_addr= sprintf ("%X",$read_addr); + my $got_pck_addr = sprintf ("%X",$read_addr+1); + my $latency_addr = sprintf ("%X",$read_addr+2); + my $worst_latency_addr = sprintf ("%X",$read_addr+3); + $results{$num}{sent_pck}=read_jtag_memory($sent_pck_addr,$jtag_intfc,$info); + $results{$num}{got_pck}=read_jtag_memory($got_pck_addr,$jtag_intfc,$info); + $results{$num}{latency}=read_jtag_memory($latency_addr,$jtag_intfc,$info); + $results{$num}{worst_latency}=read_jtag_memory($worst_latency_addr,$jtag_intfc,$info); + add_info($info, "$num, "); + $sum_of_latency+=$results{$num}{latency}; + $sum_of_pck+=$results{$num}{got_pck}; + $total_router++ if($results{$num}{sent_pck}>0); + #$i=$i+2; + } + add_info($info, "\n"); + return (\%results,$sum_of_latency,$sum_of_pck,$total_router); } - sub read_statistic_mem_fast { - my($NE,$jtag_intfc,$info)=@_; - my %results; - my $sum_of_latency=0; - my $sum_of_pck=0; - my $total_router=0; - #read static memory - my $end= STATISTIC_NUM * 8 *$NE; - $end=sprintf ("%X",$end); - my $cmd= "bash $jtag_intfc \"-n ".JTAG_STATIC_INDEX." -w 8 -r -s 0 -e $end\""; - #print "$cmd\n"; - my ($result,$exit,$stderr) = run_cmd_in_back_ground_get_stdout($cmd); - if($exit){ - add_colored_info($info, "$result\n",'red') if(defined $result); - add_colored_info($info, "$stderr\n",'red') if(defined $stderr); - return undef; - - } - #print "$result\n"; - my @q =split (/###read data#\n/,$result); - my @data= split (/\n/,$q[1]); - #print "$data[0]\n"; - - - - - for (my $endp=0; $endp<$NE; $endp=$endp+1){ - - my $num=$endp; - my $read_addr=($num * STATISTIC_NUM); - - my $sent_pck_addr= $read_addr; - my $got_pck_addr = $read_addr+1; - my $latency_addr = $read_addr+2; - my $worst_latency_addr = $read_addr+3; - - $results{$num}{sent_pck}=hex($data[$sent_pck_addr]); - $results{$num}{got_pck}=hex($data[$got_pck_addr]); - $results{$num}{latency}=hex($data[$latency_addr]); - $results{$num}{worst_latency}=hex($data[$worst_latency_addr]); - #add_info($info, "$num, "); - #print "$results{$num}{sent_pck}=hex($data[$sent_pck_addr]);\n"; - - $sum_of_latency+=$results{$num}{latency}; - $sum_of_pck+=$results{$num}{got_pck}; - $total_router++ if($results{$num}{sent_pck}>0); - #$i=$i+2; - } - - - - #add_info($info, "\n"); - - return (\%results,$sum_of_latency,$sum_of_pck,$total_router); - + my($NE,$jtag_intfc,$info)=@_; + my %results; + my $sum_of_latency=0; + my $sum_of_pck=0; + my $total_router=0; + #read static memory + my $end= STATISTIC_NUM * 8 *$NE; + $end=sprintf ("%X",$end); + my $cmd= "bash $jtag_intfc \"-n ".JTAG_STATIC_INDEX." -w 8 -r -s 0 -e $end\""; + #print "$cmd\n"; + my ($result,$exit,$stderr) = run_cmd_in_back_ground_get_stdout($cmd); + if($exit){ + add_colored_info($info, "$result\n",'red') if(defined $result); + add_colored_info($info, "$stderr\n",'red') if(defined $stderr); + return undef; + } + #print "$result\n"; + my @q =split (/###read data#\n/,$result); + my @data= split (/\n/,$q[1]); + #print "$data[0]\n"; + for (my $endp=0; $endp<$NE; $endp=$endp+1){ + my $num=$endp; + my $read_addr=($num * STATISTIC_NUM); + my $sent_pck_addr= $read_addr; + my $got_pck_addr = $read_addr+1; + my $latency_addr = $read_addr+2; + my $worst_latency_addr = $read_addr+3; + $results{$num}{sent_pck}=hex($data[$sent_pck_addr]); + $results{$num}{got_pck}=hex($data[$got_pck_addr]); + $results{$num}{latency}=hex($data[$latency_addr]); + $results{$num}{worst_latency}=hex($data[$worst_latency_addr]); + #add_info($info, "$num, "); + #print "$results{$num}{sent_pck}=hex($data[$sent_pck_addr]);\n"; + $sum_of_latency+=$results{$num}{latency}; + $sum_of_pck+=$results{$num}{got_pck}; + $total_router++ if($results{$num}{sent_pck}>0); + #$i=$i+2; + } + #add_info($info, "\n"); + return (\%results,$sum_of_latency,$sum_of_pck,$total_router); } - -sub read_pack_gen{ - my ($emulate,$sample,$info,$jtag_intfc,$ratio_in)= @_; - my $ref=$emulate->object_get_attribute($sample,"noc_info"); - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); -#wait for done +sub read_pack_gen{ + my ($emulate,$sample,$info,$jtag_intfc,$ratio_in)= @_; + my $ref=$emulate->object_get_attribute($sample,"noc_info"); + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); +#wait for done add_info($info, "wait for done\n"); my $done=0; my $counter=0; while ($done ==0){ - usleep(300000); - #my ($result,$exit) = run_cmd_in_back_ground_get_stdout("quartus_stp -t ./lib/tcl/read.tcl done"); - my ($result,$exit) = run_cmd_in_back_ground_get_stdout("bash $jtag_intfc".READ_DONE_CMD); - if($exit != 0 ){ - add_colored_info($info,$result,'red'); - return undef; - } - my @q =split (/###read data#/,$result); - #print "\$result=$result\n"; - - - $done=($q[1] eq "0x0")? 0 : 1; - #print "\$q[1]=$q[1] done=$done\n"; - - $counter++; - if($counter == 15){ # - add_info($info,"Done is not asserted. I reset the board and try again\n"); - return if(run_cmd_update_info (reset_cmd(1,1,$jtag_intfc),$info)); - #run_cmd_in_back_ground("quartus_stp -t ./lib/tcl/mem.tcl reset"); - usleep(300000); - return if(run_cmd_update_info (reset_cmd(0,0,$jtag_intfc),$info)); - #run_cmd_in_back_ground("quartus_stp -t ./lib/tcl/mem.tcl unreset"); - } - if($counter>30){ - #something is wrong - add_colored_info($info,"Done is not asserted again. I am going to ignore this test case\n",'green'); - return undef; - } - } - - add_info($info,"Done is asserted\nStart reading statistic data from cores:\n\t"); - #print" Done is asserted\n"; - #my $i=0; - #my ($results_ref,$sum_of_latency,$sum_of_pck,$total_router)= read_statistic_mem($NE,$jtag_intfc,$info); - my ($results_ref,$sum_of_latency,$sum_of_pck,$total_router)= read_statistic_mem_fast($NE,$jtag_intfc,$info); - my %results=%$results_ref; - - - foreach my $p (sort keys %results){ - update_result($emulate,$sample,"packet_rsvd_result",$ratio_in,$p,$results{$p}{got_pck} ); - update_result($emulate,$sample,"packet_sent_result",$ratio_in,$p,$results{$p}{sent_pck}); - update_result($emulate,$sample,"worst_delay_rsvd_result",$ratio_in,$p,$results{$p}{worst_latency}); - #print "$p : \n latency: $results{$p}{latency}\n"; - #print "got_pck : $results{$p}{got_pck}\n"; - #print "sent_pck:$results{$p}{sent_pck}\n\n"; - #print "worst_delay:$results{$p}{worst_latency}\n\n"; - - } - #print "total active router=$total_router\n"; - #read clock counter - my $clk_counter; - my ($result,$exit) = run_cmd_in_back_ground_get_stdout("bash $jtag_intfc".READ_COUNTER_CMD); - if($exit != 0 ){ - add_colored_info($info,$result,'red'); - - }else { - - my @q =split (/###read data#/,$result); - my $d=$q[1]; - my $s= substr $d,2; - $clk_counter= hex($s); - - } - - my $avg_latency= ($sum_of_pck>0)? $sum_of_latency/$sum_of_pck : 0; - my $packet_size=$emulate->object_get_attribute($sample,"PCK_SIZE"); - my $avg_throughput= ($sum_of_pck>0 && $total_router>0 && $clk_counter>0 )? (($sum_of_pck * $packet_size *100)/ $total_router )/$clk_counter:0; - #print "($sum_of_pck * $packet_size *100)/ $total_router )/$clk_counter = $avg_throughput)"; - - #print "$avg = $sum_of_latency/$sum_of_pck "; - $avg_latency= sprintf("%.1f", $avg_latency); - - update_result ($emulate,$sample,"latency_result",$ratio_in,$avg_latency); - update_result ($emulate,$sample,"throughput_result",$ratio_in,$avg_throughput); - update_result ($emulate,$sample,"exe_time_result",$ratio_in,$clk_counter); - - - return 1; -} - + usleep(300000); + #my ($result,$exit) = run_cmd_in_back_ground_get_stdout("quartus_stp -t ./lib/tcl/read.tcl done"); + my ($result,$exit) = run_cmd_in_back_ground_get_stdout("bash $jtag_intfc".READ_DONE_CMD); + if($exit != 0 ){ + add_colored_info($info,$result,'red'); + return undef; + } + my @q =split (/###read data#/,$result); + #print "\$result=$result\n"; + $done=($q[1] eq "0x0")? 0 : 1; + #print "\$q[1]=$q[1] done=$done\n"; + $counter++; + if($counter == 15){ # + add_info($info,"Done is not asserted. I reset the board and try again\n"); + return if(run_cmd_update_info (reset_cmd(1,1,$jtag_intfc),$info)); + #run_cmd_in_back_ground("quartus_stp -t ./lib/tcl/mem.tcl reset"); + usleep(300000); + return if(run_cmd_update_info (reset_cmd(0,0,$jtag_intfc),$info)); + #run_cmd_in_back_ground("quartus_stp -t ./lib/tcl/mem.tcl unreset"); + } + if($counter>30){ + #something is wrong + add_colored_info($info,"Done is not asserted again. I am going to ignore this test case\n",'green'); + return undef; + } + } + add_info($info,"Done is asserted\nStart reading statistic data from cores:\n\t"); + #print" Done is asserted\n"; + #my $i=0; + #my ($results_ref,$sum_of_latency,$sum_of_pck,$total_router)= read_statistic_mem($NE,$jtag_intfc,$info); + my ($results_ref,$sum_of_latency,$sum_of_pck,$total_router)= read_statistic_mem_fast($NE,$jtag_intfc,$info); + my %results=%$results_ref; + foreach my $p (sort keys %results){ + update_result($emulate,$sample,"packet_rsvd_result",$ratio_in,$p,$results{$p}{got_pck} ); + update_result($emulate,$sample,"packet_sent_result",$ratio_in,$p,$results{$p}{sent_pck}); + update_result($emulate,$sample,"worst_delay_rsvd_result",$ratio_in,$p,$results{$p}{worst_latency}); + #print "$p : \n latency: $results{$p}{latency}\n"; + #print "got_pck : $results{$p}{got_pck}\n"; + #print "sent_pck:$results{$p}{sent_pck}\n\n"; + #print "worst_delay:$results{$p}{worst_latency}\n\n"; + } + #print "total active router=$total_router\n"; + #read clock counter + my $clk_counter; + my ($result,$exit) = run_cmd_in_back_ground_get_stdout("bash $jtag_intfc".READ_COUNTER_CMD); + if($exit != 0 ){ + add_colored_info($info,$result,'red'); + }else { + my @q =split (/###read data#/,$result); + my $d=$q[1]; + my $s= substr $d,2; + $clk_counter= hex($s); + } + my $avg_latency= ($sum_of_pck>0)? $sum_of_latency/$sum_of_pck : 0; + my $packet_size=$emulate->object_get_attribute($sample,"PCK_SIZE"); + my $avg_throughput= ($sum_of_pck>0 && $total_router>0 && $clk_counter>0 )? (($sum_of_pck * $packet_size *100)/ $total_router )/$clk_counter:0; + #print "($sum_of_pck * $packet_size *100)/ $total_router )/$clk_counter = $avg_throughput)"; + #print "$avg = $sum_of_latency/$sum_of_pck "; + $avg_latency= sprintf("%.1f", $avg_latency); + update_result ($emulate,$sample,"latency_result",$ratio_in,$avg_latency); + update_result ($emulate,$sample,"throughput_result",$ratio_in,$avg_throughput); + update_result ($emulate,$sample,"exe_time_result",$ratio_in,$clk_counter); + return 1; +} +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/emulator.pl b/mpsoc/perl_gui/lib/perl/emulator.pl index b2c17c1..c8487d8 100755 --- a/mpsoc/perl_gui/lib/perl/emulator.pl +++ b/mpsoc/perl_gui/lib/perl/emulator.pl @@ -2,55 +2,43 @@ use constant::boolean; use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - use GD::Graph::Data; use emulator; - use GD::Graph::colour qw/:colours/; - use File::Basename; use File::Path qw/make_path/; use File::Copy; use File::Find::Rule; - -require "widget.pl"; -require "emulate_ram_gen.pl"; -require "mpsoc_gen.pl"; -require "mpsoc_verilog_gen.pl"; +require "widget.pl"; +require "emulate_ram_gen.pl"; +require "mpsoc_gen.pl"; +require "mpsoc_verilog_gen.pl"; require "readme_gen.pl"; require "graph.pl"; require "topology.pl"; - use List::MoreUtils qw(uniq); - - # hardware parameters taken from noc_emulator.v use constant PCK_CNTw =>30; # packet counter width in bits (results in maximum of 2^30 = 1 G packets) use constant PCK_SIZw =>14; # packet size width in bits (results in maximum packet size of 2^14 = 16 K flit) use constant MAX_EAw =>8; # maximum destination address width -use constant MAXCw =>4; # 16 message classes +use constant MAXCw =>4; # 16 message classes use constant RATIOw =>7; # log2(100) use constant RAM_Aw =>7; use constant RAM_RESERVED_ADDR_NUM=>8; -use constant MAX_PATTERN => ((2**RAM_Aw)-(RAM_RESERVED_ADDR_NUM)); -use constant RAM_SIZE => (2**RAM_Aw); - - +use constant MAX_PATTERN => ((2**RAM_Aw)-(RAM_RESERVED_ADDR_NUM)); +use constant RAM_SIZE => (2**RAM_Aw); #use constant MAX_PCK_NUM => (2**PCK_CNTw)-1; use constant MAX_PCK_NUM => (2**PCK_CNTw)-1; -use constant MAX_PCK_SIZ => (2**PCK_SIZw)-1; -use constant MAX_SIM_CLKs=> 1000000000; # simulation end at if clock counter reach this number - +use constant MAX_PCK_SIZ => (2**PCK_SIZw)-1; +use constant MAX_SIM_CLKs=> 1000000000; # simulation end at if clock counter reach this number use constant MAX_RATIO => 1000;# 0->0 1->0.1 ... 1000->100 - use constant EMULATION_TOP => "/mpsoc/rtl/src_emulate/emulator_top.v"; - - sub get_MAX_PCK_NUM(){MAX_PCK_NUM} + sub get_MAX_SIM_CLKs(){MAX_SIM_CLKs} + sub get_MAX_PCK_SIZ(){MAX_PCK_SIZ} sub check_inserted_ratios { @@ -88,7 +76,7 @@ sub get_injection_ratios{ my $button=def_image_button("icons/right.png",'Check'); $button->signal_connect("clicked" => sub { my $text= $entry->get_text(); - my $r=check_inserted_ratios($text); + my $r=check_inserted_ratios($text); if(defined $r){ my $all= join (',',@$r); message_dialog ("$all" ); @@ -104,15 +92,15 @@ sub get_injection_ratios{ } sub get_noc_configuration{ - my ($emulate,$mode,$sample,$set_win) =@_; - if($mode eq "simulate") {get_simulator_noc_configuration(@_); return;} + my ($emulate,$mode,$sample,$set_win) =@_; + if($mode eq "simulate") {get_simulator_noc_configuration(@_); return;} get_emulator_noc_configuration(@_); } sub get_sof_file_full_addr{ my ($emulate,$sample)=@_; - my $open_in = $emulate->object_get_attribute($sample,"sof_path"); - my $board = $emulate->object_get_attribute($sample,"FPGA_board"); + my $open_in = $emulate->object_get_attribute($sample,"sof_path"); + my $board = $emulate->object_get_attribute($sample,"FPGA_board"); my $file = $emulate->object_get_attribute($sample,"sof_file"); return undef if(!defined ${open_in} || !defined ${board} || !defined $file ); my $sof = "${open_in}/${board}/$file"; @@ -120,19 +108,17 @@ sub get_sof_file_full_addr{ return $sof; } - sub get_emulator_noc_configuration{ - my ($emulate,$mode,$sample,$set_win) =@_; + my ($emulate,$mode,$sample,$set_win) =@_; my $table=def_table(10,2,FALSE); my $row=0; my $traffics="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,shuffle,bit rotation,neighbor"; #TODO hot spot for emulator - #search path + #search path my $dir = Cwd::getcwd(); - my $open_in = abs_path("$ENV{PRONOC_WORK}/emulate/sof"); - attach_widget_to_table ($table,$row,gen_label_in_left("Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), + my $open_in = abs_path("$ENV{PRONOC_WORK}/emulate/sof"); + attach_widget_to_table ($table,$row,gen_label_in_left("Search Path:"),gen_button_message ("Select the Path where the verilator simulation files are located. Different NoC verilated models can be generated using Generate NoC configuration tab.","icons/help.png"), get_dir_in_object ($emulate,$sample,"sof_path",undef,'ref_set_win',1,$open_in)); $row++; - $open_in = $emulate->object_get_attribute($sample,"sof_path"); - + $open_in = $emulate->object_get_attribute($sample,"sof_path"); #select the board my($label,$param,$default,$content,$type,$info); my @dirs = grep {-d} glob("$open_in/*"); @@ -140,22 +126,21 @@ sub get_emulator_noc_configuration{ foreach my $dir (@dirs) { my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); $default=$name; - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - } - attach_widget_to_table ($table,$row,gen_label_in_left("Select FPGA board:"),gen_button_message ("Select the FPGA board. You can add your own FPGA board by adding its configuration file to mpsoc/boards directory","icons/help.png"), + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + } + attach_widget_to_table ($table,$row,gen_label_in_left("Select FPGA board:"),gen_button_message ("Select the FPGA board. You can add your own FPGA board by adding its configuration file to mpsoc/boards directory","icons/help.png"), gen_combobox_object ($emulate,$sample, "FPGA_board", $fpgas, undef,'ref_set_win',1)); $row++; - #select the sram object file - my $board = $emulate->object_get_attribute($sample,"FPGA_board"); + my $board = $emulate->object_get_attribute($sample,"FPGA_board"); my @files; @files = glob "${open_in}/${board}/*" if(defined $board); my $sof_files=""; foreach my $file (@files){ my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - $sof_files="$sof_files,$name" if($suffix eq '.sof'); - } - attach_widget_to_table ($table,$row,gen_label_in_left("Sram Object File:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), - gen_combobox_object ($emulate,$sample, "sof_file", $sof_files, undef,undef,undef)); $row++; + $sof_files="$sof_files,$name" if($suffix eq '.sof'); + } + attach_widget_to_table ($table,$row,gen_label_in_left("Sram Object File:"),gen_button_message ("Select the verilator simulation file. Different NoC simulators can be generated using Generate NoC configuration tab.","icons/help.png"), + gen_combobox_object ($emulate,$sample, "sof_file", $sof_files, undef,undef,undef)); $row++; #attach_widget_to_table ($table,$row,gen_label_in_left("SoF file:"),gen_button_message ("Select the SRAM Object File (sof) for this NoC configration.","icons/help.png"), get_file_name_object ($emulate,$sample,"sof_file",'sof',$open_in)); $row++; my @emulateinfo = ( { label=>'Configuration name:', param_name=>'line_name', type=>'Entry', default_val=>$sample, content=>undef, info=>"NoC configration name. This name will be shown in load-latency graph for this configuration", param_parent=>$sample, ref_delay=> undef}, @@ -172,21 +157,21 @@ sub get_emulator_noc_configuration{ { label=>"Simulator clocks limit:", param_name=>'SIM_CLOCK_LIMIT', type=>'Spin-button', default_val=>100000, content=>"2,".MAX_SIM_CLKs.",1", info=>"Each node stops sending packets when it reaches packet number limit or simulation clock number limit", param_parent=>$sample, ref_delay=>undef, new_status=>undef}, ); my $hot_num=$emulate->object_get_attribute($sample,"HOTSPOT_NUM"); - $hot_num=1 if(!defined $hot_num); + $hot_num=1 if(!defined $hot_num); my $max= ($hot_num>0)? 100/$hot_num: 20; my @hotspot_info=( - { label=>'Hot Spot num:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, - content=>"1,5,1", info=>"Number of hot spot nodes in the network", + { label=>'Hot Spot num:', param_name=>'HOTSPOT_NUM', type=>'Spin-button', default_val=>1, + content=>"1,5,1", info=>"Number of hot spot nodes in the network", param_parent=>$sample, ref_delay=> 1, new_status=>'ref_set_win'}, - { label=>'Hot Spot traffic percentage:', param_name=>'HOTSPOT_PERCENTAGE', type=>'Spin-button', default_val=>1, - content=>"1, $max,1", info=>"If it is set as n then each node sends n % of its traffic to each hotspot node", + { label=>'Hot Spot traffic percentage:', param_name=>'HOTSPOT_PERCENTAGE', type=>'Spin-button', default_val=>1, + content=>"1, $max,1", info=>"If it is set as n then each node sends n % of its traffic to each hotspot node", + param_parent=>$sample, ref_delay=> undef, new_status=>undef}, + { label=>'Hot Spot nodes send enable:', param_name=>'HOTSPOT_SEND', type=>'Combo-box', default_val=>1, + content=>"0,1", info=>"If it is set as 0 then hot spot nodes only recieves packet from other nodes and do not send packets to others", param_parent=>$sample, ref_delay=> undef, new_status=>undef}, - { label=>'Hot Spot nodes send enable:', param_name=>'HOTSPOT_SEND', type=>'Combo-box', default_val=>1, - content=>"0,1", info=>"If it is set as 0 then hot spot nodes only recieves packet from other nodes and do not send packets to others", - param_parent=>$sample, ref_delay=> undef, new_status=>undef}, ); - my @info= ($mode eq "simulate")? @siminfo : @emulateinfo; - my $coltmp=0; + my @info= ($mode eq "simulate")? @siminfo : @emulateinfo; + my $coltmp=0; foreach my $d ( @info) { ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); } @@ -202,8 +187,8 @@ sub get_emulator_noc_configuration{ "Defne the tile number which is hotspt. All other nodes will send [Hot Spot traffic percentage] of their traffic to this node ", $table,$row,undef,1,$sample); } } - my $l= "Injection ratios in flits/clk/Endpoint (%). -E.g. Injection ratio 10% means each endpoint inject one flit every 10 cycles. + my $l= "Injection ratios in flits/clk/Endpoint (%). +E.g. Injection ratio 10% means each endpoint inject one flit every 10 cycles. You can define individual ratios seprating by comma (\',\') or define a range of injection ratios with \$min:\$max:\$step format. As an example defining 2,3,4:10:2 will result in (2,3,4,6,8,10) injection ratios. " ; @@ -213,28 +198,25 @@ sub get_emulator_noc_configuration{ my $ok = def_image_button('icons/select.png','OK'); my $mtable = def_table(10, 1, TRUE); $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable-> attach ($ok , 0, 1, 9, 10,'expand','shrink',2,2); + $mtable-> attach ($ok , 0, 1, 9, 10,'expand','shrink',2,2); add_widget_to_scrolled_win ($mtable,$set_win); $set_win->show_all(); $set_win ->signal_connect (destroy => sub{ - $emulate->object_add_attribute("active_setting",undef,undef); }); - $ok->signal_connect("clicked"=> sub{ #check if sof file has been selected my $s=get_sof_file_full_addr($emulate,$sample); #check if injection ratios are valid my $r=$emulate->object_get_attribute($sample,"ratios"); - if(defined $s && defined $r) { + if(defined $s && defined $r) { $set_win->hide; $emulate->object_add_attribute("active_setting",undef,undef); set_gui_status($emulate,"ref",1); } else { - if(!defined $s){ my $m=($mode eq 'simulate') ? "Please select NoC verilated file" : "Please select sof file!"; - message_dialog($m); + message_dialog($m); } else { message_dialog("Please define valid injection ratio(s)!"); } @@ -244,21 +226,21 @@ sub get_emulator_noc_configuration{ ##################### # gen_widgets_column -################### +################### sub gen_emulation_column { my ($emulate,$mode, $row_num,$info,$set_win,@charts)=@_; my $table=def_table($row_num,10,FALSE); if(!defined $set_win){ - $set_win=def_popwin_size(40,80,"NoC configuration setting",'percent'); + $set_win=def_popwin_size(40,80,"NoC configuration setting",'percent'); $set_win->signal_connect (delete_event => sub {$emulate->object_add_attribute("active_setting",undef,undef); $set_win->hide_on_delete }); } else{ my @childs = $set_win->get_children; foreach my $c (@childs){ $c->destroy;} } my $scrolled_win = gen_scr_win_with_adjst ($emulate,"emulation_column"); - add_widget_to_scrolled_win($table,$scrolled_win); + add_widget_to_scrolled_win($table,$scrolled_win); my $row=0; - #title + #title my $title_l =($mode eq "simulate" ) ? "NoC Simulator" : "NoC Emulator"; my $title=gen_label_in_center($title_l); $table->attach ($title , 0, 10, $row, $row+1,'expand','shrink',2,2); $row++; @@ -270,16 +252,16 @@ sub gen_emulation_column { $order{'Name'}=3; $order{'Color'}=4; $order{'Clear'}=5; - $order{'Traffic'}=6; + $order{'Traffic'}=6; $order{'Done'}=7; - foreach my $t (sort keys %order){ + foreach my $t (sort keys %order){ $table->attach (gen_label_in_center($t), $order{$t}, $order{$t}+1, $row, $row+1,'expand','shrink',2,2); } my $traffics="Random,Transposed 1,Transposed 2,Tornado"; $row++; #my $i=0; my $active=$emulate->object_get_attribute("active_setting",undef); - my @samples; + my @samples; @samples =$emulate->object_get_attribute_order("samples"); foreach my $ss (@samples){ my $sample=$ss; @@ -292,26 +274,26 @@ sub gen_emulation_column { my $r=$emulate->object_get_attribute($sample,"ratios"); if(defined $s && defined $name){ $l=def_image_button('icons/diagram.png',$name); - $l-> signal_connect("clicked" => sub{ + $l-> signal_connect("clicked" => sub{ __PACKAGE__->mk_accessors(qw{noc_param}); my $temp = __PACKAGE__->new(); - my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); + my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my $ref=$emulate->object_get_attribute($sample,"noc_info"); + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my $ref=$emulate->object_get_attribute($sample,"noc_info"); if (defined $ref){ - my %noc_info= %$ref; + my %noc_info= %$ref; foreach my $p (sort keys %noc_info){ - $temp->object_add_attribute('noc_param',$p,$noc_info{$p}); + $temp->object_add_attribute('noc_param',$p,$noc_info{$p}); } } show_topology_diagram ($temp); }); my $traffic = def_button("Pattern"); - $traffic-> signal_connect("clicked" => sub{ - my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); + $traffic-> signal_connect("clicked" => sub{ + my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); $emulate->object_add_attribute('noc_param','T1',$T1); $emulate->object_add_attribute('noc_param','T2',$T2); $emulate->object_add_attribute('noc_param','T3',$T3); @@ -324,16 +306,16 @@ sub gen_emulation_column { my ($outbox,$tview)= create_txview(); show_info($tview,"$pattern"); $window->add ($outbox); - $window->show_all(); + $window->show_all(); }); $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); - $table->attach ($traffic, $order{'Traffic'}, $order{'Traffic'}+1, $row, $row+1,'expand','shrink',2,2); + $table->attach ($traffic, $order{'Traffic'}, $order{'Traffic'}+1, $row, $row+1,'expand','shrink',2,2); } else { $l=gen_label_in_left("Define NoC configuration"); - $l->set_markup("Define NoC configuration"); - $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); + $l->set_markup("Define NoC configuration"); + $table->attach ($l, $order{'Name'}, $order{'Name'}+1, $row, $row+1,'expand','shrink',2,2); } - #remove + #remove my $remove=def_image_button("icons/cancel.png"); $table->attach ($remove,$order{'+/-'},$order{'+/-'}+1, $row, $row+1,'expand','shrink',2,2); $remove->signal_connect("clicked"=> sub{ @@ -363,7 +345,7 @@ sub gen_emulation_column { #clear line my $clear = def_image_button('icons/clear.png'); $clear->signal_connect("clicked"=> sub{ - foreach my $chart (@charts){ + foreach my $chart (@charts){ $emulate->object_add_attribute ($sample,"$chart->{result_name}",undef); #print "\$emulate->object_add_attribute ($sample,$chart->{result_name}_result,undef);"; } @@ -375,15 +357,15 @@ sub gen_emulation_column { $table->attach ($run, $order{'Run'}, $order{'Run'}+1, $row, $row+1,'expand','shrink',2,2); $run->signal_connect("clicked"=> sub{ $emulate->object_add_attribute ($sample,"status","run"); - #start the emulator if it is not running + #start the emulator if it is not running my $status= $emulate->object_get_attribute('status',undef); if($status ne 'run'){ run_emulator($emulate,$info) if($mode eq 'emulate'); - run_simulator($emulate,$info) if($mode eq 'simulate'); + run_simulator($emulate,$info) if($mode eq 'simulate'); set_gui_status($emulate,"ref",2); } }); - my $image = gen_noc_status_image($emulate,$sample); + my $image = gen_noc_status_image($emulate,$sample); $table->attach ($image, $order{'Done'},$order{'Done'}+1, $row, $row+1,'expand','shrink',2,2); $row++; } @@ -399,17 +381,14 @@ sub gen_emulation_column { $emulate->object_add_attribute("active_setting",undef,$sample); #get_noc_configuration($emulate,$mode,$sample,$set_win); $emulate->object_add_attribute_order("samples",$sample); - set_gui_status($emulate,"ref",1); - }); + set_gui_status($emulate,"ref",1); + }); return ($scrolled_win,$set_win); } - - ########## # check_sample ########## - sub check_sample{ my ($emulate,$sample,$info)=@_; my $status=1; @@ -418,18 +397,16 @@ sub check_sample{ if(!defined $sof){ #add_info($info, "Error: SoF file has not set for $sample!\n"); add_colored_info($info, "Error: SoF file has not set for $sample!\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); + $emulate->object_add_attribute ($sample,"status","failed"); $status=0; } else { - # ckeck if sof file has info file + # ckeck if sof file has info file my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); my $sof_info= "$path$name.inf"; - # print "\n $sof \t $sof_info\n"; - if(!(-f $sof_info)){ add_colored_info($info, "Error: Could not find $name.inf file in $path. An information file is required for each sof file containig the device name and NoC configuration. Press F3 for more help.\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); + $emulate->object_add_attribute ($sample,"status","failed"); $status=0; }else { #add info my $pp= do $sof_info ; @@ -444,7 +421,6 @@ sub check_sample{ return $status; } - ############# # images ########## @@ -456,35 +432,31 @@ sub get_status_gif{ } elsif ($status eq 'run') { my($width,$hight)=max_win_size(); my $image=($width>=1600)? "icons/hamster_l.gif": - ($width>=1200)? "icons/hamster_m.gif": "icons/hamster_s.gif"; - return show_gif ($image); + ($width>=1200)? "icons/hamster_m.gif": "icons/hamster_s.gif"; + return show_gif ($image); } elsif ($status eq 'programmer_failed') { - return show_gif ("icons/Error.png"); + return show_gif ("icons/Error.png"); } } - sub gen_noc_status_image { my ($emulate,$sample)=@_; - my $status= $emulate->object_get_attribute ($sample,"status"); + my $status= $emulate->object_get_attribute ($sample,"status"); $status='' if(!defined $status); my $image; my $box = def_hbox(TRUE,1); $image = new_image_from_file ("icons/load.gif") if($status eq "run"); $image = def_icon("icons/button_ok.png") if($status eq "done"); $image = def_icon("icons/warning.png") if($status eq "failed"); - - if (defined $image) { + if (defined $image) { $box->pack_start (add_frame_to_image($image), FALSE, FALSE, 0); } return $box; } - ############ # run_emulator ########### - sub run_emulator { my ($emulate,$info)=@_; #my $graph_name="latency_ratio"; @@ -492,7 +464,6 @@ sub run_emulator { $emulate->object_add_attribute('status',undef,'run'); set_gui_status($emulate,"ref",1); show_colored_info($info, "start emulation\n",'blue'); - # #search for available usb blaster # my $cmd = "jtagconfig"; # my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); @@ -503,117 +474,98 @@ sub run_emulator { # $emulate->object_add_attribute('status',undef,'programmer_failed'); # set_gui_status($emulate,"ref",2); # #/***/ -# return; +# return; # }else{ # add_info($info, "find $usb_blaster\n"); # } my @samples =$emulate->object_get_attribute_order("samples"); foreach my $sample (@samples){ - my $status=$emulate->object_get_attribute ($sample,"status"); + my $status=$emulate->object_get_attribute ($sample,"status"); next if($status ne "run"); next if(!check_sample($emulate,$sample,$info)); my $r= $emulate->object_get_attribute($sample,"ratios"); my @ratios=@{check_inserted_ratios($r)}; - #$emulate->object_add_attribute ("sample$i","status","run"); - my $sof=get_sof_file_full_addr($emulate,$sample); + #$emulate->object_add_attribute ("sample$i","status","run"); + my $sof=get_sof_file_full_addr($emulate,$sample); add_info($info, "Programe FPGA device using $sof.sof\n"); my ($name,$path,$suffix) = fileparse("$sof",qr"\..[^.]*$"); my $programmer="$path/program_device.sh"; my $jtag_intfc="$path/jtag_intfc.sh"; if((-f $programmer)==0){ - add_colored_info ($info, " Error: file \"$programmer\" dose not exist. \n",'red'); + add_colored_info ($info, " Error: file \"$programmer\" dose not exist. \n",'red'); $emulate->object_add_attribute('status',undef,'programmer_failed'); - $emulate->object_add_attribute ($sample,"status","failed"); + $emulate->object_add_attribute ($sample,"status","failed"); set_gui_status($emulate,"ref",2); - last; + last; } if((-f $jtag_intfc)==0){ - add_colored_info ($info, " Error: file \"$jtag_intfc\" dose not exist. \n",'red'); + add_colored_info ($info, " Error: file \"$jtag_intfc\" dose not exist. \n",'red'); $emulate->object_add_attribute('status',undef,'programmer_failed'); - $emulate->object_add_attribute ($sample,"status","failed"); + $emulate->object_add_attribute ($sample,"status","failed"); set_gui_status($emulate,"ref",2); - last; + last; } my $cmd = "bash $programmer $sof.sof"; #my $Quartus_bin= $ENV{QUARTUS_BIN}; #my $cmd = "$Quartus_bin/quartus_pgm -c \"$usb_blaster\" -m jtag -o \"p;$sof\""; #my $output = `$cmd 2>&1 1>/dev/null`; # either with backticks #/***/ - my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); + my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("$cmd"); if($exit){#programming FPGA board has failed $emulate->object_add_attribute('status',undef,'programmer_failed'); add_colored_info($info, "$stdout\n",'red'); - $emulate->object_add_attribute ($sample,"status","failed"); + $emulate->object_add_attribute ($sample,"status","failed"); set_gui_status($emulate,"ref",2); next; } #print "$stdout\n"; - # load noc configuration + # load noc configuration foreach my $ratio_in (@ratios){ add_info($info, "Configure packet generators for injection ratio of $ratio_in \% \n"); if(!programe_pck_gens($emulate,$sample,$ratio_in,$info,$jtag_intfc)){ - add_colored_info($info, "Error in programe_pck_gens function\n",'red'); + add_colored_info($info, "Error in programe_pck_gens function\n",'red'); next; } my $r=read_pack_gen($emulate,$sample,$info,$jtag_intfc,$ratio_in); next if (!defined $r); set_gui_status($emulate,"ref",2); } - $emulate->object_add_attribute ($sample,"status","done"); - + $emulate->object_add_attribute ($sample,"status","done"); } - add_colored_info($info, "End emulation!\n",'blue'); $emulate->object_add_attribute('status',undef,'ideal'); set_gui_status($emulate,"ref",1); } - - - - - ############## # process_notebook_gen ############## - - sub process_notebook_gen{ my ($emulate,$info,$mode,$set_win,@charts)=@_; my $notebook = gen_notebook(); $notebook->set_tab_pos ('left'); $notebook->set_scrollable(TRUE); #$notebook->can_focus(FALSE); - my $page1; ($page1,$set_win)=gen_emulation_column($emulate, $mode,10,$info,$set_win,@charts); $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run emulator ")) if($mode eq "emulate"); $notebook->append_page ($page1,gen_label_with_mnemonic (" _Run simulator ")) if($mode eq "simulate"); - - my $page2=get_noc_setting_gui ($emulate,$info,$mode); my $tt=($mode eq "emulate")? " _Generate NoC \nEmulation Model" : " _Generate NoC \nSimulation Model" ; $notebook->append_page ($page2,gen_label_with_mnemonic ($tt)); - - - - my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($emulate,"process_sc_win")); - $scrolled_win->show_all; - my $page_num=$emulate->object_get_attribute ("process_notebook","currentpage"); + my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($emulate,"process_sc_win")); + $scrolled_win->show_all; + my $page_num=$emulate->object_get_attribute ("process_notebook","currentpage"); $notebook->set_current_page ($page_num) if(defined $page_num); - $notebook->signal_connect( 'switch-page'=> sub{ + $notebook->signal_connect( 'switch-page'=> sub{ $emulate->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber - }); - return ($scrolled_win,$set_win); - } - sub get_noc_setting_gui { my ($emulate,$info_text,$mode)=@_; - my $table=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; + my $table=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; my $scrolled_win = gen_scr_win_with_adjst ($emulate,"noc_setting_gui"); add_widget_to_scrolled_win($table,$scrolled_win); my $row=noc_config ($emulate,$table,$info_text); @@ -641,7 +593,7 @@ sub get_noc_setting_gui { ); } my $coltmp=0; - foreach my $d (@fpgainfo) { + foreach my $d (@fpgainfo) { ($row,$coltmp)=add_param_widget ($emulate, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay}); } my $maintable=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; @@ -654,14 +606,14 @@ sub get_noc_setting_gui { $maintable->attach ($generate, 0,2, 9, 10,'expand','shrink',2,2); $maintable->attach ($diagram, 2,4, 9, 10,'expand','shrink',2,2); $maintable->attach ($import, 4,6, 9, 10,'expand','shrink',2,2); - $diagram-> signal_connect("clicked" => sub{ + $diagram-> signal_connect("clicked" => sub{ show_topology_diagram ($emulate); }); $generate->signal_connect ('clicked'=> sub{ generate_sof_file($emulate,$info_text) if($mode eq "emulate"); generate_sim_bin_file($emulate,$info_text) if($mode eq "simulate"); }); - $import-> signal_connect("clicked" => sub{ + $import-> signal_connect("clicked" => sub{ import_noc_info_file($emulate,$mode); }); $scrolled_win->show_all; @@ -672,9 +624,8 @@ sub import_noc_info_file{ my ($self,$mode)=@_; my $file; my $dialog = gen_file_dialog(undef,'inf'); - my $open_in = ($mode ne "emulate" ) ? abs_path("$ENV{'PRONOC_WORK'}/simulate") : abs_path("$ENV{'PRONOC_WORK'}/emulate"); - $dialog->set_current_folder ($open_in); + $dialog->set_current_folder ($open_in); if ( "ok" eq $dialog->run ) { my $status=1; $file = $dialog->get_filename; @@ -687,128 +638,98 @@ sub import_noc_info_file{ my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); my $attr1 = ($mode ne "emulate" ) ? 'sim_param' : 'fpga_param'; $self->object_add_attribute ($attr1,'SAVE_NAME',$name); - set_gui_status($self,"ref",1); - } + } } - $dialog->destroy; + $dialog->destroy; } ########## # generate_sof_file ########## - - sub generate_sof_file { my ($self,$info)=@_; - my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); + my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; my $top = "$target_dir/src_verilog/${name}_top.v"; - if (!defined $name){ message_dialog("Please define the Save as filed!"); return; } - #copy all noc source codes my @files = ( -'/mpsoc/rtl/src_emulate/rtl/', -'/mpsoc/rtl/src_peripheral/jtag/jtag_wb/', +'/mpsoc/rtl/src_emulate/rtl/', +'/mpsoc/rtl/src_peripheral/jtag/jtag_wb/', '/mpsoc/rtl/src_peripheral/ram/', '/mpsoc/rtl/main_comp.v', '/mpsoc/rtl/arbiter.v', '/mpsoc/rtl/pronoc_def.v', '/mpsoc/rtl/src_topology/', '/mpsoc/rtl/src_noc/'); - my $dir = Cwd::getcwd(); my $project_dir = abs_path("$dir/../../"); my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("mkdir -p $target_dir/src_verilog" ); copy_file_and_folders(\@files,$project_dir,"$target_dir/src_verilog/lib/"); - - #generate parameters for emulator_top.v file gen_noc_localparam_v_file($self,"$target_dir/src_verilog/lib/src_noc/"); - open(FILE, ">$top") || die "Can not open: $!"; print FILE create_emulate_top($self,$name,$top); close(FILE) || die "Error closing file: $!"; select_compiler($self,$name,$top,$target_dir,\&save_the_sof_file); - return; } sub create_emulate_top{ my ($self,$name,$top)=@_; my $top_v= get_license_header("$top"); - $top_v ="$top_v - `timescale 1ns/1ps - module ${name}_top( output done_led, output noc_reset_led, output jtag_reset_led, input reset, input clk -); - - +); localparam - STATISTIC_VJTAG_INDEX=124, + STATISTIC_VJTAG_INDEX=124, PATTERN_VJTAG_INDEX=125, - COUNTER_VJTAG_INDEX=126, + COUNTER_VJTAG_INDEX=126, DONE_RESET_VJTAG_INDEX=127; - - - - wire reset_noc, reset_injector, reset_noc_sync, reset_injector_sync, done; wire jtag_reset_injector, jtag_reset_noc; wire start_o; wire done_time_limit; - - assign done_led = done | done_time_limit; + assign done_led = done | done_time_limit; assign noc_reset_led= reset_noc; assign jtag_reset_led = reset_injector; - - - // two reset sources which can be controled using jtag. One for reseting NoC another packet injectors jtag_source_probe #( .VJTAG_INDEX(DONE_RESET_VJTAG_INDEX), .Dw(2) //source/probe width in bits - )the_reset( + )the_reset( .probe({done_time_limit,done}), .source({jtag_reset_injector,jtag_reset_noc}) ); - - assign reset_noc = (jtag_reset_noc | reset); - assign reset_injector = (jtag_reset_injector | reset); - + assign reset_injector = (jtag_reset_injector | reset); altera_reset_synchronizer noc_rst_sync ( - .reset_in(reset_noc), + .reset_in(reset_noc), .clk(clk), .reset_out(reset_noc_sync) ); - - altera_reset_synchronizer inject_rst_sync ( - .reset_in(reset_injector), + .reset_in(reset_injector), .clk(clk), .reset_out(reset_injector_sync) ); - //noc emulator - noc_emulator #( - .STATISTIC_VJTAG_INDEX(STATISTIC_VJTAG_INDEX), + .STATISTIC_VJTAG_INDEX(STATISTIC_VJTAG_INDEX), .PATTERN_VJTAG_INDEX(PATTERN_VJTAG_INDEX), - .NOC_ID(0) + .NOC_ID(0) ) noc_emulate_top ( @@ -818,44 +739,36 @@ sub create_emulate_top{ .start_o(start_o), .done(done) ); - - - //clock counter - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2= clk_limit); endmodule "; @@ -863,13 +776,11 @@ sub create_emulate_top{ } sub save_the_sof_file{ - my $self=shift; - my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); + my $name=$self->object_get_attribute ('fpga_param',"SAVE_NAME"); my $sofdir="$ENV{PRONOC_WORK}/emulate/sof"; my $fpga_board=$self->object_get_attribute('compile','board'); my $target_dir = "$ENV{'PRONOC_WORK'}/emulate/$name"; - mkpath("$sofdir/$fpga_board/",1,01777); open(FILE, ">$sofdir/$fpga_board/$name.inf") || die "Can not open: $!"; print FILE perl_file_header("$name.inf"); @@ -877,56 +788,43 @@ sub save_the_sof_file{ $pp{'noc_param'}= $self->{'noc_param'}; $pp{'fpga_param'}= $self->{'fpga_param'}; print FILE Data::Dumper->Dump([\%pp],["emulate_info"]); - close(FILE) || die "Error closing file: $!"; - - - #find $dir_name -name \*.sof -exec cp '{}' $sofdir/$fpga_board/$save_name.sof" + close(FILE) || die "Error closing file: $!"; + #find $dir_name -name \*.sof -exec cp '{}' $sofdir/$fpga_board/$save_name.sof" my @files = File::Find::Rule->file() - ->name( '*.sof' ) - ->in( "$target_dir" ); - copy($files[0],"$sofdir/$fpga_board/$name.sof") or do { - my $err= "Error copy($files[0] , $sofdir/$fpga_board/$name.sof"; - print "$err\n"; - message_dialog($err,'error'); + ->name( '*.sof' ) + ->in( "$target_dir" ); + copy($files[0],"$sofdir/$fpga_board/$name.sof") or do { + my $err= "Error copy($files[0] , $sofdir/$fpga_board/$name.sof"; + print "$err\n"; + message_dialog($err,'error'); return; }; #copy the board's programming and jtag interface files - my $board_name=$self->object_get_attribute('compile','board'); - #copy board jtag_intfc.sh file + #copy board jtag_intfc.sh file copy("../boards/Altera/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh"); #print "../boards/$board_name/jtag_intfc.sh","$sofdir/$fpga_board/jtag_intfc.sh\n"; - #add argument run to jtag_interface file + #add argument run to jtag_interface file my $runarg=' - if [ $# -ne 0 ] - then + then $JTAG_INTFC $1 fi '; append_text_to_file ("$sofdir/$fpga_board/jtag_intfc.sh",$runarg ); - - - - - #copy board program_device.sh file + #copy board program_device.sh file copy("../boards/Altera/$board_name/program_device.sh","$sofdir/$fpga_board/program_device.sh"); - - - - message_dialog("sof file has been generated successfully"); + message_dialog("sof file has been generated successfully"); } - - ########## # save_emulation ########## sub save_emulation { my ($emulate)=@_; # read emulation name - my $name=$emulate->object_get_attribute ("emulate_name",undef); - my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; + my $name=$emulate->object_get_attribute ("emulate_name",undef); + my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; if ($s == 0){ message_dialog("Please set emulation name!"); return 0; @@ -943,110 +841,88 @@ sub save_emulation { ############# # load_emulation ############ - sub load_emulation { my ($emulate,$info)=@_; my $file; - my $dialog = gen_file_dialog (undef, 'EML'); + my $dialog = gen_file_dialog (undef, 'EML'); my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/emulate"); - + $dialog->set_current_folder ("$dir/lib/emulate"); if ( "ok" eq $dialog->run ) { $file = $dialog->get_filename; my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); if($suffix eq '.EML'){ - my ($pp,$r,$err) = regen_object($file); - if ($r ){ + if ($r ){ add_colored_info($info,"**Error reading $file file: $err\n",'red'); - $dialog->destroy; + $dialog->destroy; return; - } - + } clone_obj($emulate,$pp); - #message_dialog("done!"); - } + #message_dialog("done!"); + } } $dialog->destroy; } - - sub update_result { my ($self,$sample,$name,$x,$y,$z)=@_; my $ref=$self->object_get_attribute ($sample,$name); my %results; %results= %{$ref} if(defined $ref); if(!defined $z) {$results{$x}=$y;} - else {$results{$x}{$y}=$z;} + else {$results{$x}{$y}=$z;} $self->object_add_attribute ($sample,$name,\%results); -} - - - +} sub gen_sim_parameter_h { my ($param_h,$includ_h,$ne,$nr,$router_p,$fifow)=@_; - $param_h =~ s/\d\'b/ /g; my $text= " #ifndef INCLUDE_PARAM - #define INCLUDE_PARAM \n \n - - $param_h - - #define NE $ne - #define NR $nr - #define ROUTER_P_NUM $router_p - + #define INCLUDE_PARAM \n \n + $param_h + #define NE $ne + #define NR $nr + #define ROUTER_P_NUM $router_p extern Vtraffic *traffic[NE]; extern Vpck_inj *pck_inj[NE]; extern int reset,clk; - - //simulation parameter + //simulation parameter #define MAX_RATIO ".MAX_RATIO." #define AVG_LATENCY_METRIC \"HEAD_2_TAIL\" #define TIMSTMP_FIFO_NUM $fifow - $includ_h -\n \n \#endif" ; - return $text; -} +\n \n \#endif" ; + return $text; +} sub gen_noc_sim_param { my $simulate=shift; my $fifow=$simulate->object_get_attribute('fpga_param','TIMSTMP_FIFO_NUM'); - $fifow= '16' if (!defined $fifow); - return " - //simulation parameter + //simulation parameter //localparam MAX_RATIO = ".MAX_RATIO."; localparam MAX_PCK_NUM = ".MAX_SIM_CLKs."; - localparam MAX_PCK_SIZ = ".MAX_PCK_SIZ."; + localparam MAX_PCK_SIZ = ".MAX_PCK_SIZ."; localparam MAX_SIM_CLKs= ".MAX_SIM_CLKs."; - localparam TIMSTMP_FIFO_NUM = $fifow; + localparam TIMSTMP_FIFO_NUM = $fifow; "; - } - sub gen_noc_localparam_v_file { my ($self,$dst_path,$sample,$noc_id)=@_; - $noc_id="" if(!defined $noc_id); + $noc_id="" if(!defined $noc_id); # generate NoC parameter file my ($noc_param,$pass_param)=gen_noc_param_v($self,$sample,$noc_id); my $header=autogen_warning().get_license_header("noc_localparam.v"); open(FILE, ">${dst_path}/noc_localparam.v") || die "Can not open: $!"; my $sim =gen_noc_sim_param($self); print FILE "$header - - \`ifdef NOC_LOCAL_PARAM \n \n - $noc_param - + \`ifdef NOC_LOCAL_PARAM \n \n + $noc_param $sim - -\n \n \`endif"; +\n \n \`endif"; close FILE; } @@ -1054,9 +930,9 @@ sub noc_emulate_ctrl{ my ($self,$info)=@_; my $generate = def_image_button('icons/forward.png','Run all',FALSE,1); my ($entrybox,$entry ) =gen_save_load_widget ( - $self, #the object + $self, #the object "Name",#the label shown for setting configuration - "emulate_name",#the key name for saveing the setting configuration in object + "emulate_name",#the key name for saveing the setting configuration in object "Experiment name",#the label full name show in tool tips undef,#Where the generted RTL files are loacted. Undef if not aplicaple 0,#check the given name match the SoC or mpsoc name rules @@ -1064,15 +940,13 @@ sub noc_emulate_ctrl{ "EML",#the extenstion given for configuration seting file \&load_emulation, $info); - - $generate-> signal_connect("clicked" => sub{ + $generate-> signal_connect("clicked" => sub{ my @samples =$self->object_get_attribute_order("samples"); foreach my $sample (@samples){ $self->object_add_attribute ($sample,"status","run"); } run_emulator($self,$info); }); - my $table = def_table (1, 12, FALSE); $table->attach ($entrybox, 0, 5, 0,1,'expand','shrink',2,2); $table->attach ($generate, 5, 8, 0,1,'expand','shrink',2,2); @@ -1110,15 +984,15 @@ sub emulator_main{ $main_table->set_row_spacings (4); $main_table->set_col_spacings (1); my $ctrl = noc_emulate_ctrl($emulate,$info); - my $image = get_status_gif($emulate); + my $image = get_status_gif($emulate); my $v1=gen_vpaned($conf_box,.45,$image); my $v2=gen_vpaned($infobox,.2,$chart); my $h1=gen_hpaned($v1,.4,$v2); #$table->attach_defaults ($event_box, $col, $col+1, $row, $row+1); $main_table->attach_defaults ($h1 , 0, 12, 0,24); $main_table->attach ($ctrl, 0,12, 24,25,'fill','fill',2,2); - #check soc status every 0.5 second. referesh device table if there is any changes - Glib::Timeout->add (100, sub{ + #check soc status every 0.5 second. referesh device table if there is any changes + Glib::Timeout->add (100, sub{ my ($state,$timeout)= get_gui_status($emulate); if ($timeout>0){ $timeout--; @@ -1132,15 +1006,15 @@ sub emulator_main{ $ctrl->destroy(); $conf_box->destroy(); $chart->destroy(); - $image->destroy(); + $image->destroy(); $image = get_status_gif($emulate); ($conf_box,$set_win)=process_notebook_gen($emulate,$info,"emulate",$set_win, @charts); $chart =gen_multiple_charts ($emulate,\@pages,\@charts,.4); $ctrl = noc_emulate_ctrl($emulate,$info); $main_table->attach ($ctrl, 0,12, 24,25,'fill','fill',2,2); $v1 -> pack1($conf_box, TRUE, TRUE); - $v1 -> pack2($image, TRUE, TRUE); - $v2 -> pack2($chart, TRUE, TRUE); + $v1 -> pack2($image, TRUE, TRUE); + $v2 -> pack2($chart, TRUE, TRUE); $conf_box->show_all(); $main_table->show_all(); set_gui_status($emulate,"ideal",0); @@ -1148,6 +1022,4 @@ sub emulator_main{ } ); return add_widget_to_scrolled_win($main_table); } - - - +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/emulator.pm b/mpsoc/perl_gui/lib/perl/emulator.pm index 9b83acb..ad66939 100755 --- a/mpsoc/perl_gui/lib/perl/emulator.pm +++ b/mpsoc/perl_gui/lib/perl/emulator.pm @@ -1,126 +1,97 @@ #!/usr/bin/perl -w -I .. ############################################################################### -# # File: emulator.pm -# -# ############################################################################### + use warnings; use strict; - - - package emulator; sub uniq { - my %seen; - return grep { !$seen{$_}++ } @_; + my %seen; + return grep { !$seen{$_}++ } @_; } sub emulator_new { # be backwards compatible with non-OO call my $class = ("ARRAY" eq ref $_[0]) ? "mpsoc" : shift; my $self; - - $self = {}; $self->{file_name} = (); # information on each file $self->{samples} = (); emulator_initial_setting($self); - - bless($self,$class); - - return $self; -} +} sub emulator_initial_setting{ - my $self=shift; - $self->{status}="ideal"; - $self->{setting}{show_noc_setting}=1; - $self->{setting}{show_adv_setting}=0; - $self->{setting}{show_tile_setting}=0; - $self->{setting}{soc_path}="lib/soc"; - + my $self=shift; + $self->{status}="ideal"; + $self->{setting}{show_noc_setting}=1; + $self->{setting}{show_adv_setting}=0; + $self->{setting}{show_tile_setting}=0; + $self->{setting}{soc_path}="lib/soc"; } - - - - - - - sub object_add_attribute{ - my ($self,$attribute1,$attribute2,$value)=@_; - if(!defined $attribute2){$self->{$attribute1}=$value;} - else {$self->{$attribute1}{$attribute2}=$value;} - + my ($self,$attribute1,$attribute2,$value)=@_; + if(!defined $attribute2){$self->{$attribute1}=$value;} + else {$self->{$attribute1}{$attribute2}=$value;} } sub object_get_attribute{ - my ($self,$attribute1,$attribute2)=@_; - if(!defined $attribute2) {return $self->{$attribute1};} - return $self->{$attribute1}{$attribute2}; - - + my ($self,$attribute1,$attribute2)=@_; + if(!defined $attribute2) {return $self->{$attribute1};} + return $self->{$attribute1}{$attribute2}; } sub object_add_attribute_order{ - my ($self,$attribute,@param)=@_; - my $r = $self->{'parameters_order'}{$attribute}; - my @a; - @a = @{$r} if(defined $r); - push (@a,@param); - @a=uniq(@a); - $self->{'parameters_order'}{$attribute} =\@a; + my ($self,$attribute,@param)=@_; + my $r = $self->{'parameters_order'}{$attribute}; + my @a; + @a = @{$r} if(defined $r); + push (@a,@param); + @a=uniq(@a); + $self->{'parameters_order'}{$attribute} =\@a; } sub object_get_attribute_order{ - my ($self,$attribute)=@_; - my @array; - @array = @{$self->{parameters_order}{$attribute}} if (defined $self->{parameters_order}{$attribute}); - return uniq (@array); + my ($self,$attribute)=@_; + my @array; + @array = @{$self->{parameters_order}{$attribute}} if (defined $self->{parameters_order}{$attribute}); + return uniq (@array); } - sub object_delete_attribute_order{ - my ($self,$attribute,@param)=@_; - my @array=object_get_attribute_order($self,$attribute); - foreach my $p (@param){ - @array=remove_scolar_from_array(\@array,$p); - - } - $self->{'parameters_order'}{$attribute}=[]; - object_add_attribute_order($self,$attribute,@array); + my ($self,$attribute,@param)=@_; + my @array=object_get_attribute_order($self,$attribute); + foreach my $p (@param){ + @array=remove_scolar_from_array(\@array,$p); + } + $self->{'parameters_order'}{$attribute}=[]; + object_add_attribute_order($self,$attribute,@array); } sub object_remove_attribute{ - my ($self,$attribute1,$attribute2)=@_; - if(!defined $attribute2){ - delete $self->{$attribute1} if ( exists( $self->{$attribute1})); - } - else { - delete $self->{$attribute1}{$attribute2} if ( exists( $self->{$attribute1}{$attribute2})); ; - - } - + my ($self,$attribute1,$attribute2)=@_; + if(!defined $attribute2){ + delete $self->{$attribute1} if ( exists( $self->{$attribute1})); + } + else { + delete $self->{$attribute1}{$attribute2} if ( exists( $self->{$attribute1}{$attribute2})); ; + } } - -sub remove_scolar_from_array{ - my ($array_ref,$item)=@_; - my @array=@{$array_ref}; - my @new; - foreach my $p (@array){ - if($p ne $item ){ - push(@new,$p); - } - } - return @new; -} - - -1 +sub remove_scolar_from_array{ + my ($array_ref,$item)=@_; + my @array=@{$array_ref}; + my @new; + foreach my $p (@array){ + if($p ne $item ){ + push(@new,$p); + } + } + return @new; +} +1; diff --git a/mpsoc/perl_gui/lib/perl/gdown.pl b/mpsoc/perl_gui/lib/perl/gdown.pl index 2b62e76..ac520e9 100755 --- a/mpsoc/perl_gui/lib/perl/gdown.pl +++ b/mpsoc/perl_gui/lib/perl/gdown.pl @@ -11,94 +11,72 @@ # use strict; #use POSIX; - use FindBin; use lib $FindBin::Bin; - - - sub execute_command { - my ($TEMP,$FILENAME,$URL)=@_; + my ($TEMP,$FILENAME,$URL)=@_; my $COMMAND="wget --progress=dot:giga --no-check-certificate --load-cookie $TEMP --save-cookie $TEMP \"$URL\""; $COMMAND.=" -O \"$FILENAME\"" if $FILENAME ne ''; my $cmd = "xterm -e bash -c \'$COMMAND; sleep 5\'"; - #print "command = $cmd\n"; - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - message_dialog("Error: $stderr",'error'); + if(length $stderr>1){ + message_dialog("Error: $stderr",'error'); } return 1; } sub download_from_google_drive{ - my ($URL,$FILENAME)=@_; - my ($name,$path,$suffix) = fileparse("$FILENAME",qr"\..[^.]*$"); - my $TEMP="$ENV{PRONOC_WORK}/tmp/$name.cookie.temp"; - my $COMMAND; - my $confirm; - my $check; - - - die "\n./gdown.pl 'gdrive file url' [desired file name]\n\n" if $URL eq ''; - - - - - $FILENAME='gdown.'.strftime("%Y%m%d%H%M%S", localtime).'.'.substr(rand,2) if $FILENAME eq ''; - - if ($URL=~m#^https?://drive.google.com/file/d/([^/]+)#) { - $URL="https://docs.google.com/uc?id=$1&export=download"; - } - elsif ($URL=~m#^https?://drive.google.com/open\?id=([^/]+)#) { - $URL="https://docs.google.com/uc?id=$1&export=download"; - } - - execute_command($TEMP,$FILENAME,$URL); - - while (-s $FILENAME < 100000) { # only if the file isn't download yet - open fFILENAME, '<', $FILENAME; - $check=0; - foreach () { - if (/href="(\/uc\?export=download[^"]+)/) { - $URL='https://docs.google.com'.$1; - $URL=~s/&/&/g; - $confirm=''; - $check=1; - last; - } - if (/confirm=([^;&]+)/) { - $confirm=$1; - $check=1; - last; - } - if (/"downloadUrl":"([^"]+)/) { - $URL=$1; - $URL=~s/\\u003d/=/g; - $URL=~s/\\u0026/&/g; - $confirm=''; - $check=1; - last; - } - } - close fFILENAME; - #die "Couldn't download the file :-(\n" if ($check==0); - if($check == 0 ) { - message_dialog("Error: Couldn't download the file :-(",'error'); - return; - } - - - - $URL=~s/confirm=([^;&]+)/confirm=$confirm/ if $confirm ne ''; - - execute_command($TEMP,$FILENAME,$URL); - } - - unlink $TEMP; - + my ($URL,$FILENAME)=@_; + my ($name,$path,$suffix) = fileparse("$FILENAME",qr"\..[^.]*$"); + my $TEMP="$ENV{PRONOC_WORK}/tmp/$name.cookie.temp"; + my $COMMAND; + my $confirm; + my $check; + die "\n./gdown.pl 'gdrive file url' [desired file name]\n\n" if $URL eq ''; + $FILENAME='gdown.'.strftime("%Y%m%d%H%M%S", localtime).'.'.substr(rand,2) if $FILENAME eq ''; + if ($URL=~m#^https?://drive.google.com/file/d/([^/]+)#) { + $URL="https://docs.google.com/uc?id=$1&export=download"; + } + elsif ($URL=~m#^https?://drive.google.com/open\?id=([^/]+)#) { + $URL="https://docs.google.com/uc?id=$1&export=download"; + } + execute_command($TEMP,$FILENAME,$URL); + while (-s $FILENAME < 100000) { # only if the file isn't download yet + open fFILENAME, '<', $FILENAME; + $check=0; + foreach () { + if (/href="(\/uc\?export=download[^"]+)/) { + $URL='https://docs.google.com'.$1; + $URL=~s/&/&/g; + $confirm=''; + $check=1; + last; + } + if (/confirm=([^;&]+)/) { + $confirm=$1; + $check=1; + last; + } + if (/"downloadUrl":"([^"]+)/) { + $URL=$1; + $URL=~s/\\u003d/=/g; + $URL=~s/\\u0026/&/g; + $confirm=''; + $check=1; + last; + } + } + close fFILENAME; + #die "Couldn't download the file :-(\n" if ($check==0); + if($check == 0 ) { + message_dialog("Error: Couldn't download the file :-(",'error'); + return; + } + $URL=~s/confirm=([^;&]+)/confirm=$confirm/ if $confirm ne ''; + execute_command($TEMP,$FILENAME,$URL); + } + unlink $TEMP; } - 1; diff --git a/mpsoc/perl_gui/lib/perl/graph.pl b/mpsoc/perl_gui/lib/perl/graph.pl index f3d7c4b..1ab5661 100755 --- a/mpsoc/perl_gui/lib/perl/graph.pl +++ b/mpsoc/perl_gui/lib/perl/graph.pl @@ -5,520 +5,379 @@ use GD::Graph::linespoints; use constant::boolean; - - - sub gen_multiple_charts{ - my ($self,$pageref,$charts_ref,$image_scale)=@_; - my @pages=@{$pageref}; - my @charts=@{$charts_ref}; - my $notebook = gen_notebook(); - $notebook->set_scrollable(TRUE); - - - #check if we need to save all graph results - my $save_all_status = $self->object_get_attribute ("graph_save","save_all_result"); - $save_all_status=0 if (!defined $save_all_status); - $self->object_add_attribute ("graph_save","save_all_result",0); - if ($save_all_status ==1){ - my $save_path = $self->object_get_attribute ('sim_param','ALL_RESULT_DIR'); - if (-d $save_path){ - my $results_path = "$save_path/all_results"; - rmtree("$results_path"); - mkpath("$results_path",1,01777); - save_all_results($self,$pageref,$charts_ref,$results_path); - - } - } - - foreach my $page (@pages){ - my @selects; - my $page_id= "P$page->{page_num}"; - my $active = $self->object_get_attribute ($page_id,'active'); - - foreach my $chart (@charts){ - push (@selects,$chart->{graph_name})if($page->{page_num} == $chart->{page_num} ); - - } - $active =$selects[0] if (!defined $active); - - foreach my $chart (@charts){ - my $graph_id= $page_id."$chart->{graph_name}"; - - if($active eq $chart->{graph_name} && $page->{page_num} == $chart->{page_num}){ - - my $p= gen_graph ($self,$chart,$image_scale,@selects); - $notebook->append_page ($p,gen_label_with_mnemonic ($page->{page_name})); - $self->object_add_attribute ($graph_id,'type',$chart->{type}); - } - - } - - - #print "$page->{page_name} : @selects \n"; - - } - - - - - my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($self,"chart_sc_win")); - $scrolled_win->show_all; - - my $page_num=$self->object_get_attribute ("chart_notebook","currentpage"); - $notebook->set_current_page ($page_num) if(defined $page_num); - $notebook->signal_connect( 'switch-page'=> sub{ - $self->object_add_attribute ("chart_notebook","currentpage",$_[2]); #save the new pagenumber - #print "$self->object_add_attribute (\"chart_notebook\",\"currentpage\",$_[2]);\n"; - }); - - #return ($scrolled_win,$set_win); - return $scrolled_win; - - - - + my ($self,$pageref,$charts_ref,$image_scale)=@_; + my @pages=@{$pageref}; + my @charts=@{$charts_ref}; + my $notebook = gen_notebook(); + $notebook->set_scrollable(TRUE); + #check if we need to save all graph results + my $save_all_status = $self->object_get_attribute ("graph_save","save_all_result"); + $save_all_status=0 if (!defined $save_all_status); + $self->object_add_attribute ("graph_save","save_all_result",0); + if ($save_all_status ==1){ + my $save_path = $self->object_get_attribute ('sim_param','ALL_RESULT_DIR'); + if (-d $save_path){ + my $results_path = "$save_path/all_results"; + rmtree("$results_path"); + mkpath("$results_path",1,01777); + save_all_results($self,$pageref,$charts_ref,$results_path); + } + } + foreach my $page (@pages){ + my @selects; + my $page_id= "P$page->{page_num}"; + my $active = $self->object_get_attribute ($page_id,'active'); + foreach my $chart (@charts){ + push (@selects,$chart->{graph_name})if($page->{page_num} == $chart->{page_num} ); + } + $active =$selects[0] if (!defined $active); + foreach my $chart (@charts){ + my $graph_id= $page_id."$chart->{graph_name}"; + if($active eq $chart->{graph_name} && $page->{page_num} == $chart->{page_num}){ + my $p= gen_graph ($self,$chart,$image_scale,@selects); + $notebook->append_page ($p,gen_label_with_mnemonic ($page->{page_name})); + $self->object_add_attribute ($graph_id,'type',$chart->{type}); + } + } + #print "$page->{page_name} : @selects \n"; + } + my $scrolled_win = add_widget_to_scrolled_win($notebook,gen_scr_win_with_adjst($self,"chart_sc_win")); + $scrolled_win->show_all; + my $page_num=$self->object_get_attribute ("chart_notebook","currentpage"); + $notebook->set_current_page ($page_num) if(defined $page_num); + $notebook->signal_connect( 'switch-page'=> sub{ + $self->object_add_attribute ("chart_notebook","currentpage",$_[2]); #save the new pagenumber + #print "$self->object_add_attribute (\"chart_notebook\",\"currentpage\",$_[2]);\n"; + }); + #return ($scrolled_win,$set_win); + return $scrolled_win; } - sub save_all_results{ - my ($self,$pageref,$charts_ref,$results_path)=@_; - my @pages=@{$pageref}; - my @charts=@{$charts_ref}; - foreach my $chart (@charts){ - my $result_name= "$chart->{result_name}"; - my $charttype= "$chart->{type}"; - - if($charttype eq '2D_line'){ - my $file_name = "$results_path/${result_name}.txt"; - write_graph_results_in_file($self,$file_name,$result_name,undef,$charttype); - next; - };#3d - - my @ratios; - my @x; - - - my @samples =$self->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - - my $ref=$self->object_get_attribute ($sample,$result_name); - if(defined $ref){ - @ratios=get_uniq_keys($ref,@ratios); - - } - - foreach my $ratio (@ratios){ - - my @results; - foreach my $sample2 (@samples){ - my $ref=$self->object_get_attribute ($sample2,"$result_name"); - @x=get_uniq_keys($ref->{$ratio},@x) if(defined $ref); - - } - - my $i=1; - foreach my $sample (@samples){ - my @y; - my $ref=$self->object_get_attribute ($sample,"$result_name"); - if(defined $ref){ - foreach my $v (@x){ - my $w=$ref->{$ratio}->{$v}; - push(@y,$w); - }#for v - $results[$i]=\@y if(scalar @x); - $i++; - }#if - }#sample - $results[0]=\@x if(scalar @x); - my $file_name = "$results_path/${result_name}_r$ratio.txt"; - write_graph_results_in_file($self,$file_name,$result_name,\@results,$charttype); - - }#ratio - }#sample - }#chart - #done saving clear the saving status - - -} + my ($self,$pageref,$charts_ref,$results_path)=@_; + my @pages=@{$pageref}; + my @charts=@{$charts_ref}; + foreach my $chart (@charts){ + my $result_name= "$chart->{result_name}"; + my $charttype= "$chart->{type}"; + if($charttype eq '2D_line'){ + my $file_name = "$results_path/${result_name}.txt"; + write_graph_results_in_file($self,$file_name,$result_name,undef,$charttype); + next; + };#3d + my @ratios; + my @x; + my @samples =$self->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + my $ref=$self->object_get_attribute ($sample,$result_name); + if(defined $ref){ + @ratios=get_uniq_keys($ref,@ratios); + } + foreach my $ratio (@ratios){ + my @results; + foreach my $sample2 (@samples){ + my $ref=$self->object_get_attribute ($sample2,"$result_name"); + @x=get_uniq_keys($ref->{$ratio},@x) if(defined $ref); + } + my $i=1; + foreach my $sample (@samples){ + my @y; + my $ref=$self->object_get_attribute ($sample,"$result_name"); + if(defined $ref){ + foreach my $v (@x){ + my $w=$ref->{$ratio}->{$v}; + push(@y,$w); + }#for v + $results[$i]=\@y if(scalar @x); + $i++; + }#if + }#sample + $results[0]=\@x if(scalar @x); + my $file_name = "$results_path/${result_name}_r$ratio.txt"; + write_graph_results_in_file($self,$file_name,$result_name,\@results,$charttype); + }#ratio + }#sample + }#chart + #done saving clear the saving status +} use Scalar::Util qw(looks_like_number); sub check_numeric { - my ($ref)=@_; - my %r=%$ref; - foreach my $p (sort keys %r){ - return 0 unless (looks_like_number($p)); - } - return 1; -} + my ($ref)=@_; + my %r=%$ref; + foreach my $p (sort keys %r){ + return 0 unless (looks_like_number($p)); + } + return 1; +} sub get_uniq_keys { - my ($ref,@x)=@_; - - if(defined $ref) { - my %r=%$ref; - my $n = check_numeric($ref); - - - push(@x, sort {$a<=>$b} keys %r) if ($n); - push(@x, sort {$a cmp $b} keys %r) unless ($n); - - my @x2; - @x2 = uniq(sort {$a<=>$b} @x) if (scalar @x && $n == 1); - @x2 = uniq(sort {$a cmp $b} @x) if (scalar @x && $n==0); - - return @x2; - } - return @x; + my ($ref,@x)=@_; + if(defined $ref) { + my %r=%$ref; + my $n = check_numeric($ref); + push(@x, sort {$a<=>$b} keys %r) if ($n); + push(@x, sort {$a cmp $b} keys %r) unless ($n); + my @x2; + @x2 = uniq(sort {$a<=>$b} @x) if (scalar @x && $n == 1); + @x2 = uniq(sort {$a cmp $b} @x) if (scalar @x && $n==0); + return @x2; + } + return @x; } - sub gen_graph { - my ($self,$chart,$image_scale,@selects)=@_; - if($chart->{type} eq '2D_line') {return gen_2D_line($self,$chart,@selects);} - if($chart->{type} eq 'Heat-map') {return gen_heat_map($self,$chart,@selects);} - return gen_3D_bar($self,$chart,$image_scale,@selects); + my ($self,$chart,$image_scale,@selects)=@_; + if($chart->{type} eq '2D_line') {return gen_2D_line($self,$chart,@selects);} + if($chart->{type} eq 'Heat-map') {return gen_heat_map($self,$chart,@selects);} + return gen_3D_bar($self,$chart,$image_scale,@selects); } - - - sub gen_heat_map{ - my ($self,$chart,@selects)=@_; - - my $page_id= "P$chart->{page_num}"; - my $graph_id= $page_id."$chart->{graph_name}"; - my $result_name= $chart->{result_name}; - - - my $table = def_table (25, 10, FALSE); - - my $plus = def_image_button('icons/plus.png',undef,TRUE); - my $minues = def_image_button('icons/minus.png',undef,TRUE); - my $setting = def_image_button('icons/setting.png',undef,TRUE); - my $save = def_image_button('icons/save.png',undef,TRUE); - - my $type_combo=gen_combobox_object ($self,"${graph_id}","type","Table,Image",'Table','ref',2); - - - my @samples =$self->object_get_attribute_order("samples"); - @samples = ('-') if (scalar @samples == 0); - my $sample_combx=gen_combobox_object ($self,${graph_id},"sample_sel",join(",", @samples),$samples[0],'ref',2); - my $sample = $self->object_get_attribute("${graph_id}","sample_sel"); - my $ref=$self->object_get_attribute ($sample,$result_name); - my @ratios; - @ratios = get_uniq_keys($ref,@ratios); - @ratios = ('-') if (!defined $ratios[0]); - my $rcnt = join(",", @ratios); - my $ratio_combx=gen_combobox_object ($self,${graph_id},"ratio_sel",$rcnt,$ratios[0],'ref',2); - my $content=join( ',', @selects); - my $active_page=gen_combobox_object ($self,$page_id,"active",$content,$selects[0],'ref',2); - - - - my $t = def_table (25, 10, FALSE); - #my $dotfile= generate_heat_map_dot_file(undef,40); - - - - my $r_sel = $self->object_get_attribute("${graph_id}","ratio_sel"); - my $dat; - $dat= $ref->{$r_sel} if (defined $ref->{$r_sel}); - my $scrolled_win = add_widget_to_scrolled_win($t); - - - my $heatmap_type =$self->object_get_attribute("${graph_id}","type"); - $heatmap_type = 'Table' if (!defined $heatmap_type); - - my $scale= $self->object_get_attribute("${graph_id}","scale"); - if(!defined $scale){ - $scale = .5; - $self->object_add_attribute("${graph_id}","scale", $scale ); - } - - my $diagram; - my $map_info; + my ($self,$chart,@selects)=@_; + my $page_id= "P$chart->{page_num}"; + my $graph_id= $page_id."$chart->{graph_name}"; + my $result_name= $chart->{result_name}; + my $table = def_table (25, 10, FALSE); + my $plus = def_image_button('icons/plus.png',undef,TRUE); + my $minues = def_image_button('icons/minus.png',undef,TRUE); + my $setting = def_image_button('icons/setting.png',undef,TRUE); + my $save = def_image_button('icons/save.png',undef,TRUE); + my $type_combo=gen_combobox_object ($self,"${graph_id}","type","Table,Image",'Table','ref',2); + my @samples =$self->object_get_attribute_order("samples"); + @samples = ('-') if (scalar @samples == 0); + my $sample_combx=gen_combobox_object ($self,${graph_id},"sample_sel",join(",", @samples),$samples[0],'ref',2); + my $sample = $self->object_get_attribute("${graph_id}","sample_sel"); + my $ref=$self->object_get_attribute ($sample,$result_name); + my @ratios; + @ratios = get_uniq_keys($ref,@ratios); + @ratios = ('-') if (!defined $ratios[0]); + my $rcnt = join(",", @ratios); + my $ratio_combx=gen_combobox_object ($self,${graph_id},"ratio_sel",$rcnt,$ratios[0],'ref',2); + my $content=join( ',', @selects); + my $active_page=gen_combobox_object ($self,$page_id,"active",$content,$selects[0],'ref',2); + my $t = def_table (25, 10, FALSE); + #my $dotfile= generate_heat_map_dot_file(undef,40); + my $r_sel = $self->object_get_attribute("${graph_id}","ratio_sel"); + my $dat; + $dat= $ref->{$r_sel} if (defined $ref->{$r_sel}); + my $scrolled_win = add_widget_to_scrolled_win($t); + my $heatmap_type =$self->object_get_attribute("${graph_id}","type"); + $heatmap_type = 'Table' if (!defined $heatmap_type); + my $scale= $self->object_get_attribute("${graph_id}","scale"); + if(!defined $scale){ + $scale = .5; + $self->object_add_attribute("${graph_id}","scale", $scale ); + } + my $diagram; + my $map_info; my $image ="$ENV{PRONOC_WORK}/tmp/heatmap.png"; - if($chart->{'graph_name'} ne 'Select'){ - if ($heatmap_type eq 'Image'){ - - my $regen_img= $self->object_get_attribute("${graph_id}","regen_img"); - $regen_img = 0 if (!defined $regen_img); - if ($regen_img==1){ - my $title= $self->object_get_attribute($page_id,"active"); - generate_heat_map_img_file($dat,$image,$title); - $self->object_add_attribute("${graph_id}","regen_img",0); - } - - show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png") if(-f $image); - - $minues -> signal_connect("clicked" => sub{ - $scale*=.9 if ($scale >0.1); - $self->object_add_attribute("${graph_id}","scale", $scale ); - show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png") if(-f $image); - }); - - $plus -> signal_connect("clicked" => sub{ - $scale*=1.1 if ($scale <10); - $self->object_add_attribute("${graph_id}","scale", $scale ); - show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png") if(-f $image); - }); - - $save-> signal_connect("clicked" => sub{ - my $file; - my $title ='Save as'; - my @extensions=('png'); - my $open_in=undef; - my $dialog=save_file_dialog ($title, @extensions); - $dialog->set_current_folder ($open_in) if(defined $open_in); - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my $ext = $dialog->get_filter; - $ext=$ext->get_name; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; - copy("$image","$file"); - - } - $dialog->destroy; - }); - set_tip($save, "Save graph"); - - - - } - else{ #heatmap table - my $t; - ($t,$map_info)=generate_heat_map_table($dat); - add_widget_to_scrolled_win($t ,$scrolled_win); - $scrolled_win->show_all(); - } - } - - - - - # my $scrolled_win = add_widget_to_scrolled_win($t); - # show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png"); - - - - - - - - + if($chart->{'graph_name'} ne 'Select'){ + if ($heatmap_type eq 'Image'){ + my $regen_img= $self->object_get_attribute("${graph_id}","regen_img"); + $regen_img = 0 if (!defined $regen_img); + if ($regen_img==1){ + my $title= $self->object_get_attribute($page_id,"active"); + generate_heat_map_img_file($dat,$image,$title); + $self->object_add_attribute("${graph_id}","regen_img",0); + } + show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png") if(-f $image); + $minues -> signal_connect("clicked" => sub{ + $scale*=.9 if ($scale >0.1); + $self->object_add_attribute("${graph_id}","scale", $scale ); + show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png") if(-f $image); + }); + $plus -> signal_connect("clicked" => sub{ + $scale*=1.1 if ($scale <10); + $self->object_add_attribute("${graph_id}","scale", $scale ); + show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png") if(-f $image); + }); + $save-> signal_connect("clicked" => sub{ + my $file; + my $title ='Save as'; + my @extensions=('png'); + my $open_in=undef; + my $dialog=save_file_dialog ($title, @extensions); + $dialog->set_current_folder ($open_in) if(defined $open_in); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my $ext = $dialog->get_filter; + $ext=$ext->get_name; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; + copy("$image","$file"); + } + $dialog->destroy; + }); + set_tip($save, "Save graph"); + } + else{ #heatmap table + my $t; + ($t,$map_info)=generate_heat_map_table($dat); + add_widget_to_scrolled_win($t ,$scrolled_win); + $scrolled_win->show_all(); + } + } + # my $scrolled_win = add_widget_to_scrolled_win($t); + # show_diagram ($self,$scrolled_win,${graph_id},"heatmap.png"); $table->attach_defaults ($scrolled_win , 0, 9, 0, 24); - my $row=0; - - - $type_combo-> signal_connect("changed" => sub{ - $self->object_add_attribute("${graph_id}","regen_img",1); - - }); - - - $table->attach ($active_page, 9, 10, $row, $row+1,'shrink','shrink',2,2);$row++; - $table->attach ($sample_combx, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach (gen_label_in_center("Injection-Ratio/"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach (gen_label_in_center("Task-file index"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($ratio_combx, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + my $row=0; + $type_combo-> signal_connect("changed" => sub{ + $self->object_add_attribute("${graph_id}","regen_img",1); + }); + $table->attach ($active_page, 9, 10, $row, $row+1,'shrink','shrink',2,2);$row++; + $table->attach ($sample_combx, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach (gen_label_in_center("Injection-Ratio/"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach (gen_label_in_center("Task-file index"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($ratio_combx, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; $table->attach (gen_label_in_center("Graph-Type"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; $table->attach ($type_combo, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - - if ($heatmap_type eq 'Image'){ - $table->attach ($plus , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($minues, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($save, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - }elsif(defined $map_info){ - $table->attach ($map_info , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row+=6; - - } - #$table->attach ($setting, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - - while ($row<10){ - my $tmp=gen_label_in_left(''); - $table->attach_defaults ($tmp, 9, 10, $row, $row+1);$row++; - } - + if ($heatmap_type eq 'Image'){ + $table->attach ($plus , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($minues, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($save, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + }elsif(defined $map_info){ + $table->attach ($map_info , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row+=6; + } + #$table->attach ($setting, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + while ($row<10){ + my $tmp=gen_label_in_left(''); + $table->attach_defaults ($tmp, 9, 10, $row, $row+1);$row++; + } return $table; - - - - - } - sub gen_3D_bar{ - my ($self,$chart,$image_scale,@selects)=@_; - # $image_scale = .4 if (!defined $image_scale); - my($width,$hight)=max_win_size(); - my $page_id= "P$chart->{page_num}"; - my $graph_id= $page_id."$chart->{graph_name}"; - #my $graph_name=$chart->{graph_name}; - my $result_name= $chart->{result_name}; - - my @legend_keys; - - - my @results; - $results[0]= [0]; - $results[1]= [0]; - #$results[2]= [0]; - - - - my $legend_info="This attribute controls placement of the legend within the graph image. The value is supplied as a two-letter string, where the first letter is placement (a B or an R for bottom or right, respectively) and the second is alignment (L, R, C, T, or B for left, right, center, top, or bottom, respectively). "; - -my $fontsize="Tiny,Small,MediumBold,Large,Giant"; - - - -my @ginfo = ( -#{ label=>"Graph Title", param_name=>"G_Title", type=>"Entry", default_val=>undef, content=>undef, info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>undef }, -{ label=>"Y Axix Title", param_name=>"Y_Title", type=>"Entry", default_val=>$chart->{"Y_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>undef }, - { label=>"X Axix Title", param_name=>"X_Title", type=>"Entry", default_val=>$chart->{"X_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" ,ref_delay=>undef }, - { label=>"legend placement", param_name=>"legend_placement", type=>'Combo-box', default_val=>'BL', content=>"BL,BC,BR,RT,RC,RB", info=>$legend_info, param_parent=>"${graph_id}_param" , ref_delay=>1}, - - { label=>"Y min", param_name=>"Y_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"Y axix minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, - { label=>"X min", param_name=>"X_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"X axix minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, -{ label=>"X max", param_name=>"X_MAX", type=>'Spin-button', default_val=>100, content=>"0,1024,1", info=>"X axix maximum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, - { label=>"Line Width", param_name=>"LINEw", type=>'Spin-button', default_val=>3, content=>"1,20,1", info=>undef, param_parent=>"${graph_id}_param" , ref_delay=> 5}, -#{ label=>"Y Axis Values", param_name=>"y_value", type=>'Combo-box', default_val=>'Original', content=>"Original,Normalized to 1,Normalized to 100", info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>1}, -{ label=>"legend font size", param_name=>"legend_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, -{ label=>"label font size", param_name=>"label_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, - { label=>"label font size", param_name=>"x_axis_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, -); - + my ($self,$chart,$image_scale,@selects)=@_; + # $image_scale = .4 if (!defined $image_scale); + my($width,$hight)=max_win_size(); + my $page_id= "P$chart->{page_num}"; + my $graph_id= $page_id."$chart->{graph_name}"; + #my $graph_name=$chart->{graph_name}; + my $result_name= $chart->{result_name}; + my @legend_keys; + my @results; + $results[0]= [0]; + $results[1]= [0]; + #$results[2]= [0]; + my $legend_info="This attribute controls placement of the legend within the graph image. The value is supplied as a two-letter string, where the first letter is placement (a B or an R for bottom or right, respectively) and the second is alignment (L, R, C, T, or B for left, right, center, top, or bottom, respectively). "; + my $fontsize="Tiny,Small,MediumBold,Large,Giant"; + my @ginfo = ( + #{ label=>"Graph Title", param_name=>"G_Title", type=>"Entry", default_val=>undef, content=>undef, info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>undef }, + { label=>"Y Axix Title", param_name=>"Y_Title", type=>"Entry", default_val=>$chart->{"Y_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>undef }, + { label=>"X Axix Title", param_name=>"X_Title", type=>"Entry", default_val=>$chart->{"X_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" ,ref_delay=>undef }, + { label=>"legend placement", param_name=>"legend_placement", type=>'Combo-box', default_val=>'BL', content=>"BL,BC,BR,RT,RC,RB", info=>$legend_info, param_parent=>"${graph_id}_param" , ref_delay=>1}, + { label=>"Y min", param_name=>"Y_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"Y axix minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, + { label=>"X min", param_name=>"X_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"X axix minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, + { label=>"X max", param_name=>"X_MAX", type=>'Spin-button', default_val=>100, content=>"0,1024,1", info=>"X axix maximum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, + { label=>"Line Width", param_name=>"LINEw", type=>'Spin-button', default_val=>3, content=>"1,20,1", info=>undef, param_parent=>"${graph_id}_param" , ref_delay=> 5}, + #{ label=>"Y Axis Values", param_name=>"y_value", type=>'Combo-box', default_val=>'Original', content=>"Original,Normalized to 1,Normalized to 100", info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>1}, + { label=>"legend font size", param_name=>"legend_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, + { label=>"label font size", param_name=>"label_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, + { label=>"label font size", param_name=>"x_axis_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, +); my $content=join( ',', @selects); - my $dimension=gen_combobox_object ($self,$graph_id,"dimension","2D,3D","3D",'ref',2); my $active_page=gen_combobox_object ($self,$page_id,"active",$content,$selects[0],'ref',2); - - -#print "${graph_name}_${dir}_result\n"; - my @ratios; - my @color; - my $min_y=200; - my $i=0; - my @samples =$self->object_get_attribute_order("samples"); - @samples = ('no_name') if (scalar @samples == 0); - foreach my $sample (@samples){ - - my $color_num=$self->object_get_attribute($sample,"color"); - my $l_name= $self->object_get_attribute($sample,"line_name"); - - - #push(@color, "my_color$color_num"); - my $ref=$self->object_get_attribute ($sample,$result_name); - if(defined $ref){ - $i++; - @ratios=get_uniq_keys($ref,@ratios); - $color_num=$i+1 if(!defined $color_num); - push(@color, "my_color$color_num"); - $legend_keys[$i-1]= (defined $l_name)? $l_name : $sample; - } - - - }#for - $content = join(",", @ratios); - my $ratio_combx=gen_combobox_object ($self,${graph_id},"ratio",$content,$ratios[0],'ref',2); - - @color= ("my_color0") if ((scalar @color) ==0); - @legend_keys=("-") if ((scalar @legend_keys) ==0); - - - my $ymax=10; - my $ratio = $self->object_get_attribute ($graph_id,"ratio"); - - - my @x; - if (defined $ratio){ - - foreach my $sample (@samples){ - my $ref=$self->object_get_attribute ($sample,"$result_name"); - if(defined $ref){ - @x=get_uniq_keys($ref->{$ratio},@x); - } - } - my $i=1; - foreach my $sample (@samples){ - my @y; - my $ref=$self->object_get_attribute ($sample,"$result_name"); - if(defined $ref){ - foreach my $v (@x){ - my $w=$ref->{$ratio}->{$v}; - push(@y,$w); - if (defined $w){$ymax=$w+1 if($w>$ymax);} - } - $results[$i]=\@y if(scalar @x); - $i++; - } - } - - - - - } - - $results[0]=\@x if(scalar @x); - - $i=1; - - # all results which is larger than ymax will be changed to ymax, - $i=0; - - #foreach my $sample (@samples){ - #$i++; - #for (my $j=1;$j<=$s; $j++) { - # $results[$i][$j]=($results[$i][$j]>$max_y)? $max_y: $results[$i][$j] if (defined $results[$i][$j]); - #} - #} - - - my $graphs_info; - foreach my $d ( @ginfo){ - $graphs_info->{$d->{param_name}}=$self->object_get_attribute( "${graph_id}_param" ,$d->{param_name}); - if(!defined $graphs_info->{$d->{param_name}}){ - $graphs_info->{$d->{param_name}}= $d->{default_val}; - $self->object_add_attribute( "${graph_id}_param" ,$d->{param_name},$d->{default_val} ); - } - } - - my $graph_w=$width*$image_scale; - my $graph_h=$hight*$image_scale; - my $graph = new GD::Graph::bars3d($graph_w, $graph_h); - my $dim = $self->object_get_attribute (${graph_id},"dimension"); - #my $dir = $self->object_get_attribute ($graph_name,"direction"); - my $over= ($dim eq "2D")? 0 : 1; - $graph->set( - overwrite => $over, - x_label => $graphs_info->{X_Title}, - y_label => $graphs_info->{Y_Title}, - title => $graphs_info->{G_Title}, - y_max_value => $ymax, - y_tick_number => 18, - y_label_skip => 2, - x_label_skip => 1, - x_all_ticks => 1, - x_labels_vertical => 1, - box_axis => 0, - y_long_ticks => 1, - legend_placement => $graphs_info->{legend_placement}, - dclrs=>\@color, - y_number_format=>"%.1f", - - transparent => '0', - bgclr => 'white', - boxclr => 'white', - fgclr => 'black', - textclr => 'black', - labelclr => 'black', - axislabelclr => 'black', - legendclr => 'black', - #cycle_clrs => '1', - - # Draw bars with width 3 pixels +#print "${graph_name}_${dir}_result\n"; + my @ratios; + my @color; + my $min_y=200; + my $i=0; + my @samples =$self->object_get_attribute_order("samples"); + @samples = ('no_name') if (scalar @samples == 0); + foreach my $sample (@samples){ + my $color_num=$self->object_get_attribute($sample,"color"); + my $l_name= $self->object_get_attribute($sample,"line_name"); + #push(@color, "my_color$color_num"); + my $ref=$self->object_get_attribute ($sample,$result_name); + if(defined $ref){ + $i++; + @ratios=get_uniq_keys($ref,@ratios); + $color_num=$i+1 if(!defined $color_num); + push(@color, "my_color$color_num"); + $legend_keys[$i-1]= (defined $l_name)? $l_name : $sample; + } + }#for + $content = join(",", @ratios); + my $ratio_combx=gen_combobox_object ($self,${graph_id},"ratio",$content,$ratios[0],'ref',2); + @color= ("my_color0") if ((scalar @color) ==0); + @legend_keys=("-") if ((scalar @legend_keys) ==0); + my $ymax=10; + my $ratio = $self->object_get_attribute ($graph_id,"ratio"); + my @x; + if (defined $ratio){ + foreach my $sample (@samples){ + my $ref=$self->object_get_attribute ($sample,"$result_name"); + if(defined $ref){ + @x=get_uniq_keys($ref->{$ratio},@x); + } + } + my $i=1; + foreach my $sample (@samples){ + my @y; + my $ref=$self->object_get_attribute ($sample,"$result_name"); + if(defined $ref){ + foreach my $v (@x){ + my $w=$ref->{$ratio}->{$v}; + push(@y,$w); + if (defined $w){$ymax=$w+1 if($w>$ymax);} + } + $results[$i]=\@y if(scalar @x); + $i++; + } + } + } + $results[0]=\@x if(scalar @x); + $i=1; + # all results which is larger than ymax will be changed to ymax, + $i=0; + #foreach my $sample (@samples){ + #$i++; + #for (my $j=1;$j<=$s; $j++) { + # $results[$i][$j]=($results[$i][$j]>$max_y)? $max_y: $results[$i][$j] if (defined $results[$i][$j]); + #} + #} + my $graphs_info; + foreach my $d ( @ginfo){ + $graphs_info->{$d->{param_name}}=$self->object_get_attribute( "${graph_id}_param" ,$d->{param_name}); + if(!defined $graphs_info->{$d->{param_name}}){ + $graphs_info->{$d->{param_name}}= $d->{default_val}; + $self->object_add_attribute( "${graph_id}_param" ,$d->{param_name},$d->{default_val} ); + } + } + my $graph_w=$width*$image_scale; + my $graph_h=$hight*$image_scale; + my $graph = new GD::Graph::bars3d($graph_w, $graph_h); + my $dim = $self->object_get_attribute (${graph_id},"dimension"); + #my $dir = $self->object_get_attribute ($graph_name,"direction"); + my $over= ($dim eq "2D")? 0 : 1; + $graph->set( + overwrite => $over, + x_label => $graphs_info->{X_Title}, + y_label => $graphs_info->{Y_Title}, + title => $graphs_info->{G_Title}, + y_max_value => $ymax, + y_tick_number => 18, + y_label_skip => 2, + x_label_skip => 1, + x_all_ticks => 1, + x_labels_vertical => 1, + box_axis => 0, + y_long_ticks => 1, + legend_placement => $graphs_info->{legend_placement}, + dclrs=>\@color, + y_number_format=>"%.1f", + transparent => '0', + bgclr => 'white', + boxclr => 'white', + fgclr => 'black', + textclr => 'black', + labelclr => 'black', + axislabelclr => 'black', + legendclr => 'black', + #cycle_clrs => '1', + # Draw bars with width 3 pixels bar_width => 3, # Separate the bars with 4 pixels bar_spacing => 10, @@ -527,672 +386,493 @@ sub gen_3D_bar{ # Show values on top of each bar #show_values => 1, ); - - - $graph->set_legend(@legend_keys); - - my $font; - - $font= $self->object_get_attribute( "${graph_id}_param" ,'label_font'); - $graph->set_x_label_font(GD::Font->$font); - $graph->set_y_label_font(GD::Font->$font); - $font= $self->object_get_attribute( "${graph_id}_param" ,'legend_font'); - $graph->set_legend_font(GD::Font->$font); - - $font= $self->object_get_attribute( "${graph_id}_param" ,'x_axis_font'); - #$graph->set_values_font(GD::gdGiantFont); - $graph->set_x_axis_font(GD::Font->$font); - $graph->set_y_axis_font(GD::Font->$font); - - #@results=reorder_result(@results); - - my $gd = $graph->plot( \@results ); - my $image =open_inline_image($gd->png); - - write_image ($self,$graph_id,$gd); - write_image_result ($self,$graph_id,$graph,$result_name,$chart->{type},\@results); - - - - - my $table = def_table (25, 10, FALSE); + $graph->set_legend(@legend_keys); + my $font; + $font= $self->object_get_attribute( "${graph_id}_param" ,'label_font'); + $graph->set_x_label_font(GD::Font->$font); + $graph->set_y_label_font(GD::Font->$font); + $font= $self->object_get_attribute( "${graph_id}_param" ,'legend_font'); + $graph->set_legend_font(GD::Font->$font); + $font= $self->object_get_attribute( "${graph_id}_param" ,'x_axis_font'); + #$graph->set_values_font(GD::gdGiantFont); + $graph->set_x_axis_font(GD::Font->$font); + $graph->set_y_axis_font(GD::Font->$font); + #@results=reorder_result(@results); + my $gd = $graph->plot( \@results ); + my $image =open_inline_image($gd->png); + write_image ($self,$graph_id,$gd); + write_image_result ($self,$graph_id,$graph,$result_name,$chart->{type},\@results); + my $table = def_table (25, 10, FALSE); my $filename; - my $align= add_frame_to_image($image); - - - - - my $plus = def_image_button('icons/plus.png',undef,TRUE); - my $minues = def_image_button('icons/minus.png',undef,TRUE); - my $setting = def_image_button('icons/setting.png',undef,TRUE); - my $save = def_image_button('icons/save.png',undef,TRUE); - my $scale= $self->object_get_attribute("${graph_id}_graph_scale",undef); - $scale = 5 if(!defined $scale); - $minues -> signal_connect("clicked" => sub{ - $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale*1.05); - set_gui_status($self,"ref",1); - }); - - $plus -> signal_connect("clicked" => sub{ - $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale*0.95) if( $scale>0.5); - set_gui_status($self,"ref",5); - }); - - $setting -> signal_connect("clicked" => sub{ - get_graph_setting ($self,\@ginfo); - }); - set_tip($setting, "Setting"); - - $save-> signal_connect("clicked" => sub{ - # my @imags=$graph->export_format(); - my @imags=('png'); - save_graph_as ($self,\@imags,$graph_id); - }); - set_tip($save, "Save graph"); - - - - $table->attach_defaults ($align , 0, 9, 0, 24); - my $row=0; - $table->attach ($active_page, 0, 9, 24, 25,'shrink','shrink',2,2); - $table->attach (gen_label_in_center("Injection-Ratio/"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach (gen_label_in_center("Task-file index"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($ratio_combx, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($dimension, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - - #$table->attach ($plus , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - #$table->attach ($minues, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($setting, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($save, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - - while ($row<10){ - my $tmp=gen_label_in_left(''); - $table->attach_defaults ($tmp, 9, 10, $row, $row+1);$row++; - } - - - + my $align= add_frame_to_image($image); + my $plus = def_image_button('icons/plus.png',undef,TRUE); + my $minues = def_image_button('icons/minus.png',undef,TRUE); + my $setting = def_image_button('icons/setting.png',undef,TRUE); + my $save = def_image_button('icons/save.png',undef,TRUE); + my $scale= $self->object_get_attribute("${graph_id}_graph_scale",undef); + $scale = 5 if(!defined $scale); + $minues -> signal_connect("clicked" => sub{ + $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale*1.05); + set_gui_status($self,"ref",1); + }); + $plus -> signal_connect("clicked" => sub{ + $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale*0.95) if( $scale>0.5); + set_gui_status($self,"ref",5); + }); + $setting -> signal_connect("clicked" => sub{ + get_graph_setting ($self,\@ginfo); + }); + set_tip($setting, "Setting"); + $save-> signal_connect("clicked" => sub{ + # my @imags=$graph->export_format(); + my @imags=('png'); + save_graph_as ($self,\@imags,$graph_id); + }); + set_tip($save, "Save graph"); + $table->attach_defaults ($align , 0, 9, 0, 24); + my $row=0; + $table->attach ($active_page, 0, 9, 24, 25,'shrink','shrink',2,2); + $table->attach (gen_label_in_center("Injection-Ratio/"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach (gen_label_in_center("Task-file index"), 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($ratio_combx, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($dimension, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + #$table->attach ($plus , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + #$table->attach ($minues, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($setting, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($save, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + while ($row<10){ + my $tmp=gen_label_in_left(''); + $table->attach_defaults ($tmp, 9, 10, $row, $row+1);$row++; + } return $table; } - - - - - - - - - - - - - sub gen_2D_line { - - my ($self,$chart,@selects)=@_; - my($width,$hight)=max_win_size(); - my $page_id= "P$chart->{page_num}"; - my $graph_id= $page_id."$chart->{graph_name}"; - #my $graph_name=$chart->{graph_name}; - my $result_name= $chart->{result_name}; - my @x; - my @legend_keys; - - - my @results; - $results[0]=[0]; - $results[1]= [0]; - my $legend_info="This attribute controls placement of the legend within the graph image. The value is supplied as a two-letter string, where the first letter is placement (a B or an R for bottom or right, respectively) and the second is alignment (L, R, C, T, or B for left, right, center, top, or bottom, respectively). "; - - my $fontsize="Tiny,Small,MediumBold,Large,Giant"; - + my ($self,$chart,@selects)=@_; + my($width,$hight)=max_win_size(); + my $page_id= "P$chart->{page_num}"; + my $graph_id= $page_id."$chart->{graph_name}"; + #my $graph_name=$chart->{graph_name}; + my $result_name= $chart->{result_name}; + my @x; + my @legend_keys; + my @results; + $results[0]=[0]; + $results[1]= [0]; + my $legend_info="This attribute controls placement of the legend within the graph image. The value is supplied as a two-letter string, where the first letter is placement (a B or an R for bottom or right, respectively) and the second is alignment (L, R, C, T, or B for left, right, center, top, or bottom, respectively). "; + my $fontsize="Tiny,Small,MediumBold,Large,Giant"; my $content=join( ',', @selects); my $active_page=gen_combobox_object ($self,$page_id,"active",$content,$selects[0],'ref',2); - - - my @ginfo = ( -#{ label=>"Graph Title", param_name=>"G_Title", type=>"Entry", default_val=>undef, content=>undef, info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>undef }, -{ label=>"Y Axis Title", param_name=>"Y_Title", type=>"Entry", default_val=>$chart->{"Y_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>undef }, - { label=>"X Axis Title", param_name=>"X_Title", type=>"Entry", default_val=>$chart->{"X_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" ,ref_delay=>undef }, - { label=>"legend placement", param_name=>"legend_placement", type=>'Combo-box', default_val=>'BL', content=>"BL,BC,BR,RT,RC,RB", info=>$legend_info, param_parent=>"${graph_id}_param" , ref_delay=>1}, - - { label=>"Y min", param_name=>"Y_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"Y axis minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, - { label=>"X min", param_name=>"X_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"X axis minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, -{ label=>"X max", param_name=>"X_MAX", type=>'Spin-button', default_val=>100, content=>"0,1024,1", info=>"X axis maximum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, - { label=>"Line Width", param_name=>"LINEw", type=>'Spin-button', default_val=>3, content=>"1,20,1", info=>undef, param_parent=>"${graph_id}_param" , ref_delay=> 5}, -#{ label=>"Y Axis Values", param_name=>"y_value", type=>'Combo-box', default_val=>'Original', content=>"Original,Normalized to 1,Normalized to 100", info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>1}, - -{ label=>"legend font size", param_name=>"legend_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"{$graph_id}_param" , ref_delay=>1}, -{ label=>"label font size", param_name=>"label_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, - { label=>"label font size", param_name=>"x_axis_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, -); - - - - - - my @color; - my $min_y;#=200; - my $i=0; - my @samples =$self->object_get_attribute_order("samples"); - @samples = ('no_name') if (scalar @samples == 0); - foreach my $sample (@samples){ - my $ref=$self->object_get_attribute ($sample,$result_name); - $i++; - my $color_num=$self->object_get_attribute($sample,"color"); - my $l_name= $self->object_get_attribute($sample,"line_name"); - $legend_keys[$i-1]= (defined $l_name)? $l_name : $sample; - $color_num=$i+1 if(!defined $color_num); - push(@color, "my_color$color_num"); - - if(defined $ref) { - push(@x, sort {$a<=>$b} keys %{$ref}); - - } - - }#for - - my @x2; - @x2 = uniq(sort {$a<=>$b} @x) if (scalar @x); - - my @x1; #remove x values larger than x_max - my $x_max= $self->object_get_attribute( "${graph_id}_param" ,'X_MAX'); - foreach my $p (@x2){ - if(defined $x_max) {push (@x1,$p) if($p<$x_max);} - else {push (@x1,$p);} - } - - #print "\@x1=@x1\n"; - if (scalar @x1){ - $results[0]=\@x1; - $i=0; - foreach my $sample (@samples){ - $i++; - my $j=0; - my $ref=$self->object_get_attribute ($sample,$result_name); - if(defined $ref){ - #print "$i\n"; - my %line=%$ref; - foreach my $k (@x1){ - $results[$i][$j]=$line{$k}; - if(defined $line{$k}){ - $min_y = $line{$k} if (!defined $min_y); - $min_y= $line{$k} if ($line{$k}!=0 && $min_y > $line{$k}); - $j++; - } - }#$k - }#if - else { - $results[$i][$j]=undef; - } - }#$i - }#if - - $min_y = 200 if (!defined $min_y); - my $scale= $self->object_get_attribute("${graph_id}_graph_scale",undef); - $scale = 5 if(!defined $scale); - - my $max_y=$min_y* $scale; - my $s=scalar @x1; - - # all results which is larger than ymax will be changed to ymax, - $i=0; - - foreach my $sample (@samples){ - $i++; - for (my $j=1;$j<=$s; $j++) { - $results[$i][$j]=($results[$i][$j]>$max_y)? $max_y: $results[$i][$j] if (defined $results[$i][$j]); - } - } - - - my $graphs_info; - foreach my $d ( @ginfo){ - $graphs_info->{$d->{param_name}}=$self->object_get_attribute( "${graph_id}_param" ,$d->{param_name}); - if(!defined $graphs_info->{$d->{param_name}}){ - $graphs_info->{$d->{param_name}}= $d->{default_val}; - $self->object_add_attribute( "${graph_id}_param" ,$d->{param_name},$d->{default_val} ); - } - } - - my $graph_w=$width/2.5; - my $graph_h=$hight/2.5; - my $graph = GD::Graph::linespoints->new($graph_w, $graph_h); - - $graph->set ( - x_label => $graphs_info->{X_Title}, - y_label => $graphs_info->{Y_Title}, - y_max_value => $max_y, - y_min_value => $graphs_info->{Y_MIN}, - y_tick_number => 8, - # x_min_value => $graphs_info->{X_MIN}, # dosent work? - title => $graphs_info->{G_Title}, - bar_spacing => 1, - shadowclr => 'dred', - - - - box_axis => 0, - skip_undef=> 1, - # transparent => 1, - transparent => '0', - bgclr => 'white', - boxclr => 'white', - fgclr => 'black', - textclr => 'black', - labelclr => 'black', - axislabelclr => 'black', - legendclr => 'black', - cycle_clrs => '1', - line_width => $graphs_info->{LINEw}, - # cycle_clrs => 'black', - legend_placement => $graphs_info->{legend_placement}, - dclrs=>\@color, - y_number_format=>"%.1f", - BACKGROUND=>'black', - - ); - - - $graph->set_legend(@legend_keys); - - - - - - - - my $data = GD::Graph::Data->new(\@results) or die GD::Graph::Data->error; - $data->make_strict(); - + #{ label=>"Graph Title", param_name=>"G_Title", type=>"Entry", default_val=>undef, content=>undef, info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>undef }, + { label=>"Y Axis Title", param_name=>"Y_Title", type=>"Entry", default_val=>$chart->{"Y_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>undef }, + { label=>"X Axis Title", param_name=>"X_Title", type=>"Entry", default_val=>$chart->{"X_Title"}, content=>undef, info=>undef, param_parent=>"${graph_id}_param" ,ref_delay=>undef }, + { label=>"legend placement", param_name=>"legend_placement", type=>'Combo-box', default_val=>'BL', content=>"BL,BC,BR,RT,RC,RB", info=>$legend_info, param_parent=>"${graph_id}_param" , ref_delay=>1}, + { label=>"Y min", param_name=>"Y_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"Y axis minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, + { label=>"X min", param_name=>"X_MIN", type=>'Spin-button', default_val=>0, content=>"0,1024,1", info=>"X axis minimum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, + { label=>"X max", param_name=>"X_MAX", type=>'Spin-button', default_val=>100, content=>"0,1024,1", info=>"X axis maximum value", param_parent=>"${graph_id}_param" , ref_delay=> 5}, + { label=>"Line Width", param_name=>"LINEw", type=>'Spin-button', default_val=>3, content=>"1,20,1", info=>undef, param_parent=>"${graph_id}_param" , ref_delay=> 5}, + #{ label=>"Y Axis Values", param_name=>"y_value", type=>'Combo-box', default_val=>'Original', content=>"Original,Normalized to 1,Normalized to 100", info=>undef, param_parent=>"${graph_name}_param" , ref_delay=>1}, + { label=>"legend font size", param_name=>"legend_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"{$graph_id}_param" , ref_delay=>1}, + { label=>"label font size", param_name=>"label_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, + { label=>"label font size", param_name=>"x_axis_font", type=>'Combo-box', default_val=>'MediumBold', content=>$fontsize, info=>undef, param_parent=>"${graph_id}_param" , ref_delay=>1}, + ); + my @color; + my $min_y;#=200; + my $i=0; + my @samples =$self->object_get_attribute_order("samples"); + @samples = ('no_name') if (scalar @samples == 0); + foreach my $sample (@samples){ + my $ref=$self->object_get_attribute ($sample,$result_name); + $i++; + my $color_num=$self->object_get_attribute($sample,"color"); + my $l_name= $self->object_get_attribute($sample,"line_name"); + $legend_keys[$i-1]= (defined $l_name)? $l_name : $sample; + $color_num=$i+1 if(!defined $color_num); + push(@color, "my_color$color_num"); + if(defined $ref) { + push(@x, sort {$a<=>$b} keys %{$ref}); + } + }#for + my @x2; + @x2 = uniq(sort {$a<=>$b} @x) if (scalar @x); + my @x1; #remove x values larger than x_max + my $x_max= $self->object_get_attribute( "${graph_id}_param" ,'X_MAX'); + foreach my $p (@x2){ + if(defined $x_max) {push (@x1,$p) if($p<$x_max);} + else {push (@x1,$p);} + } + #print "\@x1=@x1\n"; + if (scalar @x1){ + $results[0]=\@x1; + $i=0; + foreach my $sample (@samples){ + $i++; + my $j=0; + my $ref=$self->object_get_attribute ($sample,$result_name); + if(defined $ref){ + #print "$i\n"; + my %line=%$ref; + foreach my $k (@x1){ + $results[$i][$j]=$line{$k}; + if(defined $line{$k}){ + $min_y = $line{$k} if (!defined $min_y); + $min_y= $line{$k} if ($line{$k}!=0 && $min_y > $line{$k}); + $j++; + } + }#$k + }#if + else { + $results[$i][$j]=undef; + } + }#$i + }#if + $min_y = 200 if (!defined $min_y); + my $scale= $self->object_get_attribute("${graph_id}_graph_scale",undef); + $scale = 5 if(!defined $scale); + my $max_y=$min_y* $scale; + my $s=scalar @x1; + # all results which is larger than ymax will be changed to ymax, + $i=0; + foreach my $sample (@samples){ + $i++; + for (my $j=1;$j<=$s; $j++) { + $results[$i][$j]=($results[$i][$j]>$max_y)? $max_y: $results[$i][$j] if (defined $results[$i][$j]); + } + } + my $graphs_info; + foreach my $d ( @ginfo){ + $graphs_info->{$d->{param_name}}=$self->object_get_attribute( "${graph_id}_param" ,$d->{param_name}); + if(!defined $graphs_info->{$d->{param_name}}){ + $graphs_info->{$d->{param_name}}= $d->{default_val}; + $self->object_add_attribute( "${graph_id}_param" ,$d->{param_name},$d->{default_val} ); + } + } + my $graph_w=$width/2.5; + my $graph_h=$hight/2.5; + my $graph = GD::Graph::linespoints->new($graph_w, $graph_h); + $graph->set ( + x_label => $graphs_info->{X_Title}, + y_label => $graphs_info->{Y_Title}, + y_max_value => $max_y, + y_min_value => $graphs_info->{Y_MIN}, + y_tick_number => 8, + # x_min_value => $graphs_info->{X_MIN}, # dosent work? + title => $graphs_info->{G_Title}, + bar_spacing => 1, + shadowclr => 'dred', + box_axis => 0, + skip_undef=> 1, + # transparent => 1, + transparent => '0', + bgclr => 'white', + boxclr => 'white', + fgclr => 'black', + textclr => 'black', + labelclr => 'black', + axislabelclr => 'black', + legendclr => 'black', + cycle_clrs => '1', + line_width => $graphs_info->{LINEw}, + #cycle_clrs => 'black', + legend_placement => $graphs_info->{legend_placement}, + dclrs=>\@color, + y_number_format=>"%.1f", + BACKGROUND=>'black', + ); + $graph->set_legend(@legend_keys); + my $data = GD::Graph::Data->new(\@results) or die GD::Graph::Data->error; + $data->make_strict(); my $image = my_get_image($self,$graph,$data,$graph_id,$result_name,$chart->{type}); - - - - # print Data::Dumper->Dump ([\@results],['ttt']); - - - - + # print Data::Dumper->Dump ([\@results],['ttt']); my $table = def_table (25, 10, FALSE); - - - - my $filename; - - my $align = add_frame_to_image($image); - - - my $plus = def_image_button('icons/plus.png',undef,TRUE); - my $minues = def_image_button('icons/minus.png',undef,TRUE); - my $setting = def_image_button('icons/setting.png',undef,TRUE); - my $save = def_image_button('icons/save.png',undef,TRUE); - - - $minues -> signal_connect("clicked" => sub{ - $scale*=1.05; - $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale); - set_gui_status($self,"ref",5); - }); - set_tip($minues, "Zoom out"); - - $plus -> signal_connect("clicked" => sub{ - $scale*=0.95 if( $scale>0.5); - $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale); - set_gui_status($self,"ref",5); - }); - set_tip($plus, "Zoom in"); - - $setting -> signal_connect("clicked" => sub{ - get_graph_setting ($self,\@ginfo); - }); - set_tip($setting, "Setting"); - - $save-> signal_connect("clicked" => sub{ - # my $G = $graph->{graph}; - # my @imags=$G->export_format(); - my @imags=('png'); - save_graph_as ($self,\@imags,$graph_id); - }); - set_tip($save, "Save graph"); - - - - $table->attach_defaults ($align , 0, 9, 0, 24); - my $row=0; - $table->attach ($active_page, 0, 9, 24, 25,'shrink','shrink',2,2);# $row++; - $table->attach ($plus , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($minues, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($setting, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - $table->attach ($save, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; - while ($row<10){ - - my $tmp=gen_label_in_left(''); - $table->attach_defaults ($tmp, 9, 10, $row, $row+1);$row++; - } - + my $filename; + my $align = add_frame_to_image($image); + my $plus = def_image_button('icons/plus.png',undef,TRUE); + my $minues = def_image_button('icons/minus.png',undef,TRUE); + my $setting = def_image_button('icons/setting.png',undef,TRUE); + my $save = def_image_button('icons/save.png',undef,TRUE); + $minues -> signal_connect("clicked" => sub{ + $scale*=1.05; + $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale); + set_gui_status($self,"ref",5); + }); + set_tip($minues, "Zoom out"); + $plus -> signal_connect("clicked" => sub{ + $scale*=0.95 if( $scale>0.5); + $self->object_add_attribute("${graph_id}_graph_scale",undef,$scale); + set_gui_status($self,"ref",5); + }); + set_tip($plus, "Zoom in"); + $setting -> signal_connect("clicked" => sub{ + get_graph_setting ($self,\@ginfo); + }); + set_tip($setting, "Setting"); + $save-> signal_connect("clicked" => sub{ + # my $G = $graph->{graph}; + # my @imags=$G->export_format(); + my @imags=('png'); + save_graph_as ($self,\@imags,$graph_id); + }); + set_tip($save, "Save graph"); + $table->attach_defaults ($align , 0, 9, 0, 24); + my $row=0; + $table->attach ($active_page, 0, 9, 24, 25,'shrink','shrink',2,2);# $row++; + $table->attach ($plus , 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($minues, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($setting, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + $table->attach ($save, 9, 10, $row, $row+1,'shrink','shrink',2,2); $row++; + while ($row<10){ + my $tmp=gen_label_in_left(''); + $table->attach_defaults ($tmp, 9, 10, $row, $row+1);$row++; + } return $table; - } - ############## -# save_graph_as +# save_graph_as ############## - sub save_graph_as { - my ($self,$ref,$graph_name)=@_; - - my $file; - my $title ='Save as'; - my @extensions=@$ref; - my $open_in=undef; - my $dialog=save_file_dialog ($title, @extensions); - - $dialog->set_current_folder ($open_in) if(defined $open_in); - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my $ext = $dialog->get_filter; - $ext=$ext->get_name; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; - - $self->object_add_attribute("graph_save","name",$file); - $self->object_add_attribute("graph_save","extension",$ext); - $self->object_add_attribute("graph_save","save",1); - $self->object_add_attribute("graph_save","save_result",1); - $self->object_add_attribute("graph_save","graph_name",$graph_name); - set_gui_status($self,"ref",1); - - } - $dialog->destroy; + my ($self,$ref,$graph_name)=@_; + my $file; + my $title ='Save as'; + my @extensions=@$ref; + my $open_in=undef; + my $dialog=save_file_dialog ($title, @extensions); + $dialog->set_current_folder ($open_in) if(defined $open_in); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my $ext = $dialog->get_filter; + $ext=$ext->get_name; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + $file = ($suffix eq ".$ext" )? $file : "$file.$ext"; + $self->object_add_attribute("graph_save","name",$file); + $self->object_add_attribute("graph_save","extension",$ext); + $self->object_add_attribute("graph_save","save",1); + $self->object_add_attribute("graph_save","save_result",1); + $self->object_add_attribute("graph_save","graph_name",$graph_name); + set_gui_status($self,"ref",1); + } + $dialog->destroy; } - - sub my_get_image { - my ($self,$exgraph, $data, $graph_name, $result_name,$charttype) = @_; - $exgraph->{graphdata} = $data; - my $graph = $exgraph;#->{graph}; - my $font; - - $font= $self->object_get_attribute( "${graph_name}_param" ,'label_font'); - $graph->set_x_label_font(GD::Font->$font); - $graph->set_y_label_font(GD::Font->$font); - $font= $self->object_get_attribute( "${graph_name}_param" ,'legend_font'); - $graph->set_legend_font(GD::Font->$font); - - $font= $self->object_get_attribute( "${graph_name}_param" ,'x_axis_font'); - #$graph->set_values_font(GD::gdGiantFont); - $graph->set_x_axis_font(GD::Font->$font); - $graph->set_y_axis_font(GD::Font->$font); - - my $gd2=$graph->plot($data) or warn $graph->error; - - - - #cut the upper side of the image to remove the straight line created by changing large results to ymax - - my $gd1= GD::Image->new($gd2->getBounds); - my $white= $gd1->colorAllocate(255,255,254); - my ($x,$h)=$gd2->getBounds; - $gd1->transparent($white); - $gd1->copy( $gd2, 0, 0, 0, ,$h*0.05, $x ,$h*.95 ); - - write_image ($self,$graph_name,$gd1); - write_image_result ($self,$graph_name,$graph,$result_name,$charttype); - - my $image =open_inline_image($gd1->png); - return $image; - + my ($self,$exgraph, $data, $graph_name, $result_name,$charttype) = @_; + $exgraph->{graphdata} = $data; + my $graph = $exgraph;#->{graph}; + my $font; + $font= $self->object_get_attribute( "${graph_name}_param" ,'label_font'); + $graph->set_x_label_font(GD::Font->$font); + $graph->set_y_label_font(GD::Font->$font); + $font= $self->object_get_attribute( "${graph_name}_param" ,'legend_font'); + $graph->set_legend_font(GD::Font->$font); + $font= $self->object_get_attribute( "${graph_name}_param" ,'x_axis_font'); + #$graph->set_values_font(GD::gdGiantFont); + $graph->set_x_axis_font(GD::Font->$font); + $graph->set_y_axis_font(GD::Font->$font); + my $gd2=$graph->plot($data) or warn $graph->error; + #cut the upper side of the image to remove the straight line created by changing large results to ymax + my $gd1= GD::Image->new($gd2->getBounds); + my $white= $gd1->colorAllocate(255,255,254); + my ($x,$h)=$gd2->getBounds; + $gd1->transparent($white); + $gd1->copy( $gd2, 0, 0, 0, ,$h*0.05, $x ,$h*.95 ); + write_image ($self,$graph_name,$gd1); + write_image_result ($self,$graph_name,$graph,$result_name,$charttype); + my $image =open_inline_image($gd1->png); + return $image; } - - ############ -# get_graph_setting +# get_graph_setting ########### - sub get_graph_setting { - my ($self,$ref)=@_; - my $window=def_popwin_size(33,33,'Graph Setting','percent'); - my $table = def_table(10, 2, FALSE); - my $row=0; - - -my @data=@$ref; -my $coltmp; -foreach my $d (@data) { - #$row=noc_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row, 1, $d->{param_parent}, $d->{ref_delay}); - ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay} ,undef,undef); + my ($self,$ref)=@_; + my $window=def_popwin_size(33,33,'Graph Setting','percent'); + my $table = def_table(10, 2, FALSE); + my $row=0; + my @data=@$ref; + my $coltmp; + foreach my $d (@data) { + #$row=noc_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row, 1, $d->{param_parent}, $d->{ref_delay}); + ($row,$coltmp)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,undef,1, $d->{param_parent}, $d->{ref_delay} ,undef,undef); + } + my $scrolled_win = add_widget_to_scrolled_win($table); + my $ok = def_image_button('icons/select.png',' OK '); + my $mtable = def_table(10, 1, FALSE); + $mtable->attach_defaults($scrolled_win,0,1,0,9); + $mtable->attach($ok,0,1,9,10,'shrink','shrink',2,2); + $window->add ($mtable); + $window->show_all(); + $ok-> signal_connect("clicked" => sub{ + $window->destroy; + set_gui_status($self,"ref",1); + }); } - - - - - my $scrolled_win = add_widget_to_scrolled_win($table); - my $ok = def_image_button('icons/select.png',' OK '); - - - my $mtable = def_table(10, 1, FALSE); - $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable->attach($ok,0,1,9,10,'shrink','shrink',2,2); - $window->add ($mtable); - $window->show_all(); - - $ok-> signal_connect("clicked" => sub{ - $window->destroy; - set_gui_status($self,"ref",1); - }); - - - -} - - sub write_image { - my ($self,$graph_name,$image)=@_; - my $save=$self->object_get_attribute("graph_save","save"); - - my $active_graph=$self->object_get_attribute("graph_save","graph_name"); - $save=0 if (!defined $save); - $active_graph = 0 if(!defined $active_graph); - - if ($save ==1 && $active_graph eq $graph_name){ - my $file=$self->object_get_attribute("graph_save","name"); - my $ext=$self->object_get_attribute("graph_save","extension"); - $self->object_add_attribute("graph_save","save",0); - - #image - open(my $out, '>', $file); - if (tell $out ) - { - warn "Cannot open '$file' to write: $!"; - }else - { - #my @extens=$graph->export_format(); - binmode $out; - print $out $image->$ext;# if($ext eq 'png'); - #print $out $gd1->gif if($ext eq 'gif'); - close $out; - } - } - + my ($self,$graph_name,$image)=@_; + my $save=$self->object_get_attribute("graph_save","save"); + my $active_graph=$self->object_get_attribute("graph_save","graph_name"); + $save=0 if (!defined $save); + $active_graph = 0 if(!defined $active_graph); + if ($save ==1 && $active_graph eq $graph_name){ + my $file=$self->object_get_attribute("graph_save","name"); + my $ext=$self->object_get_attribute("graph_save","extension"); + $self->object_add_attribute("graph_save","save",0); + #image + open(my $out, '>', $file); + if (tell $out ) + { + warn "Cannot open '$file' to write: $!"; + }else + { + #my @extens=$graph->export_format(); + binmode $out; + print $out $image->$ext;# if($ext eq 'png'); + #print $out $gd1->gif if($ext eq 'gif'); + close $out; + } + } } - sub write_image_result { - my ($self,$graph_name,$graph,$result_name,$charttype,$result_ref)=@_; - my $save=$self->object_get_attribute("graph_save","save_result"); - my $active_graph=$self->object_get_attribute("graph_save","graph_name"); - $save=0 if (!defined $save); - $active_graph = 0 if(!defined $active_graph); - - if ($save ==1 && $active_graph eq $graph_name){ - my $file=$self->object_get_attribute("graph_save","name"); - $self->object_add_attribute("graph_save","save_result",0); - write_graph_results_in_file($self,"$file.txt",$result_name,$result_ref,$charttype); - } + my ($self,$graph_name,$graph,$result_name,$charttype,$result_ref)=@_; + my $save=$self->object_get_attribute("graph_save","save_result"); + my $active_graph=$self->object_get_attribute("graph_save","graph_name"); + $save=0 if (!defined $save); + $active_graph = 0 if(!defined $active_graph); + if ($save ==1 && $active_graph eq $graph_name){ + my $file=$self->object_get_attribute("graph_save","name"); + $self->object_add_attribute("graph_save","save_result",0); + write_graph_results_in_file($self,"$file.txt",$result_name,$result_ref,$charttype); + } } sub write_graph_results_in_file{ - my ($self,$file_name,$result_name,$result_ref,$charttype)=@_; - - open( my $out, '>', $file_name); - if (tell $out ) - { - warn "Cannot open $file_name to write: $!"; - return; - } - else - { - if($charttype eq '2D_line'){ - write_2d_graph_results($self,$out,$result_name); - } else{ - write_3d_graph_results($self,$out,$result_ref); - } - close $out; - } -} - + my ($self,$file_name,$result_name,$result_ref,$charttype)=@_; + open( my $out, '>', $file_name); + if (tell $out ) + { + warn "Cannot open $file_name to write: $!"; + return; + } + else + { + if($charttype eq '2D_line'){ + write_2d_graph_results($self,$out,$result_name); + } else{ + write_3d_graph_results($self,$out,$result_ref); + } + close $out; + } +} sub write_2d_graph_results{ - my ($self,$out,$result_name)=@_; - my @samples =$self->object_get_attribute_order("samples"); - foreach my $sample (@samples){ - my $l_name= $self->object_get_attribute($sample,"line_name"); - my $ref=$self->object_get_attribute ($sample,$result_name); - my @x; - if(defined $ref) { - print $out "$l_name\n"; - foreach my $x (sort {$a<=>$b} keys %{$ref}) { - my $y=$ref->{$x}; - print $out "\t$x , $y\n"; - } - print $out "\n\n"; - } - }#for -} - + my ($self,$out,$result_name)=@_; + my @samples =$self->object_get_attribute_order("samples"); + foreach my $sample (@samples){ + my $l_name= $self->object_get_attribute($sample,"line_name"); + my $ref=$self->object_get_attribute ($sample,$result_name); + my @x; + if(defined $ref) { + print $out "$l_name\n"; + foreach my $x (sort {$a<=>$b} keys %{$ref}) { + my $y=$ref->{$x}; + print $out "\t$x , $y\n"; + } + print $out "\n\n"; + } + }#for +} sub write_3d_graph_results{ - my ($self,$out,$result_ref)=@_; - - my @r=@{$result_ref}; - - my @samples =$self->object_get_attribute_order("samples"); - my $i=0; - if(defined $r[$i]){ - my @k=@{$r[$i]}; - print $out "@k\n\n"; - } - - foreach my $sample (@samples){ - $i++; - my $l_name= $self->object_get_attribute($sample,"line_name"); - print $out "$l_name:\n"; - if(defined $r[$i]){ - my @k=@{$r[$i]}; - print $out "@k\n\n"; - } - } -} - - - - ################ - # get_color_window - ############### - - sub get_color_window{ - my ($self,$atrebute1,$atrebute2)=@_; - my $window=def_popwin_size(40,40,"Select line color",'percent'); - my ($r,$c)=(4,8); - my $table= def_table(5,6,TRUE); - for (my $col=0;$col<$c;$col++){ - for (my $row=0;$row<$r;$row++){ - my $color_num=$row*$c+$col; - my $color=def_colored_button(" ",$color_num); - $table->attach_defaults ($color, $col, $col+1, $row, $row+1); - $color->signal_connect("clicked"=> sub{ - $self->object_add_attribute($atrebute1,$atrebute2,$color_num); - #print "$self->object_add_attribute($atrebute1,$atrebute2,$color_num);\n"; - set_gui_status($self,"ref",1); - $window->destroy; - }); - } - } - - $window->add($table); - - $window->show_all(); - + my ($self,$out,$result_ref)=@_; + my @r=@{$result_ref}; + my @samples =$self->object_get_attribute_order("samples"); + my $i=0; + if(defined $r[$i]){ + my @k=@{$r[$i]}; + print $out "@k\n\n"; + } + foreach my $sample (@samples){ + $i++; + my $l_name= $self->object_get_attribute($sample,"line_name"); + print $out "$l_name:\n"; + if(defined $r[$i]){ + my @k=@{$r[$i]}; + print $out "@k\n\n"; + } + } } +################ +# get_color_window +############### +sub get_color_window{ + my ($self,$atrebute1,$atrebute2)=@_; + my $window=def_popwin_size(40,40,"Select line color",'percent'); + my ($r,$c)=(4,8); + my $table= def_table(5,6,TRUE); + for (my $col=0;$col<$c;$col++){ + for (my $row=0;$row<$r;$row++){ + my $color_num=$row*$c+$col; + my $color=def_colored_button(" ",$color_num); + $table->attach_defaults ($color, $col, $col+1, $row, $row+1); + $color->signal_connect("clicked"=> sub{ + $self->object_add_attribute($atrebute1,$atrebute2,$color_num); + #print "$self->object_add_attribute($atrebute1,$atrebute2,$color_num);\n"; + set_gui_status($self,"ref",1); + $window->destroy; + }); + } + } + $window->add($table); + $window->show_all(); +} sub reorder_result{ - my @results=@_; - - my @app=( - "a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","a10","a11"," "," "," "," ", - "b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","b10","b11","b12","b13","b14","b15"," "," "," "," ", - "c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11"," "," "," "," ", - "d0","d1","d2","d3","d4","d5","d6","d7","d8"); - - - - my %nmap=( - "b7" => 0 ,"b9" => 1 ,"b8" => 2 ,"a11"=> 3 ,"b11"=> 4 ,"b12"=> 5 ,"b13"=> 6 , - "b6" => 7 ,"b5" => 8 ,"a10"=> 9 ,"a8" => 10,"a9" => 11,"b14"=> 12,"b10"=> 13, - "b3" => 14,"b4" => 15,"a5" => 16,"a7" => 17,"a2" => 18,"d8" => 19,"d0" => 20, - "b2" => 21,"a3" => 22,"a6" => 23,"a0" => 24,"a1" => 25,"d1" => 26,"d2" => 27, - "b1" => 28,"b15"=> 29,"c2" => 30,"a4" => 31,"d4" => 32,"d3" => 33,"d5" => 34, - "b0" => 35,"c9" => 36,"c8" => 37,"c3" => 38,"d7" => 39,"d6" => 40,"c7" => 41, - "c11"=> 42,"c10"=> 43,"c5" => 44,"c4" => 45,"c1" => 46,"c0" => 47,"c6" => 48); - - my %worst=( - "a0" => 0 ,"a8" => 1 ,"b7" => 2 ,"d8"=> 3 ,"b1"=> 4 ,"b5"=> 5 ,"b8"=> 6 , - "a5" => 7 ,"c2" => 8 ,"c10"=> 9 ,"c3" => 10,"c5" => 11,"b12"=> 12,"b3"=> 13, - "d1" => 14,"d7" => 15,"c1" => 16,"c7" => 17,"c0" => 18,"c8" => 19,"b10" => 20, - "b15" => 21,"d2" => 22,"c4" => 23,"c6" => 24,"c9" => 25,"d3" => 26,"a4" => 27, - "b2" => 28,"b13"=> 29,"d4" => 30,"c11" => 31,"d5" => 32,"a2" => 33,"a10" => 34, - "b6" => 35,"b0" => 36,"d0" => 37,"d6" => 38,"a3" => 39,"a9" => 40,"a6" => 41, - "b9"=> 42,"b4"=> 43,"b11" => 44,"b14" => 45,"a1" => 46,"a11" => 47,"a7" => 48); - - my %rnd=( - "d3" => 0 ,"d6" => 1 ,"b8" => 2 ,"c10"=> 3 ,"d5" => 4 ,"d8" => 5 ,"a3" => 6 , - "b15"=> 7 ,"a9" => 8 ,"c3" => 9 ,"b12"=> 10,"a4" => 11,"b9" => 12,"b6" => 13, - "d2" => 14,"c2" => 15,"b0" => 16,"b13"=> 17,"a5" => 18,"c9" => 19,"a2" => 20, - "c0" => 21,"c7" => 22,"c5" => 23,"b14"=> 24,"b7" => 25,"c4" => 26,"b10"=> 27, - "d1" => 28,"c6" => 29,"b11"=> 30,"a10"=> 31,"b1" => 32,"c1" => 33,"b5" => 34, - "d7" => 35,"d4" => 36,"a6" => 37,"a11"=> 38,"a7" => 39,"b2" => 40,"c11" => 41, - "c8" => 42,"a1" => 43,"a0" => 44,"d0" => 45,"a8" => 46,"b3" => 47,"b4" => 48); - - my @r; - - my $tile=0; - foreach my $p (@app){ - - - #my $l=$nmap{$p}; - #my $l=$rnd{$p}; - my $l=$worst{$p}; - - - $r[0][$tile]=$p; - $r[1][$tile]=(defined $l)? $results[1][$l]: undef; - $r[2][$tile]=(defined $l)? $results[2][$l]: undef; - $tile++; - } - - - - return @r; -} - -1; + my @results=@_; + my @app=( + "a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","a10","a11"," "," "," "," ", + "b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","b10","b11","b12","b13","b14","b15"," "," "," "," ", + "c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11"," "," "," "," ", + "d0","d1","d2","d3","d4","d5","d6","d7","d8"); + my %nmap=( + "b7" => 0 ,"b9" => 1 ,"b8" => 2 ,"a11"=> 3 ,"b11"=> 4 ,"b12"=> 5 ,"b13"=> 6 , + "b6" => 7 ,"b5" => 8 ,"a10"=> 9 ,"a8" => 10,"a9" => 11,"b14"=> 12,"b10"=> 13, + "b3" => 14,"b4" => 15,"a5" => 16,"a7" => 17,"a2" => 18,"d8" => 19,"d0" => 20, + "b2" => 21,"a3" => 22,"a6" => 23,"a0" => 24,"a1" => 25,"d1" => 26,"d2" => 27, + "b1" => 28,"b15"=> 29,"c2" => 30,"a4" => 31,"d4" => 32,"d3" => 33,"d5" => 34, + "b0" => 35,"c9" => 36,"c8" => 37,"c3" => 38,"d7" => 39,"d6" => 40,"c7" => 41, + "c11"=> 42,"c10"=> 43,"c5" => 44,"c4" => 45,"c1" => 46,"c0" => 47,"c6" => 48); + my %worst=( + "a0" => 0 ,"a8" => 1 ,"b7" => 2 ,"d8"=> 3 ,"b1"=> 4 ,"b5"=> 5 ,"b8"=> 6 , + "a5" => 7 ,"c2" => 8 ,"c10"=> 9 ,"c3" => 10,"c5" => 11,"b12"=> 12,"b3"=> 13, + "d1" => 14,"d7" => 15,"c1" => 16,"c7" => 17,"c0" => 18,"c8" => 19,"b10" => 20, + "b15" => 21,"d2" => 22,"c4" => 23,"c6" => 24,"c9" => 25,"d3" => 26,"a4" => 27, + "b2" => 28,"b13"=> 29,"d4" => 30,"c11" => 31,"d5" => 32,"a2" => 33,"a10" => 34, + "b6" => 35,"b0" => 36,"d0" => 37,"d6" => 38,"a3" => 39,"a9" => 40,"a6" => 41, + "b9"=> 42,"b4"=> 43,"b11" => 44,"b14" => 45,"a1" => 46,"a11" => 47,"a7" => 48); + my %rnd=( + "d3" => 0 ,"d6" => 1 ,"b8" => 2 ,"c10"=> 3 ,"d5" => 4 ,"d8" => 5 ,"a3" => 6 , + "b15"=> 7 ,"a9" => 8 ,"c3" => 9 ,"b12"=> 10,"a4" => 11,"b9" => 12,"b6" => 13, + "d2" => 14,"c2" => 15,"b0" => 16,"b13"=> 17,"a5" => 18,"c9" => 19,"a2" => 20, + "c0" => 21,"c7" => 22,"c5" => 23,"b14"=> 24,"b7" => 25,"c4" => 26,"b10"=> 27, + "d1" => 28,"c6" => 29,"b11"=> 30,"a10"=> 31,"b1" => 32,"c1" => 33,"b5" => 34, + "d7" => 35,"d4" => 36,"a6" => 37,"a11"=> 38,"a7" => 39,"b2" => 40,"c11" => 41, + "c8" => 42,"a1" => 43,"a0" => 44,"d0" => 45,"a8" => 46,"b3" => 47,"b4" => 48); + my @r; + my $tile=0; + foreach my $p (@app){ + #my $l=$nmap{$p}; + #my $l=$rnd{$p}; + my $l=$worst{$p}; + $r[0][$tile]=$p; + $r[1][$tile]=(defined $l)? $results[1][$l]: undef; + $r[2][$tile]=(defined $l)? $results[2][$l]: undef; + $tile++; + } + return @r; +} +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/hdr_file_gen.pl b/mpsoc/perl_gui/lib/perl/hdr_file_gen.pl index a7b854d..3df6e5c 100755 --- a/mpsoc/perl_gui/lib/perl/hdr_file_gen.pl +++ b/mpsoc/perl_gui/lib/perl/hdr_file_gen.pl @@ -1,5 +1,4 @@ use lib 'lib/perl'; - use strict; use warnings; use FindBin; @@ -7,187 +6,137 @@ use soc; use ip; - - ################## # header file gen ################## - - - sub get_instance_global_variable{ - my ($soc,$id) = @_; - my $module =$soc->soc_get_module($id); - my $module_name =$soc->soc_get_module_name($id); - my $category =$soc->soc_get_category($id); - my $inst =$soc->soc_get_instance_name($id); - my @plugs= $soc->soc_get_all_plugs_of_an_instance($id); - my %params= $soc->soc_get_module_param($id); - #add two extra variable the instance name and base addresses - my $core_id= $soc->object_get_attribute('global_param','CORE_ID'); - $params{CORE_ID}=(defined $core_id)? $core_id: 0; - $params{IP}=$inst; - $params{CORE}=$id; - foreach my $plug (@plugs){ - my @nums=$soc->soc_list_plug_nums($id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$plug,$num); - #wishbone slave address - if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ - #print "$addr,$base,$end,$connect_id,$connect_socket,$connect_socket_num\n"; - my $base_hex=sprintf("0X%08x", $base); - my $end_hex=sprintf("0X%08x", $end); - my $val="BASE".$num; - $params{$val}=$base_hex; - - } - - - } - } - $params{BASE}=$params{BASE0} if(defined $params{BASE0}); - - - return (\%params); + my ($soc,$id) = @_; + my $module =$soc->soc_get_module($id); + my $module_name =$soc->soc_get_module_name($id); + my $category =$soc->soc_get_category($id); + my $inst =$soc->soc_get_instance_name($id); + my @plugs= $soc->soc_get_all_plugs_of_an_instance($id); + my %params= $soc->soc_get_module_param($id); + #add two extra variable the instance name and base addresses + my $core_id= $soc->object_get_attribute('global_param','CORE_ID'); + $params{CORE_ID}=(defined $core_id)? $core_id: 0; + $params{IP}=$inst; + $params{CORE}=$id; + foreach my $plug (@plugs){ + my @nums=$soc->soc_list_plug_nums($id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$plug,$num); + #wishbone slave address + if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ + #print "$addr,$base,$end,$connect_id,$connect_socket,$connect_socket_num\n"; + my $base_hex=sprintf("0X%08x", $base); + my $end_hex=sprintf("0X%08x", $end); + my $val="BASE".$num; + $params{$val}=$base_hex; + } + } + } + $params{BASE}=$params{BASE0} if(defined $params{BASE0}); + return (\%params); } - sub replace_golb_var{ - my ($hdr,$ref)=@_; - my %params= %{$ref}; - foreach my $p (sort keys %params){ - my $pattern= '\$\{?' . $p . '(\}|\b)'; - ($hdr=$hdr)=~s/$pattern/$params{$p}/g; - } - return $hdr; - + my ($hdr,$ref)=@_; + my %params= %{$ref}; + foreach my $p (sort keys %params){ + my $pattern= '\$\{?' . $p . '(\}|\b)'; + ($hdr=$hdr)=~s/$pattern/$params{$p}/g; + } + return $hdr; } - - -sub generate_header_file{ - my ($soc,$project_dir,$sw_path,$hw_path,$dir)= @_; - my $soc_name=$soc->object_get_attribute('soc_name'); - $soc_name = uc($soc_name); - if(!defined $soc_name){$soc_name='soc'}; - - my $name=$soc->object_get_attribute('soc_name'); - - my @instances=$soc->soc_get_all_instances(); - my $system_h="#ifndef $soc_name\_SYSTEM_H\n\t#define $soc_name\_SYSTEM_H\n"; - my $system_c="#include \"$name.h\"\n\n"; - - #add_text_to_string(\$system_h, "\n #include \n #include \n #include \"aemb/core.hh\""); - - - my $ip = ip->lib_new (); - - - foreach my $id (@instances){ - my $module =$soc->soc_get_module($id); - my $module_name =$soc->soc_get_module_name($id); - my $category =$soc->soc_get_category($id); - my $inst =$soc->soc_get_instance_name($id); - - add_text_to_string(\$system_h,"\n \n /* $inst */ \n"); - $system_c = $system_c . "\n \n /* $inst */ \n"; - - #$inst=uc($inst); - # print base address - my @plugs= $soc->soc_get_all_plugs_of_an_instance($id); - - - my %params= %{get_instance_global_variable($soc,$id)}; - - - foreach my $plug (@plugs){ - my @nums=$soc->soc_list_plug_nums($id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$plug,$num); - #intrrupt - if((defined $connect_socket) && ($connect_socket eq 'interrupt_peripheral')){ - add_text_to_string(\$system_h,"//intrrupt flag location\n"); - add_text_to_string(\$system_h," #define $inst\_INT (1<<$connect_socket_num)\n") if(scalar (@nums)==1); - add_text_to_string(\$system_h," #define $inst\_$num\_INT (1<<$connect_socket_num)\n") if(scalar (@nums)>1); - add_text_to_string(\$system_h," #define $inst\_INT_PIN $connect_socket_num\n") if(scalar (@nums)==1); - add_text_to_string(\$system_h," #define $inst\_$num\_INT_PIN $connect_socket_num\n") if(scalar (@nums)>1); - } - - } - } - - - my $hdr_h=$ip->ip_get($category,$module,"system_h"); - if(defined $hdr_h){ - $hdr_h=replace_golb_var($hdr_h,\%params); - add_text_to_string(\$system_h,"$hdr_h\n"); - } - - - my $hdr_c=$ip->ip_get($category,$module,"system_c"); - if(defined $hdr_c){ - $hdr_c=replace_golb_var($hdr_c,\%params); - $system_c=$system_c."$hdr_c\n"; - } - - - # Write Software gen files - my @sw_file_gen = $ip->ip_get_list($category,$module,"gen_sw_files"); - foreach my $file (@sw_file_gen){ - if(defined $file ){ - my ($path,$rename)=split('frename_sep_t',$file); - $rename=replace_golb_var($rename,\%params); - #read the file content - my $content=read_file_cntent($path,$project_dir); - $content=replace_golb_var($content,\%params); - - if(defined $rename){ - open(FILE, ">$sw_path/$rename") || die "Can not open: $!"; - print FILE $content; - close(FILE) || die "Error closing file: $!"; - } - } - } - - # Write Hardware gen files - my @hw_file_gen = $ip->ip_get_list($category,$module,"gen_hw_files"); - foreach my $file (@hw_file_gen){ - if(defined $file ){ - my ($path,$rename)=split('frename_sep_t',$file); - $rename=replace_golb_var($rename,\%params); - #read the file content - my $content=read_file_cntent($path,$project_dir); - $content=replace_golb_var($content,\%params); - - if(defined $rename){ - open(FILE, ">$hw_path/$rename") || die "Can not open: $!"; - print FILE $content; - close(FILE) || die "Error closing file: $!"; - } - } - } - - - - } - - add_text_to_string(\$system_h,"#endif\n"); - - #write sytem.h file - open(FILE, ">$sw_path/$name.h") || die "Can not open: $!"; - print FILE $system_h; - close(FILE) || die "Error closing file: $!"; - - #write system.c file - open(FILE, ">$sw_path/$name.c") || die "Can not open: $!"; - print FILE $system_c; - close(FILE) || die "Error closing file: $!"; - - - - - +sub generate_header_file{ + my ($soc,$project_dir,$sw_path,$hw_path,$dir)= @_; + my $soc_name=$soc->object_get_attribute('soc_name'); + $soc_name = uc($soc_name); + if(!defined $soc_name){$soc_name='soc'}; + my $name=$soc->object_get_attribute('soc_name'); + my @instances=$soc->soc_get_all_instances(); + my $system_h="#ifndef $soc_name\_SYSTEM_H\n\t#define $soc_name\_SYSTEM_H\n"; + my $system_c="#include \"$name.h\"\n\n"; + #add_text_to_string(\$system_h, "\n #include \n #include \n #include \"aemb/core.hh\""); + my $ip = ip->lib_new (); + foreach my $id (@instances){ + my $module =$soc->soc_get_module($id); + my $module_name =$soc->soc_get_module_name($id); + my $category =$soc->soc_get_category($id); + my $inst =$soc->soc_get_instance_name($id); + add_text_to_string(\$system_h,"\n \n /* $inst */ \n"); + $system_c = $system_c . "\n \n /* $inst */ \n"; + #$inst=uc($inst); + # print base address + my @plugs= $soc->soc_get_all_plugs_of_an_instance($id); + my %params= %{get_instance_global_variable($soc,$id)}; + foreach my $plug (@plugs){ + my @nums=$soc->soc_list_plug_nums($id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$plug,$num); + #intrrupt + if((defined $connect_socket) && ($connect_socket eq 'interrupt_peripheral')){ + add_text_to_string(\$system_h,"//intrrupt flag location\n"); + add_text_to_string(\$system_h," #define $inst\_INT (1<<$connect_socket_num)\n") if(scalar (@nums)==1); + add_text_to_string(\$system_h," #define $inst\_$num\_INT (1<<$connect_socket_num)\n") if(scalar (@nums)>1); + add_text_to_string(\$system_h," #define $inst\_INT_PIN $connect_socket_num\n") if(scalar (@nums)==1); + add_text_to_string(\$system_h," #define $inst\_$num\_INT_PIN $connect_socket_num\n") if(scalar (@nums)>1); + } + } + } + my $hdr_h=$ip->ip_get($category,$module,"system_h"); + if(defined $hdr_h){ + $hdr_h=replace_golb_var($hdr_h,\%params); + add_text_to_string(\$system_h,"$hdr_h\n"); + } + my $hdr_c=$ip->ip_get($category,$module,"system_c"); + if(defined $hdr_c){ + $hdr_c=replace_golb_var($hdr_c,\%params); + $system_c=$system_c."$hdr_c\n"; + } + # Write Software gen files + my @sw_file_gen = $ip->ip_get_list($category,$module,"gen_sw_files"); + foreach my $file (@sw_file_gen){ + if(defined $file ){ + my ($path,$rename)=split('frename_sep_t',$file); + $rename=replace_golb_var($rename,\%params); + #read the file content + my $content=read_file_cntent($path,$project_dir); + $content=replace_golb_var($content,\%params); + if(defined $rename){ + open(FILE, ">$sw_path/$rename") || die "Can not open: $!"; + print FILE $content; + close(FILE) || die "Error closing file: $!"; + } + } + } + # Write Hardware gen files + my @hw_file_gen = $ip->ip_get_list($category,$module,"gen_hw_files"); + foreach my $file (@hw_file_gen){ + if(defined $file ){ + my ($path,$rename)=split('frename_sep_t',$file); + $rename=replace_golb_var($rename,\%params); + #read the file content + my $content=read_file_cntent($path,$project_dir); + $content=replace_golb_var($content,\%params); + if(defined $rename){ + open(FILE, ">$hw_path/$rename") || die "Can not open: $!"; + print FILE $content; + close(FILE) || die "Error closing file: $!"; + } + } + } + } + add_text_to_string(\$system_h,"#endif\n"); + #write sytem.h file + open(FILE, ">$sw_path/$name.h") || die "Can not open: $!"; + print FILE $system_h; + close(FILE) || die "Error closing file: $!"; + #write system.c file + open(FILE, ">$sw_path/$name.c") || die "Can not open: $!"; + print FILE $system_c; + close(FILE) || die "Error closing file: $!"; } - - -1 +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/interface.pm b/mpsoc/perl_gui/lib/perl/interface.pm index be71cb7..92dd951 100755 --- a/mpsoc/perl_gui/lib/perl/interface.pm +++ b/mpsoc/perl_gui/lib/perl/interface.pm @@ -2,302 +2,238 @@ ############################################################################### # # File: interface.pm -# +# # ############################################################################### use warnings; use strict; use intfc_gen; use Data::Dumper; - use Cwd; - - - package interface; - - - - sub interface_new { # be backwards compatible with non-OO call my $class = ("ARRAY" eq ref $_[0]) ? "interface" : shift; my $self; - - $self = {}; - $self->{plugs} = {}; - $self->{sockets} = {}; - $self->{categories} = {}; - - - my $dir = Cwd::getcwd(); - $dir =~ s/ /\\ /g; - my @files = glob "$dir/lib/interface/*.ITC"; - for my $p (@files){ - #print "$p\n"; - #my $infc_gen = Storable::retrieve($p); - # Read - my $infc_gen; - $infc_gen = eval { do $p }; - # Might need "no strict;" before and "use strict;" after "do" - die "Error reading: $@" if $@; - - add_intfc($self,$infc_gen); - } - - + $self->{plugs} = {}; + $self->{sockets} = {}; + $self->{categories} = {}; + my $dir = Cwd::getcwd(); + $dir =~ s/ /\\ /g; + my @files = glob "$dir/lib/interface/*.ITC"; + for my $p (@files){ + #print "$p\n"; + #my $infc_gen = Storable::retrieve($p); + # Read + my $infc_gen; + $infc_gen = eval { do $p }; + # Might need "no strict;" before and "use strict;" after "do" + die "Error reading: $@" if $@; + add_intfc($self,$infc_gen); + } bless($self,$class); - - return $self; -} - +} sub add_category{ - my ($self,$category,$intfc_name,$info)=@_; - $self->{categories}{$category}{names}{$intfc_name}{info}=$info; - -} + my ($self,$category,$intfc_name,$info)=@_; + $self->{categories}{$category}{names}{$intfc_name}{info}=$info; +} sub get_description{ - my ($self,$category,$name)=@_; - my $info; - if(exists ($self->{categories}{$category}{names}{$name})){ - $info= $self->{categories}{$category}{names}{$name}{info}; - } - return $info; -} - + my ($self,$category,$name)=@_; + my $info; + if(exists ($self->{categories}{$category}{names}{$name})){ + $info= $self->{categories}{$category}{names}{$name}{info}; + } + return $info; +} sub add_plug{ - my($self,$plug,$info,$category,$connection_num,$connect_to)=@_; - $self->{plugs}{$plug}={}; - $self->{plugs}{$plug}{connection_num}=$connection_num; - $self->{plugs}{$plug}{connect_to}=$connect_to; - $self->{plugs}{$plug}{info}=$info; - $self->{plugs}{$plug}{category}=$category; + my($self,$plug,$info,$category,$connection_num,$connect_to)=@_; + $self->{plugs}{$plug}={}; + $self->{plugs}{$plug}{connection_num}=$connection_num; + $self->{plugs}{$plug}{connect_to}=$connect_to; + $self->{plugs}{$plug}{info}=$info; + $self->{plugs}{$plug}{category}=$category; } sub get_plug{ - my($self,$plug)=@_; - my ($connection_num,$connect_to,$info,$category); - if(exists ($self->{plugs}{$plug})){ - $connection_num =$self->{plugs}{$plug}{connection_num}; - $connect_to =$self->{plugs}{$plug}{connect_to}; - $info =$self->{plugs}{$plug}{info}; - $category =$self->{plugs}{$plug}{category}; - - } - return ($connection_num,$connect_to,$info,$category); -} - - + my($self,$plug)=@_; + my ($connection_num,$connect_to,$info,$category); + if(exists ($self->{plugs}{$plug})){ + $connection_num =$self->{plugs}{$plug}{connection_num}; + $connect_to =$self->{plugs}{$plug}{connect_to}; + $info =$self->{plugs}{$plug}{info}; + $category =$self->{plugs}{$plug}{category}; + } + return ($connection_num,$connect_to,$info,$category); +} sub add_socket{ - my($self,$socket,$info,$category,$connection_num,$connect_to)=@_; - $self->{sockets}{$socket}={}; - $self->{sockets}{$socket}{connection_num}=$connection_num; - $self->{sockets}{$socket}{connect_to}=$connect_to; - $self->{sockets}{$socket}{info}=$info; - $self->{sockets}{$socket}{category}=$category; -} - - + my($self,$socket,$info,$category,$connection_num,$connect_to)=@_; + $self->{sockets}{$socket}={}; + $self->{sockets}{$socket}{connection_num}=$connection_num; + $self->{sockets}{$socket}{connect_to}=$connect_to; + $self->{sockets}{$socket}{info}=$info; + $self->{sockets}{$socket}{category}=$category; +} + sub get_socket{ - my($self,$socket)=@_; - my ($connection_num,$connect_to,$info,$category); - if(exists ($self->{sockets}{$socket})){ - $connection_num =$self->{sockets}{$socket}{connection_num}; - $connect_to =$self->{sockets}{$socket}{connect_to}; - $info =$self->{sockets}{$socket}{info}; - $category =$self->{sockets}{$socket}{category}=$category; - } - return ($connection_num,$connect_to,$info,$category); -} - + my($self,$socket)=@_; + my ($connection_num,$connect_to,$info,$category); + if(exists ($self->{sockets}{$socket})){ + $connection_num =$self->{sockets}{$socket}{connection_num}; + $connect_to =$self->{sockets}{$socket}{connect_to}; + $info =$self->{sockets}{$socket}{info}; + $category =$self->{sockets}{$socket}{category}=$category; + } + return ($connection_num,$connect_to,$info,$category); +} sub add_param_to_plug{ - my($self,$interface,$param,$value)=@_; - $self->{plugs}{$interface}{parameters}{$param}=$value; - + my($self,$interface,$param,$value)=@_; + $self->{plugs}{$interface}{parameters}{$param}=$value; } - sub add_param_to_socket{ - my($self,$interface,$param,$value)=@_; - $self->{sockets}{$interface}{parameters}{$param}=$value; - -} - - + my($self,$interface,$param,$value)=@_; + $self->{sockets}{$interface}{parameters}{$param}=$value; +} sub add_port_to_plug{ - my($self,$interface,$port,$range,$type,$outport_type,$connect,$default_out)=@_; - $self->{plugs}{$interface}{ports}{$port}={}; - $self->{plugs}{$interface}{ports}{$port}{range}=$range; - $self->{plugs}{$interface}{ports}{$port}{type}=$type; - $self->{plugs}{$interface}{ports}{$port}{outport_type}=$outport_type; - $self->{plugs}{$interface}{ports}{$port}{connect}=$connect; - $self->{plugs}{$interface}{ports}{$port}{default_out}=$default_out; - + my($self,$interface,$port,$range,$type,$outport_type,$connect,$default_out)=@_; + $self->{plugs}{$interface}{ports}{$port}={}; + $self->{plugs}{$interface}{ports}{$port}{range}=$range; + $self->{plugs}{$interface}{ports}{$port}{type}=$type; + $self->{plugs}{$interface}{ports}{$port}{outport_type}=$outport_type; + $self->{plugs}{$interface}{ports}{$port}{connect}=$connect; + $self->{plugs}{$interface}{ports}{$port}{default_out}=$default_out; } - sub get_port_info_of_socket{ - my($self,$socket,$port)=@_; - my($range,$type,$connect,$default_out); - if(exists ($self->{sockets}{$socket}{ports}{$port})){ - $range=$self->{sockets}{$socket}{ports}{$port}{range}; - $type=$self->{sockets}{$socket}{ports}{$port}{type}; - $connect=$self->{sockets}{$socket}{ports}{$port}{connect}; - $default_out=$self->{sockets}{$socket}{ports}{$port}{default_out}; - } - return ($range,$type,$connect,$default_out); + my($self,$socket,$port)=@_; + my($range,$type,$connect,$default_out); + if(exists ($self->{sockets}{$socket}{ports}{$port})){ + $range=$self->{sockets}{$socket}{ports}{$port}{range}; + $type=$self->{sockets}{$socket}{ports}{$port}{type}; + $connect=$self->{sockets}{$socket}{ports}{$port}{connect}; + $default_out=$self->{sockets}{$socket}{ports}{$port}{default_out}; + } + return ($range,$type,$connect,$default_out); } sub get_port_info_of_plug{ - my($self,$plug,$port)=@_; - my($range,$type,$connect,$default_out); - if(exists ($self->{plugs}{$plug}{ports}{$port})){ - $range=$self->{plugs}{$plug}{ports}{$port}{range}; - $type=$self->{plugs}{$plug}{ports}{$port}{type}; - $connect=$self->{plugs}{$plug}{ports}{$port}{connect}; - $default_out=$self->{plugs}{$plug}{ports}{$port}{default_out}; - - } - return ($range,$type,$connect,$default_out); + my($self,$plug,$port)=@_; + my($range,$type,$connect,$default_out); + if(exists ($self->{plugs}{$plug}{ports}{$port})){ + $range=$self->{plugs}{$plug}{ports}{$port}{range}; + $type=$self->{plugs}{$plug}{ports}{$port}{type}; + $connect=$self->{plugs}{$plug}{ports}{$port}{connect}; + $default_out=$self->{plugs}{$plug}{ports}{$port}{default_out}; + } + return ($range,$type,$connect,$default_out); } - sub add_port_to_socket{ - my($self,$socket,$port,$range,$type,$outport_type,$connect,$default_out)=@_; - $self->{sockets}{$socket}{ports}{$port}={}; - $self->{sockets}{$socket}{ports}{$port}{range}=$range; - $self->{sockets}{$socket}{ports}{$port}{type}=$type; - $self->{sockets}{$socket}{ports}{$port}{outport_type}=$outport_type; - $self->{sockets}{$socket}{ports}{$port}{connect}=$connect; - $self->{sockets}{$socket}{ports}{$port}{default_out}=$default_out; - + my($self,$socket,$port,$range,$type,$outport_type,$connect,$default_out)=@_; + $self->{sockets}{$socket}{ports}{$port}={}; + $self->{sockets}{$socket}{ports}{$port}{range}=$range; + $self->{sockets}{$socket}{ports}{$port}{type}=$type; + $self->{sockets}{$socket}{ports}{$port}{outport_type}=$outport_type; + $self->{sockets}{$socket}{ports}{$port}{connect}=$connect; + $self->{sockets}{$socket}{ports}{$port}{default_out}=$default_out; } - sub get_socket_port_list{ - my($self,$socket)=@_; - my @ports; - if(exists ($self->{sockets}{$socket}{ports})){ - foreach my $p(keys %{$self->{sockets}{$socket}{ports}}){ - push (@ports,$p); - } - } - return @ports; + my($self,$socket)=@_; + my @ports; + if(exists ($self->{sockets}{$socket}{ports})){ + foreach my $p(keys %{$self->{sockets}{$socket}{ports}}){ + push (@ports,$p); + } + } + return @ports; } sub get_plug_port_list{ - my($self,$plug)=@_; - my @ports; - if(exists ($self->{plugs}{$plug}{ports})){ - foreach my $p(keys %{$self->{plugs}{$plug}{ports}}){ - push (@ports,$p); - } - } - return @ports; + my($self,$plug)=@_; + my @ports; + if(exists ($self->{plugs}{$plug}{ports})){ + foreach my $p(keys %{$self->{plugs}{$plug}{ports}}){ + push (@ports,$p); + } + } + return @ports; } - - sub get_interfaces{ - my $self=shift; - my @interfaces; - if(exists ($self->{plugs})){ - foreach my $p (sort keys %{$self->{plugs}}){ - push (@interfaces,$p); - } - } - return @interfaces; - - -} + my $self=shift; + my @interfaces; + if(exists ($self->{plugs})){ + foreach my $p (sort keys %{$self->{plugs}}){ + push (@interfaces,$p); + } + } + return @interfaces; +} sub get_categories{ - my $self=shift; - my @categories; - if(exists ($self->{categories})){ - foreach my $p (sort keys %{$self->{categories}}){ - push (@categories,$p); - } - } - return @categories; - -} - -sub get_intfcs_of_category{ - my ($self,$category)=@_; - my @list; - if(exists ($self->{categories}{$category}{names})){ - foreach my $p (sort keys %{$self->{categories}{$category}{names}}){ - push (@list,$p); - } - - } - return @list; -} + my $self=shift; + my @categories; + if(exists ($self->{categories})){ + foreach my $p (sort keys %{$self->{categories}}){ + push (@categories,$p); + } + } + return @categories; +} +sub get_intfcs_of_category{ + my ($self,$category)=@_; + my @list; + if(exists ($self->{categories}{$category}{names})){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}}){ + push (@list,$p); + } + } + return @list; +} sub add_intfc{ - - my ($self,$infc_gen) =@_; - - my $intfc_name=$infc_gen->object_get_attribute('name'); - my $connection_num=$infc_gen->object_get_attribute('connection_num'); - my $intfc_type=$infc_gen->object_get_attribute('type'); - my $intfc_info=$infc_gen->object_get_attribute('description'); - my $intfc_category=$infc_gen->object_get_attribute('category'); - - - my(%types,%ranges,%names,%connect_types,%connect_ranges,%connect_names,%outport_types,%default_outs); - - - add_socket($self,$intfc_name,$intfc_info,$intfc_category,$connection_num,$intfc_name); - add_plug($self,$intfc_name,$intfc_info,$intfc_category,$connection_num,$intfc_name); - - add_category($self,$intfc_category,$intfc_name,$intfc_info); - - - $infc_gen->intfc_get_ports(\%types,\%ranges,\%names,\%connect_types,\%connect_ranges,\%connect_names,\%outport_types,\%default_outs); - foreach my $id (sort keys %ranges){ - my $type=$types{$id}; - my $range=$ranges{$id}; - my $name=$names{$id}; - my $connect_type=$connect_types{$id}; - my $connect_range=$connect_ranges{$id}; - my $connect_name=$connect_names{$id}; - my $outport_type=$outport_types{$id}; - my $default_out=$default_outs{$id}; - if($intfc_type eq 'plug'){ - - #my($self,$interface,$port,$range,$type,$outport_type) - add_port_to_plug ($self,$intfc_name,$name,$range,$type,$outport_type,$connect_name,$default_out); - #print "add_port_to_plug(\$self,$intfc_name,$name,$range,$type,,$outport_type);\n"; - add_port_to_socket ($self,$intfc_name,$connect_name,$connect_range,$connect_type,$outport_type,$name,$default_out); - #print "add_port_to_socket(\$self,$connect_name,$connect_range,$connect_type);\n"; - } - else{ - add_port_to_socket($self,$intfc_name,$name,$range,$type,$outport_type,$connect_name,$default_out); - add_port_to_plug($self,$intfc_name,$connect_name,$connect_range,$connect_type,$outport_type,$name,$default_out); - } - } - -} - - - - - - - - - - -1 + my ($self,$infc_gen) =@_; + my $intfc_name=$infc_gen->object_get_attribute('name'); + my $connection_num=$infc_gen->object_get_attribute('connection_num'); + my $intfc_type=$infc_gen->object_get_attribute('type'); + my $intfc_info=$infc_gen->object_get_attribute('description'); + my $intfc_category=$infc_gen->object_get_attribute('category'); + my(%types,%ranges,%names,%connect_types,%connect_ranges,%connect_names,%outport_types,%default_outs); + add_socket($self,$intfc_name,$intfc_info,$intfc_category,$connection_num,$intfc_name); + add_plug($self,$intfc_name,$intfc_info,$intfc_category,$connection_num,$intfc_name); + add_category($self,$intfc_category,$intfc_name,$intfc_info); + $infc_gen->intfc_get_ports(\%types,\%ranges,\%names,\%connect_types,\%connect_ranges,\%connect_names,\%outport_types,\%default_outs); + foreach my $id (sort keys %ranges){ + my $type=$types{$id}; + my $range=$ranges{$id}; + my $name=$names{$id}; + my $connect_type=$connect_types{$id}; + my $connect_range=$connect_ranges{$id}; + my $connect_name=$connect_names{$id}; + my $outport_type=$outport_types{$id}; + my $default_out=$default_outs{$id}; + if($intfc_type eq 'plug'){ + #my($self,$interface,$port,$range,$type,$outport_type) + add_port_to_plug ($self,$intfc_name,$name,$range,$type,$outport_type,$connect_name,$default_out); + #print "add_port_to_plug(\$self,$intfc_name,$name,$range,$type,,$outport_type);\n"; + add_port_to_socket ($self,$intfc_name,$connect_name,$connect_range,$connect_type,$outport_type,$name,$default_out); + #print "add_port_to_socket(\$self,$connect_name,$connect_range,$connect_type);\n"; + } + else{ + add_port_to_socket($self,$intfc_name,$name,$range,$type,$outport_type,$connect_name,$default_out); + add_port_to_plug($self,$intfc_name,$connect_name,$connect_range,$connect_type,$outport_type,$name,$default_out); + } + } +} +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/interface_gen.pl b/mpsoc/perl_gui/lib/perl/interface_gen.pl index 065faec..64a4699 100755 --- a/mpsoc/perl_gui/lib/perl/interface_gen.pl +++ b/mpsoc/perl_gui/lib/perl/interface_gen.pl @@ -2,749 +2,507 @@ use constant::boolean; use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - use Data::Dumper; use intfc_gen; use rvp; - - - - -require "widget.pl"; - +require "widget.pl"; sub read_file_modules{ - my ($file,$intfc_gen,$info)=@_; - - if (!defined $file) { - add_colored_info($info,"No input file is given. Please set an input Verilog fle first.\n", 'red'); - return; - } - - my $f=add_project_dir_to_addr($file); - if (-e $f) { - my $vdb = read_verilog_file($f); - my @modules=sort $vdb->get_modules($f); - #foreach my $p(@module_list) {print "$p\n"} - $intfc_gen->intfc_set_interface_file($file); - $intfc_gen->intfc_set_module_name($modules[0]); - $intfc_gen->intfc_add_module_list(@modules); - - set_gui_status($intfc_gen,"file_selected",1); - add_info($info,"$f is loaded\n"); - - } - else { - add_colored_info($info,"File $file does not exist!\n", 'red'); - - } -} - + my ($file,$intfc_gen,$info)=@_; + if (!defined $file) { + add_colored_info($info,"No input file is given. Please set an input Verilog fle first.\n", 'red'); + return; + } + my $f=add_project_dir_to_addr($file); + if (-e $f) { + my $vdb = read_verilog_file($f); + my @modules=sort $vdb->get_modules($f); + #foreach my $p(@module_list) {print "$p\n"} + $intfc_gen->intfc_set_interface_file($file); + $intfc_gen->intfc_set_module_name($modules[0]); + $intfc_gen->intfc_add_module_list(@modules); + set_gui_status($intfc_gen,"file_selected",1); + add_info($info,"$f is loaded\n"); + } + else { + add_colored_info($info,"File $file does not exist!\n", 'red'); + } +} ################ # check_input_intfc_file ################ - sub check_input_intfc_file{ - my ($file,$intfc_gen,$info)=@_; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.ITC'){ - $intfc_gen->intfc_set_interface_file($file); - set_gui_status($intfc_gen,"load_file",0); - - - }else{ - read_file_modules($file,$intfc_gen,$info); - - } - - -} + my ($file,$intfc_gen,$info)=@_; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.ITC'){ + $intfc_gen->intfc_set_interface_file($file); + set_gui_status($intfc_gen,"load_file",0); + }else{ + read_file_modules($file,$intfc_gen,$info); + } +} sub file_box { - my ($intfc_gen,$info)=@_; - my $label = gen_label_in_left("Select file:"); - my $entry = gen_entry(); - my $open= def_image_button("icons/select.png","Open"); - my $browse= def_image_button("icons/browse.png","Browse"); - my $file= $intfc_gen->intfc_get_interface_file(); - my $intfc_info= def_image_button("icons/add_info.png","Description"); - my $table = def_table(1,10,FALSE); - $intfc_info->signal_connect("clicked"=> sub{ - get_intfc_description($intfc_gen,$info); - - - }); - - if(defined $file){$entry->set_text($file);} - else {show_info($info,"Please select the Verilog file containing the interface\n");} - - - $browse->signal_connect("clicked"=> sub{ - my $entry_ref=$_[1]; - my $file; + my ($intfc_gen,$info)=@_; + my $label = gen_label_in_left("Select file:"); + my $entry = gen_entry(); + my $open= def_image_button("icons/select.png","Open"); + my $browse= def_image_button("icons/browse.png","Browse"); + my $file= $intfc_gen->intfc_get_interface_file(); + my $intfc_info= def_image_button("icons/add_info.png","Description"); + my $table = def_table(1,10,FALSE); + $intfc_info->signal_connect("clicked"=> sub{ + get_intfc_description($intfc_gen,$info); + }); + if(defined $file){$entry->set_text($file);} + else {show_info($info,"Please select the Verilog file containing the interface\n");} + $browse->signal_connect("clicked"=> sub{ + my $entry_ref=$_[1]; + my $file; my $dialog = gen_file_dialog (undef, 'v','ITC'); - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - $$entry_ref->set_text($file); - check_input_intfc_file($file,$intfc_gen,$info); - } - $dialog->destroy; - } , \$entry); - - $open->signal_connect("clicked"=> sub{ - my $file_name=$entry->get_text(); - check_input_intfc_file($file,$intfc_gen,$info); - #read_file_modules($file_name,$intfc_gen,$info); - - }); - $entry->signal_connect("activate"=>sub{ - my $file_name=$entry->get_text(); - read_file_modules($file_name,$intfc_gen,$info); - }); - - $entry->signal_connect("changed"=>sub{ - #show_info($info,"Please select the verilog file containing the interface\n"); - }); - - my $row=0; - $table->attach_defaults ($label, 0, 1 , $row, $row+1); - $table->attach_defaults ($entry, 1, 7 , $row, $row+1); - $table->attach ($browse, 7, 8, $row, $row+1,'shrink','shrink',2,2); - $table->attach ($intfc_info, 8, 9 , $row, $row+1,'shrink','shrink',2,2); - #$table->attach_defaults ($open, 9, 10, $row, $row+1); - #$table->attach_defaults ($entry, $col, $col+1, $row, $row+1); - return $table; - - + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + $$entry_ref->set_text($file); + check_input_intfc_file($file,$intfc_gen,$info); + } + $dialog->destroy; + } , \$entry); + $open->signal_connect("clicked"=> sub{ + my $file_name=$entry->get_text(); + check_input_intfc_file($file,$intfc_gen,$info); + #read_file_modules($file_name,$intfc_gen,$info); + }); + $entry->signal_connect("activate"=>sub{ + my $file_name=$entry->get_text(); + read_file_modules($file_name,$intfc_gen,$info); + }); + $entry->signal_connect("changed"=>sub{ + #show_info($info,"Please select the verilog file containing the interface\n"); + }); + my $row=0; + $table->attach_defaults ($label, 0, 1 , $row, $row+1); + $table->attach_defaults ($entry, 1, 7 , $row, $row+1); + $table->attach ($browse, 7, 8, $row, $row+1,'shrink','shrink',2,2); + $table->attach ($intfc_info, 8, 9 , $row, $row+1,'shrink','shrink',2,2); + #$table->attach_defaults ($open, 9, 10, $row, $row+1); + #$table->attach_defaults ($entry, $col, $col+1, $row, $row+1); + return $table; } - - - - sub get_interface_ports { - my ($intfc_gen,$info)=@_; - my $window=def_popwin_size(60,60,"Import Ports",'percent'); - - my $file=$intfc_gen->intfc_get_interface_file(); - if (!defined $file){show_info($info,"File name has not been defined yet!"); return;} - my $module=$intfc_gen->intfc_get_module_name(); - if (!defined $module){ show_info($info,"Module name has not been selected yet!"); return;} - my $f=add_project_dir_to_addr($file); - my $vdb=read_verilog_file($f); - my %port_type=get_ports_type($vdb,$module); - my %port_range=get_ports_rang($vdb,$module); - - my $table=def_table(8,8,TRUE); - my $scrolled_win = add_widget_to_scrolled_win($table); - - - my $title=gen_label_in_center("Select the ports included in the interface"); - my $title1=gen_label_in_center("Type"); - my $title2=gen_label_in_center("Range"); - my $title3=gen_label_in_center("Name"); - my $title4=gen_label_in_center("Select"); - - my $row =0; - $table->attach_defaults($title, 0,8, $row, $row+1); - $row++; - $table->attach_defaults($title1, 0,1, $row, $row+1); - $table->attach_defaults($title2, 1,4, $row, $row+1); - $table->attach_defaults($title3, 4,7, $row, $row+1); - $table->attach_defaults($title4, 7,8, $row, $row+1); - $row++; - - add_Hsep_to_table($table, 0, 8 , $row); $row++; - - $intfc_gen->intfc_remove_ports(); - foreach my $p (sort keys %port_type){ - my $port_id= $p; - my $porttype=$port_type{$p}; - my $label1= gen_label_in_center("$porttype"); - $table->attach_defaults($label1, 0,1, $row, $row+1); - my $portrange=$port_range{$p}; - if ( $port_range{$p} ne ''){ - - my $label2= gen_label_in_center("\[$portrange\]"); - $table->attach_defaults($label2, 1,4, $row, $row+1); - } - - my $label3= gen_label_in_center($p); - $table->attach_defaults($label3, 4,7, $row, $row+1); - - my $check= gen_checkbutton(); - $table->attach_defaults($check, 7,8, $row, $row+1); - - $row++; - if($row>8){$table->resize ($row, 8);} - #print "$p\:$port_type{$p}\n"; - - $check->signal_connect("toggled"=>sub{ - my $widget=shift; - my $in=$widget->get_active(); - if ($in eq 1){ - my $connect_type=($porttype eq "input")? "output" : ($porttype eq "output")? "input" : $porttype; - $intfc_gen->intfc_add_port($port_id,$porttype,$portrange,$p,$connect_type,$portrange,$p,"concatenate","Active low"); - - - - #print "chanhed to $in \n"; - }else { - $intfc_gen->intfc_remove_port($port_id); - - #print "chanhed to 0 \n"; - - } - - - }); - - } - - - my $ok= def_image_button("icons/select.png","ok"); - $table->attach($ok, 3,5, $row, $row+1,'shrink','shrink',2,2); - - $ok->signal_connect("clicked"=>sub{ - $window->destroy; - set_gui_status($intfc_gen,"refresh",1); - - - }); - - $window->add($scrolled_win); - - $window->show_all(); -} - - - - - + my ($intfc_gen,$info)=@_; + my $window=def_popwin_size(60,60,"Import Ports",'percent'); + my $file=$intfc_gen->intfc_get_interface_file(); + if (!defined $file){show_info($info,"File name has not been defined yet!"); return;} + my $module=$intfc_gen->intfc_get_module_name(); + if (!defined $module){ show_info($info,"Module name has not been selected yet!"); return;} + my $f=add_project_dir_to_addr($file); + my $vdb=read_verilog_file($f); + my %port_type=get_ports_type($vdb,$module); + my %port_range=get_ports_rang($vdb,$module); + my $table=def_table(8,8,TRUE); + my $scrolled_win = add_widget_to_scrolled_win($table); + my $title=gen_label_in_center("Select the ports included in the interface"); + my $title1=gen_label_in_center("Type"); + my $title2=gen_label_in_center("Range"); + my $title3=gen_label_in_center("Name"); + my $title4=gen_label_in_center("Select"); + my $row =0; + $table->attach_defaults($title, 0,8, $row, $row+1); + $row++; + $table->attach_defaults($title1, 0,1, $row, $row+1); + $table->attach_defaults($title2, 1,4, $row, $row+1); + $table->attach_defaults($title3, 4,7, $row, $row+1); + $table->attach_defaults($title4, 7,8, $row, $row+1); + $row++; + add_Hsep_to_table($table, 0, 8 , $row); $row++; + $intfc_gen->intfc_remove_ports(); + foreach my $p (sort keys %port_type){ + my $port_id= $p; + my $porttype=$port_type{$p}; + my $label1= gen_label_in_center("$porttype"); + $table->attach_defaults($label1, 0,1, $row, $row+1); + my $portrange=$port_range{$p}; + if ( $port_range{$p} ne ''){ + my $label2= gen_label_in_center("\[$portrange\]"); + $table->attach_defaults($label2, 1,4, $row, $row+1); + } + my $label3= gen_label_in_center($p); + $table->attach_defaults($label3, 4,7, $row, $row+1); + my $check= gen_checkbutton(); + $table->attach_defaults($check, 7,8, $row, $row+1); + $row++; + if($row>8){$table->resize ($row, 8);} + #print "$p\:$port_type{$p}\n"; + $check->signal_connect("toggled"=>sub{ + my $widget=shift; + my $in=$widget->get_active(); + if ($in eq 1){ + my $connect_type=($porttype eq "input")? "output" : ($porttype eq "output")? "input" : $porttype; + $intfc_gen->intfc_add_port($port_id,$porttype,$portrange,$p,$connect_type,$portrange,$p,"concatenate","Active low"); + #print "chanhed to $in \n"; + }else { + $intfc_gen->intfc_remove_port($port_id); + #print "chanhed to 0 \n"; + } + }); + } + my $ok= def_image_button("icons/select.png","ok"); + $table->attach($ok, 3,5, $row, $row+1,'shrink','shrink',2,2); + $ok->signal_connect("clicked"=>sub{ + $window->destroy; + set_gui_status($intfc_gen,"refresh",1); + }); + $window->add($scrolled_win); + $window->show_all(); +} sub module_select{ - my ($intfc_gen,$info)=@_; - #my $file= $intfc_gen->intfc_get_interface_file(); - - my $table = def_table(1,10,FALSE); - - - - my @modules= $intfc_gen->intfc_get_module_list(); - my $combo=gen_combobox_object($intfc_gen,'module_name',undef,join(',', @modules),undef,'refresh',1); - my $modul_name=gen_label_info(" Select module:",$combo); - - - my $port= def_image_button("icons/import.png","Import Ports"); - my $category_entry=gen_entry_object($intfc_gen,'category',undef,undef,undef,undef); - my $category=gen_label_info(" Select Category:",$category_entry,'Define the Interface category:e.g RAM, wishbone,...'); - - - - - my $row=0; - #$table->attach_defaults ($label, 0, 1 , $row, $row+1); - $table->attach ($modul_name, 0, 3 , $row,$row+1,'shrink','shrink',2,2); - $table->attach ($port, 4, 6 , $row, $row+1,'shrink','shrink',2,2); - $table->attach_defaults ($category, 7, 10 , $row, $row+1); - - - - - $port->signal_connect("clicked"=> sub{ - get_interface_ports($intfc_gen,$info); - - - }); - - - - return $table; - - -} + my ($intfc_gen,$info)=@_; + #my $file= $intfc_gen->intfc_get_interface_file(); + my $table = def_table(1,10,FALSE); + my @modules= $intfc_gen->intfc_get_module_list(); + my $combo=gen_combobox_object($intfc_gen,'module_name',undef,join(',', @modules),undef,'refresh',1); + my $modul_name=gen_label_info(" Select module:",$combo); + my $port= def_image_button("icons/import.png","Import Ports"); + my $category_entry=gen_entry_object($intfc_gen,'category',undef,undef,undef,undef); + my $category=gen_label_info(" Select Category:",$category_entry,'Define the Interface category:e.g RAM, wishbone,...'); + my $row=0; + #$table->attach_defaults ($label, 0, 1 , $row, $row+1); + $table->attach ($modul_name, 0, 3 , $row,$row+1,'shrink','shrink',2,2); + $table->attach ($port, 4, 6 , $row, $row+1,'shrink','shrink',2,2); + $table->attach_defaults ($category, 7, 10 , $row, $row+1); + $port->signal_connect("clicked"=> sub{ + get_interface_ports($intfc_gen,$info); + }); + return $table; +} sub interface_type_select { - my ($intfc_gen,$info,$table,$row)=@_; - - my $entry=gen_entry_object($intfc_gen,'name',undef,undef,"refresh",50); - my $entrybox=gen_label_info(" Interface name:",$entry); - - my $combo=gen_combobox_object($intfc_gen,'connection_num',undef,"single connection,multi connection","single connection",'refresh',1); - my $combo_box=gen_label_info(" Select socket type:",$combo,'Define the socket as multi connection if only if all interfaces ports are output oprts and they can feed more than one plug interface. E.g. clk is defined as multi connection'); - - $table->attach ($entrybox, 0, 2 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($combo_box, 3, 6 , $row, $row+1,'expand','shrink',2,2); - -} - - - - - + my ($intfc_gen,$info,$table,$row)=@_; + my $entry=gen_entry_object($intfc_gen,'name',undef,undef,"refresh",50); + my $entrybox=gen_label_info(" Interface name:",$entry); + my $combo=gen_combobox_object($intfc_gen,'connection_num',undef,"single connection,multi connection","single connection",'refresh',1); + my $combo_box=gen_label_info(" Select socket type:",$combo,'Define the socket as multi connection if only if all interfaces ports are output oprts and they can feed more than one plug interface. E.g. clk is defined as multi connection'); + $table->attach ($entrybox, 0, 2 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($combo_box, 3, 6 , $row, $row+1,'expand','shrink',2,2); +} sub port_select{ - my ($intfc_gen,$info,$table,$row)=@_; - my(%types,%ranges,%names,%connect_types,%connect_ranges,%connect_names,%outport_types,%default_outs); - $intfc_gen->intfc_get_ports(\%types,\%ranges,\%names,\%connect_types,\%connect_ranges,\%connect_names,\%outport_types,\%default_outs); - - my $size = keys %types; - if($size >0){ - - add_Hsep_to_table($table, 0, 10 , $row); $row++; - - my $swap= def_image_button("icons/swap.png","swap"); - - $swap->signal_connect('clicked'=>sub{ - my $type=$intfc_gen->intfc_get_interface_type(); - if($type eq 'plug'){ - $intfc_gen->intfc_set_interface_type('socket'); - } - else { - $intfc_gen->intfc_set_interface_type('plug'); - } - set_gui_status($intfc_gen,"refresh",1); - - }); - - - my @intfcs=("plug","socket"); - my $inttype=$intfc_gen->intfc_get_interface_type(); - if (!defined $inttype){ - $inttype='plug'; - $intfc_gen->intfc_set_interface_type($inttype); - } - - #my $lab1= gen_label_in_center($inttype); - my ($lab1,$lab2); - if ($inttype eq 'plug'){ - $lab1=def_image_label('icons/plug.png' ,'plug '); - $lab2=def_image_label('icons/socket.png','socket'); - }else { - $lab2=def_image_label('icons/plug.png','plug'); - $lab1=def_image_label('icons/socket.png','socket'); - - } - - - - - $table->attach ($lab1, 1, 2 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($swap, 3, 4 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($lab2, 5, 6 , $row, $row+1,'expand','shrink',2,2); $row++; - - - add_Hsep_to_table($table, 0, 9 , $row); $row++; - - - my $lab3= gen_label_in_center("Type"); - my $lab4= gen_label_in_center("Range"); - my $lab5= gen_label_in_center("Name"); - $table->attach ($lab3, 0, 1 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($lab4, 1, 2 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($lab5, 2, 3 , $row, $row+1,'expand','shrink',2,2); - my $lab6= gen_label_in_center("Type"); - my $lab7= gen_label_in_center("Range"); - my $lab8= gen_label_in_center("Name"); - $table->attach ($lab6, 4, 5 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($lab7, 5, 6 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($lab8, 6, 7 , $row, $row+1,'expand','shrink',2,2); - my $lab9= gen_label_help ("When an IP core does not have any of interface output port, the default value will be send to the IP core's input port which is supposed to be connected to that port","Output port Default "); - $table->attach ($lab9, 8, 9 , $row, $row+1,'expand','shrink',2,2); - $row++; - - foreach my $id (sort keys %ranges){ - my $type=$types{$id}; - my $range=$ranges{$id}; - my $name=$names{$id}; - my $connect_type=$connect_types{$id}; - my $connect_range=$connect_ranges{$id}; - my $connect_name=$connect_names{$id}; - my $outport_type=$outport_types{$id}; - my $default_out=$default_outs{$id}; - if(! defined $default_out){ - $default_out = "Active low"; # port_width_repeat($connect_range,"1\'b0"); - $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); - print "\$default_out is set to: $default_out\n "; - } - - #my $box=def_hbox(FALSE,0); - - my @ports_type=("input","output","inout"); - my $pos=get_scolar_pos($type,@ports_type); - my $combo1=gen_combo(\@ports_type,$pos); - my $entry2=gen_entry($range); - my $entry3=gen_entry($name); - - my $connect_type_lable= gen_label_in_center($connect_type); - my $entry4=gen_entry($connect_range); - my $entry5=gen_entry($connect_name); - my @outport_types=("shared","concatenate"); - my $pos2=get_scolar_pos($outport_type,@outport_types); - my $combo2=gen_combo(\@outport_types,$pos2); - - - #my @list=(port_width_repeat($range,"1\'b0"),port_width_repeat($range,"1\'b1"),port_width_repeat($range,"1\'bx")); - my @list=("Active low","Active high","Don't care"); - - my $combentry=gen_combo_entry(\@list); - my $combochiled = combo_entry_get_chiled($combentry); - $pos2=get_scolar_pos($default_out,@list); - if( defined $pos2){ - $combentry->set_active($pos2); - } else { - - $combochiled->set_text($default_out); - } - - - #$box->pack_start($entry3,TRUE,FALSE,3); - #$box->pack_start($separator,TRUE,FALSE,3); - - $table->attach ($combo1, 0, 1 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($entry2, 1, 2 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($entry3, 2, 3 , $row, $row+1,'expand','shrink',2,2); - - - $table->attach ($connect_type_lable, 4, 5 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($entry4, 5, 6 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($entry5, 6, 7 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($combentry, 8, 9 , $row, $row+1,'expand','shrink',2,2); - - $combo1->signal_connect("changed"=>sub{ - my $new_type=$combo1->get_active_text(); - my $new_connect_type=($new_type eq "input")? "output" : ($new_type eq "output")? "input" : $new_type; - $intfc_gen->intfc_add_port($id,$new_type,$range,$name,$new_connect_type,$connect_range,$connect_name,$outport_type,$default_out); - set_gui_status($intfc_gen,"refresh",1); - - }); - $entry2->signal_connect("changed"=>sub{ - $range=$entry2->get_text(); - $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); - set_gui_status($intfc_gen,"refresh",50); - - }); - $entry3->signal_connect("changed"=>sub{ - $name=$entry3->get_text(); - $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); - set_gui_status($intfc_gen,"refresh",50); - - }); - - $entry4->signal_connect("changed"=>sub{ - $connect_range=$entry4->get_text(); - $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); - set_gui_status($intfc_gen,"refresh",50); - - }); - $entry5->signal_connect("changed"=>sub{ - $connect_name=$entry5->get_text(); - $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); - set_gui_status($intfc_gen,"refresh",50); - - }); - $combo2->signal_connect("changed"=>sub{ - my $new_outport_type=$combo2->get_active_text(); - $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$new_outport_type,$default_out); - set_gui_status($intfc_gen,"refresh",1); - - }); - $combochiled->signal_connect('changed' => sub { - my ($entry) = @_; - $default_out=$entry->get_text(); - $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); - - - }); - - - - $row++; - - - }#foreach port - - - } - return $row; + my ($intfc_gen,$info,$table,$row)=@_; + my(%types,%ranges,%names,%connect_types,%connect_ranges,%connect_names,%outport_types,%default_outs); + $intfc_gen->intfc_get_ports(\%types,\%ranges,\%names,\%connect_types,\%connect_ranges,\%connect_names,\%outport_types,\%default_outs); + my $size = keys %types; + if($size >0){ + add_Hsep_to_table($table, 0, 10 , $row); $row++; + my $swap= def_image_button("icons/swap.png","swap"); + $swap->signal_connect('clicked'=>sub{ + my $type=$intfc_gen->intfc_get_interface_type(); + if($type eq 'plug'){ + $intfc_gen->intfc_set_interface_type('socket'); + } + else { + $intfc_gen->intfc_set_interface_type('plug'); + } + set_gui_status($intfc_gen,"refresh",1); + }); + my @intfcs=("plug","socket"); + my $inttype=$intfc_gen->intfc_get_interface_type(); + if (!defined $inttype){ + $inttype='plug'; + $intfc_gen->intfc_set_interface_type($inttype); + } + #my $lab1= gen_label_in_center($inttype); + my ($lab1,$lab2); + if ($inttype eq 'plug'){ + $lab1=def_image_label('icons/plug.png' ,'plug '); + $lab2=def_image_label('icons/socket.png','socket'); + }else { + $lab2=def_image_label('icons/plug.png','plug'); + $lab1=def_image_label('icons/socket.png','socket'); + } + $table->attach ($lab1, 1, 2 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($swap, 3, 4 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($lab2, 5, 6 , $row, $row+1,'expand','shrink',2,2); $row++; + add_Hsep_to_table($table, 0, 9 , $row); $row++; + my $lab3= gen_label_in_center("Type"); + my $lab4= gen_label_in_center("Range"); + my $lab5= gen_label_in_center("Name"); + $table->attach ($lab3, 0, 1 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($lab4, 1, 2 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($lab5, 2, 3 , $row, $row+1,'expand','shrink',2,2); + my $lab6= gen_label_in_center("Type"); + my $lab7= gen_label_in_center("Range"); + my $lab8= gen_label_in_center("Name"); + $table->attach ($lab6, 4, 5 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($lab7, 5, 6 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($lab8, 6, 7 , $row, $row+1,'expand','shrink',2,2); + my $lab9= gen_label_help ("When an IP core does not have any of interface output port, the default value will be send to the IP core's input port which is supposed to be connected to that port","Output port Default "); + $table->attach ($lab9, 8, 9 , $row, $row+1,'expand','shrink',2,2); + $row++; + foreach my $id (sort keys %ranges){ + my $type=$types{$id}; + my $range=$ranges{$id}; + my $name=$names{$id}; + my $connect_type=$connect_types{$id}; + my $connect_range=$connect_ranges{$id}; + my $connect_name=$connect_names{$id}; + my $outport_type=$outport_types{$id}; + my $default_out=$default_outs{$id}; + if(! defined $default_out){ + $default_out = "Active low"; # port_width_repeat($connect_range,"1\'b0"); + $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); + print "\$default_out is set to: $default_out\n "; + } + #my $box=def_hbox(FALSE,0); + my @ports_type=("input","output","inout"); + my $pos=get_scolar_pos($type,@ports_type); + my $combo1=gen_combo(\@ports_type,$pos); + my $entry2=gen_entry($range); + my $entry3=gen_entry($name); + my $connect_type_lable= gen_label_in_center($connect_type); + my $entry4=gen_entry($connect_range); + my $entry5=gen_entry($connect_name); + my @outport_types=("shared","concatenate"); + my $pos2=get_scolar_pos($outport_type,@outport_types); + my $combo2=gen_combo(\@outport_types,$pos2); + #my @list=(port_width_repeat($range,"1\'b0"),port_width_repeat($range,"1\'b1"),port_width_repeat($range,"1\'bx")); + my @list=("Active low","Active high","Don't care"); + my $combentry=gen_combo_entry(\@list); + my $combochiled = combo_entry_get_chiled($combentry); + $pos2=get_scolar_pos($default_out,@list); + if( defined $pos2){ + $combentry->set_active($pos2); + } else { + $combochiled->set_text($default_out); + } + #$box->pack_start($entry3,TRUE,FALSE,3); + #$box->pack_start($separator,TRUE,FALSE,3); + $table->attach ($combo1, 0, 1 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($entry2, 1, 2 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($entry3, 2, 3 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($connect_type_lable, 4, 5 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($entry4, 5, 6 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($entry5, 6, 7 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($combentry, 8, 9 , $row, $row+1,'expand','shrink',2,2); + $combo1->signal_connect("changed"=>sub{ + my $new_type=$combo1->get_active_text(); + my $new_connect_type=($new_type eq "input")? "output" : ($new_type eq "output")? "input" : $new_type; + $intfc_gen->intfc_add_port($id,$new_type,$range,$name,$new_connect_type,$connect_range,$connect_name,$outport_type,$default_out); + set_gui_status($intfc_gen,"refresh",1); + }); + $entry2->signal_connect("changed"=>sub{ + $range=$entry2->get_text(); + $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); + set_gui_status($intfc_gen,"refresh",50); + }); + $entry3->signal_connect("changed"=>sub{ + $name=$entry3->get_text(); + $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); + set_gui_status($intfc_gen,"refresh",50); + }); + $entry4->signal_connect("changed"=>sub{ + $connect_range=$entry4->get_text(); + $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); + set_gui_status($intfc_gen,"refresh",50); + }); + $entry5->signal_connect("changed"=>sub{ + $connect_name=$entry5->get_text(); + $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); + set_gui_status($intfc_gen,"refresh",50); + }); + $combo2->signal_connect("changed"=>sub{ + my $new_outport_type=$combo2->get_active_text(); + $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$new_outport_type,$default_out); + set_gui_status($intfc_gen,"refresh",1); + }); + $combochiled->signal_connect('changed' => sub { + my ($entry) = @_; + $default_out=$entry->get_text(); + $intfc_gen->intfc_add_port($id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out); + }); + $row++; + }#foreach port + } + return $row; } - - - - - - - - - - - - sub dev_box_show{ - my($intfc_gen,$info)=@_; - - my $table = def_table(20,10,FALSE); - - - interface_type_select($intfc_gen,$info,$table,0); - my $row=port_select($intfc_gen,$info,$table,1); - for (my $i=$row; $i<20; $i++){ - my $temp=gen_label_in_center(" "); - #$table->attach_defaults ($temp, 0, 1 , $i, $i+1); - } - - - my $scrolled_win = add_widget_to_scrolled_win($table); - - return $scrolled_win; - -} - - - + my($intfc_gen,$info)=@_; + my $table = def_table(20,10,FALSE); + interface_type_select($intfc_gen,$info,$table,0); + my $row=port_select($intfc_gen,$info,$table,1); + for (my $i=$row; $i<20; $i++){ + my $temp=gen_label_in_center(" "); + #$table->attach_defaults ($temp, 0, 1 , $i, $i+1); + } + my $scrolled_win = add_widget_to_scrolled_win($table); + return $scrolled_win; +} sub check_intfc{ - my $intfc_gen=shift; - my $result; - my $message; - - - $result=$intfc_gen->intfc_ckeck_ports_available(); - if(!defined $result){$message="No port connection has been selected for this interface!";} - $result=$intfc_gen->intfc_get_interface_name(); - if(!defined $result){$message="The interface name is empty!";} - $result=$intfc_gen->intfc_get_interface_file(); - if(!defined $result){$message="The Verilog file containing the interface has not been selected!";} - - if(!defined $message){return 1;} - else {message_dialog($message); return 0;} - - -} - - + my $intfc_gen=shift; + my $result; + my $message; + $result=$intfc_gen->intfc_ckeck_ports_available(); + if(!defined $result){$message="No port connection has been selected for this interface!";} + $result=$intfc_gen->intfc_get_interface_name(); + if(!defined $result){$message="The interface name is empty!";} + $result=$intfc_gen->intfc_get_interface_file(); + if(!defined $result){$message="The Verilog file containing the interface has not been selected!";} + if(!defined $message){return 1;} + else {message_dialog($message); return 0;} +} sub generate_lib{ - my $intfc_gen=shift; - my $name=$intfc_gen->intfc_get_interface_name(); - my $category=$intfc_gen->object_get_attribute('category'); - # Write - if(defined ($category)){ - open(FILE, ">lib/interface/$name.ITC") || die "Can not open: $!"; - print FILE perl_file_header("$name.ITC"); - print FILE Data::Dumper->Dump([\%$intfc_gen],["HashRef"]); - close(FILE) || die "Error closing file: $!"; - #store \%$intfc_gen, "lib/$name.ITC"; - - my $message="Interface $name has been generated successfully. In order to see this interface in IP generator you need to reset the ProNoC. Do you want to reset the ProNoC now?" ; - - my $response = yes_no_dialog($message); - if ($response eq 'yes') { - exec($^X, $0, @ARGV);# reset ProNoC to apply changes - } - - - - }else{ - my $message="Category must be defined!"; - message_dialog($message); - - } - - -return 1; -} - - + my $intfc_gen=shift; + my $name=$intfc_gen->intfc_get_interface_name(); + my $category=$intfc_gen->object_get_attribute('category'); + # Write + if(defined ($category)){ + open(FILE, ">lib/interface/$name.ITC") || die "Can not open: $!"; + print FILE perl_file_header("$name.ITC"); + print FILE Data::Dumper->Dump([\%$intfc_gen],["HashRef"]); + close(FILE) || die "Error closing file: $!"; + #store \%$intfc_gen, "lib/$name.ITC"; + my $message="Interface $name has been generated successfully. In order to see this interface in IP generator you need to reset the ProNoC. Do you want to reset the ProNoC now?" ; + my $response = yes_no_dialog($message); + if ($response eq 'yes') { + exec($^X, $0, @ARGV);# reset ProNoC to apply changes + } + }else{ + my $message="Category must be defined!"; + message_dialog($message); + } +return 1; +} ########### -# get description +# get description ######### - sub get_intfc_description{ - my ($intfc_gen,$info)=@_; - my $description = $intfc_gen->intfc_get_description(); - my $table = def_table(15,15,TRUE); - my $window=def_popwin_size(50,50,"Add description",'percent'); - my ($scrwin,$text_view)=create_txview(); - #my $buffer = $textbox->get_buffer(); - my $ok=def_image_button("icons/select.png",' Ok '); - - $table->attach_defaults($scrwin,0,15,0,14); - $table->attach_defaults($ok,6,9,14,15); - my $text_buffer = $text_view->get_buffer; - if(defined $description) {$text_buffer->set_text($description)}; - - $ok->signal_connect("clicked"=> sub { - $window->destroy; - - my $text = $text_buffer->get_text($text_buffer->get_bounds, TRUE); - $intfc_gen->intfc_set_description($text); - #print "$text\n"; - - }); - - $window->add($table); - $window->show_all(); - -} - - + my ($intfc_gen,$info)=@_; + my $description = $intfc_gen->intfc_get_description(); + my $table = def_table(15,15,TRUE); + my $window=def_popwin_size(50,50,"Add description",'percent'); + my ($scrwin,$text_view)=create_txview(); + #my $buffer = $textbox->get_buffer(); + my $ok=def_image_button("icons/select.png",' Ok '); + $table->attach_defaults($scrwin,0,15,0,14); + $table->attach_defaults($ok,6,9,14,15); + my $text_buffer = $text_view->get_buffer; + if(defined $description) {$text_buffer->set_text($description)}; + $ok->signal_connect("clicked"=> sub { + $window->destroy; + my $text = $text_buffer->get_text($text_buffer->get_bounds, TRUE); + $intfc_gen->intfc_set_description($text); + #print "$text\n"; + }); + $window->add($table); + $window->show_all(); +} sub load_interface{ - my ($intfc_gen)=@_; - my $file; - my $dialog = gen_file_dialog (undef, 'ITC'); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/interface") ; - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.ITC'){ - $intfc_gen->intfc_set_interface_file($file); - set_gui_status($intfc_gen,"load_file",0); - } - } - $dialog->destroy; + my ($intfc_gen)=@_; + my $file; + my $dialog = gen_file_dialog (undef, 'ITC'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/lib/interface") ; + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.ITC'){ + $intfc_gen->intfc_set_interface_file($file); + set_gui_status($intfc_gen,"load_file",0); + } + } + $dialog->destroy; } - - ############ # main ############ sub intfc_main{ - - my $intfc_gen= intfc_gen->interface_generator(); - set_gui_status($intfc_gen,"ideal",0); - my $main_table =def_table(15, 12, FALSE); - - $main_table->set_row_spacings (4); - $main_table->set_col_spacings (1); - # The box which holds the info, warning, error ... mesages - my ($infobox,$info)= create_txview(); - - - my $generate = def_image_button('icons/gen.png','Generate'); - - - - my $fbox=file_box($intfc_gen,$info); - my $sbox=module_select($intfc_gen,$info); - - - my $devbox=dev_box_show($intfc_gen,$info); - - #$main_table->attach_defaults ($fbox , 0, 12, 0,1); - #$main_table->attach_defaults ($sbox , 0, 12, 1,2); - #$main_table->attach_defaults ($devbox , 0, 12, 2,12); - #$main_table->attach_defaults ($infobox , 0, 12, 12,14); + my $intfc_gen= intfc_gen->interface_generator(); + set_gui_status($intfc_gen,"ideal",0); + my $main_table =def_table(15, 12, FALSE); + $main_table->set_row_spacings (4); + $main_table->set_col_spacings (1); + # The box which holds the info, warning, error ... mesages + my ($infobox,$info)= create_txview(); + my $generate = def_image_button('icons/gen.png','Generate'); + my $fbox=file_box($intfc_gen,$info); + my $sbox=module_select($intfc_gen,$info); + my $devbox=dev_box_show($intfc_gen,$info); + #$main_table->attach_defaults ($fbox , 0, 12, 0,1); + #$main_table->attach_defaults ($sbox , 0, 12, 1,2); + #$main_table->attach_defaults ($devbox , 0, 12, 2,12); + #$main_table->attach_defaults ($infobox , 0, 12, 12,14); my $table=def_table(2,11,FALSE); $table->attach($fbox,0,11,0,1,'fill','shrink',2,2); - $table->attach($sbox,0,11,1,2,'fill','shrink',2,2); - - #my $v1=def_pack_vbox(TRUE,0,$fbox,$sbox); - my $v2=gen_vpaned($table,.12,$devbox); - my $v3=gen_vpaned($v2,.6,$infobox); - $main_table->attach_defaults ($v3 , 0, 12, 0,14); - - - $main_table->attach ($generate , 6, 8, 14,15,'shrink','shrink',2,2); - - - my $open = def_image_button('icons/browse.png','Load Interface'); - my $openbox=def_hbox(TRUE,0); - $openbox->pack_start($open, FALSE, FALSE,0); - $main_table->attach ($openbox,0, 2, 14,15,'shrink','shrink',2,2); - - - - - - - #check soc status every 0.5 second. referesh gui if there is any changes -Glib::Timeout->add (100, sub{ - - my ($state,$timeout)= get_gui_status($intfc_gen); - if ($timeout>0){ - $timeout--; - set_gui_status($intfc_gen,$state,$timeout); - } - elsif($state eq "load_file"){ - my $file=$intfc_gen->intfc_get_interface_file(); - my ($pp,$r,$err) = regen_object($file); - if ($r){ - add_info($info,"**Error reading $file file: $err\n"); - return; - } - clone_obj($intfc_gen,$pp); - show_info($info,"$file is loaded!\n "); - set_gui_status($intfc_gen,"ref",1); - - - } - elsif( $state ne "ideal" ){ - $devbox->destroy(); - $fbox->destroy(); - $sbox->destroy(); - - select(undef, undef, undef, 0.1); #wait 10 ms - $devbox=dev_box_show($intfc_gen,$info); - $fbox=file_box($intfc_gen,$info); - $sbox=module_select($intfc_gen,$info); - $table->attach($fbox,0,11,0,1,'fill','shrink',2,2); - $table->attach($sbox,0,11,1,2,'fill','shrink',2,2); - - $v2->pack2($devbox,TRUE, TRUE); - $v3-> pack1($v2, TRUE, TRUE); - #$main_table->attach_defaults ($v3 , 0, 12, 0,14); - $v3->show_all(); - set_gui_status($intfc_gen,"ideal",0); - - } - return TRUE; - - } ); - - $open-> signal_connect("clicked" => sub{ - load_interface($intfc_gen); - - }); - - $generate-> signal_connect("clicked" => sub{ - if( check_intfc($intfc_gen)) { - generate_lib($intfc_gen); - - } - set_gui_status($intfc_gen,"ref",1); - - -}); - - #show_selected_dev($info,\@active_dev,\$dev_list_refresh,\$dev_table); - - - -#$box->show; - #$window->add ($main_table); - #$window->show_all; - #return $main_table; - - - return add_widget_to_scrolled_win($main_table); - + $table->attach($sbox,0,11,1,2,'fill','shrink',2,2); + #my $v1=def_pack_vbox(TRUE,0,$fbox,$sbox); + my $v2=gen_vpaned($table,.12,$devbox); + my $v3=gen_vpaned($v2,.6,$infobox); + $main_table->attach_defaults ($v3 , 0, 12, 0,14); + $main_table->attach ($generate , 6, 8, 14,15,'shrink','shrink',2,2); + my $open = def_image_button('icons/browse.png','Load Interface'); + my $openbox=def_hbox(TRUE,0); + $openbox->pack_start($open, FALSE, FALSE,0); + $main_table->attach ($openbox,0, 2, 14,15,'shrink','shrink',2,2); + #check soc status every 0.5 second. referesh gui if there is any changes + Glib::Timeout->add (100, sub{ + my ($state,$timeout)= get_gui_status($intfc_gen); + if ($timeout>0){ + $timeout--; + set_gui_status($intfc_gen,$state,$timeout); + } + elsif($state eq "load_file"){ + my $file=$intfc_gen->intfc_get_interface_file(); + my ($pp,$r,$err) = regen_object($file); + if ($r){ + add_info($info,"**Error reading $file file: $err\n"); + return; + } + clone_obj($intfc_gen,$pp); + show_info($info,"$file is loaded!\n "); + set_gui_status($intfc_gen,"ref",1); + } + elsif( $state ne "ideal" ){ + $devbox->destroy(); + $fbox->destroy(); + $sbox->destroy(); + select(undef, undef, undef, 0.1); #wait 10 ms + $devbox=dev_box_show($intfc_gen,$info); + $fbox=file_box($intfc_gen,$info); + $sbox=module_select($intfc_gen,$info); + $table->attach($fbox,0,11,0,1,'fill','shrink',2,2); + $table->attach($sbox,0,11,1,2,'fill','shrink',2,2); + $v2->pack2($devbox,TRUE, TRUE); + $v3-> pack1($v2, TRUE, TRUE); + #$main_table->attach_defaults ($v3 , 0, 12, 0,14); + $v3->show_all(); + set_gui_status($intfc_gen,"ideal",0); + } + return TRUE; + } ); + $open-> signal_connect("clicked" => sub{ + load_interface($intfc_gen); + }); + $generate-> signal_connect("clicked" => sub{ + if( check_intfc($intfc_gen)) { + generate_lib($intfc_gen); + } + set_gui_status($intfc_gen,"ref",1); + }); + #show_selected_dev($info,\@active_dev,\$dev_list_refresh,\$dev_table); + #$box->show; + #$window->add ($main_table); + #$window->show_all; + #return $main_table; + return add_widget_to_scrolled_win($main_table); } - - - - - -1 - +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/intfc_gen.pm b/mpsoc/perl_gui/lib/perl/intfc_gen.pm index 01a1d77..a1a29f7 100755 --- a/mpsoc/perl_gui/lib/perl/intfc_gen.pm +++ b/mpsoc/perl_gui/lib/perl/intfc_gen.pm @@ -2,68 +2,58 @@ ############################################################################### # # File: interface.pm -# +# # ############################################################################### use warnings; use strict; - - - package intfc_gen; sub uniq { - my %seen; - return grep { !$seen{$_}++ } @_; + my %seen; + return grep { !$seen{$_}++ } @_; } - sub interface_generator { my $class = "intfc_gen"; my $self; $self->{file_name}=(); $self->{modules}={}; $self->{module_name}=(); - $self->{type}=(); + $self->{type}=(); $self->{name}=(); bless($self,$class); return $self; -} +} sub intfc_set_interface_file { my ($self,$file)= @_; - if (defined $file){ + if (defined $file){ #print "file name has been changed to $file\n"; $self->{file_name}=$file; #delete old data if(exists ($self->{modules})) {delete $self->{modules}; } ; if(exists ($self->{module_name})) {delete $self->{module_name}; } ; if(exists ($self->{ports})){ delete $self->{ports}}; - - - } -} +} sub intfc_get_interface_file { my ($self)=@_; my $file; if (exists ($self->{file_name})){ - $file=$self->{file_name}; + $file=$self->{file_name}; } - return $file; -} + return $file; +} sub intfc_add_module_list{ my ($self,@list)=@_; $self->{modules}={}; - foreach my $p(@list) { - $self->{modules}{$p}={}; - + foreach my $p(@list) { + $self->{modules}{$p}={}; } - -} - +} sub intfc_get_module_list{ my ($self)=@_; @@ -71,43 +61,40 @@ sub intfc_get_module_list{ if(exists($self->{modules})){ @modules=keys %{$self->{modules}}; } - return @modules; -} + return @modules; +} sub intfc_set_module_name{ - my ($self,$module)= @_; + my ($self,$module)= @_; $self->{module_name}=$module; - if(exists ($self->{ports})){ delete $self->{ports}}; -} + if(exists ($self->{ports})){ delete $self->{ports}}; +} sub intfc_remove_ports{ my $self=shift; if(exists ($self->{ports})){ delete $self->{ports}}; } - - sub intfc_get_module_name { my ($self)=@_; my $module; if (exists ($self->{module_name})){ - $module=$self->{module_name}; + $module=$self->{module_name}; } - return $module; -} - + return $module; +} sub intfc_add_port{ my ($self,$port_id,$type,$range,$name,$connect_type,$connect_range,$connect_name,$outport_type,$default_out)=@_; $self->{ports}{$port_id}{name}=$name; $self->{ports}{$port_id}{range}=$range; $self->{ports}{$port_id}{type}=$type; - $self->{ports}{$port_id}{connect_name}=$connect_name; + $self->{ports}{$port_id}{connect_name}=$connect_name; $self->{ports}{$port_id}{connect_range}=$connect_range; - $self->{ports}{$port_id}{connect_type}=$connect_type; + $self->{ports}{$port_id}{connect_type}=$connect_type; $self->{ports}{$port_id}{outport_type}=$outport_type; - $self->{ports}{$port_id}{default_out}=$default_out; -} + $self->{ports}{$port_id}{default_out}=$default_out; +} sub intfc_get_ports{ my ($self,$types_ref,$ranges_ref,$names_ref,$connect_types_ref,$connect_ranges_ref,$connect_name_ref,$outport_type_ref,$default_out_ref)=@_; @@ -130,16 +117,14 @@ sub intfc_ckeck_ports_available{ my $result; if(exists ($self->{ports})){$result=1;} return $result; - -} +} sub intfc_remove_port{ my ($self,$port_id)=@_; if(exists ($self->{ports}{$port_id})){ delete $self->{ports}{$port_id}; - } -} - + } +} sub intfc_get_ports_type{ my ($self)=@_; @@ -147,18 +132,15 @@ sub intfc_get_ports_type{ if(exists ($self->{ports})){ foreach my $p (sort keys %{$self->{ports}}){ $ports_type{$p}= $self->{ports}{$p}{type}; - } } return %ports_type; -} - - +} sub intfc_set_interface_name{ my ($self,$name)=@_; $self->{name}=$name; -} +} sub intfc_get_interface_name { my ($self)=@_; @@ -169,15 +151,11 @@ sub intfc_get_interface_name { return $name; } - - - sub intfc_set_interface_type { my ($self,$intfc_type)=@_; $self->{type}=$intfc_type; } - sub intfc_get_interface_type { my ($self)=@_; my $type; @@ -187,13 +165,11 @@ sub intfc_get_interface_type { return $type; } - sub intfc_set_connection_num { my ($self,$connection_num)=@_; $self->{connection_num}=$connection_num; } - sub intfc_get_connection_num { my ($self)=@_; my $connection_num; @@ -203,42 +179,30 @@ sub intfc_get_connection_num { return $connection_num; } - - - - sub intfc_set_description{ my ($self,$description)=@_; - $self->{description}=$description; + $self->{description}=$description; } - - sub intfc_get_description{ -my ($self)=@_; + my ($self)=@_; my $des; if(exists ($self->{description})){ $des=$self->{description}; } return $des; -} - - - +} sub object_add_attribute{ my ($self,$attribute1,$attribute2,$value)=@_; if(!defined $attribute2){$self->{$attribute1}=$value;} else {$self->{$attribute1}{$attribute2}=$value;} - } sub object_get_attribute{ my ($self,$attribute1,$attribute2)=@_; if(!defined $attribute2) {return $self->{$attribute1};} return $self->{$attribute1}{$attribute2}; - - } sub object_add_attribute_order{ @@ -247,7 +211,7 @@ sub object_add_attribute_order{ my @a; @a = @{$r} if(defined $r); push (@a,@param); - @a=uniq(@a); + @a=uniq(@a); $self->{'parameters_order'}{$attribute} =\@a; } @@ -255,9 +219,4 @@ sub object_get_attribute_order{ my ($self,$attribute)=@_; return @{$self->{parameters_order}{$attribute}}; } - - - - - -1 +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/ip.pm b/mpsoc/perl_gui/lib/perl/ip.pm index 614ec81..8043633 100755 --- a/mpsoc/perl_gui/lib/perl/ip.pm +++ b/mpsoc/perl_gui/lib/perl/ip.pm @@ -2,7 +2,7 @@ ############################################################################### # # File: ip.pm -# +# # ############################################################################### use warnings; @@ -11,484 +11,374 @@ use FindBin; use lib $FindBin::Bin; use ip_gen; use Cwd; - - package ip; - sub lib_new { - my $class = ("ARRAY" eq ref $_[0]) ? "ip" : shift; my $self; $self = {}; - my $dir = Cwd::getcwd(); - $dir =~ s/ /\\ /g; - my @files = glob "$dir/lib/ip/*/*.IP"; - for my $p (@files){ - - # Read - my $ipgen; - $ipgen = eval { do $p }; - # Might need "no strict;" before and "use strict;" after "do" - if ($@ || !defined $ipgen){ - print "\n**Warning: skipping $p file due to error in reading: $@\n"; - next; - } - add_ip($self,$ipgen); - - } - - + my $dir = Cwd::getcwd(); + $dir =~ s/ /\\ /g; + my @files = glob "$dir/lib/ip/*/*.IP"; + for my $p (@files){ + # Read + my $ipgen; + $ipgen = eval { do $p }; + # Might need "no strict;" before and "use strict;" after "do" + if ($@ || !defined $ipgen){ + print "\n**Warning: skipping $p file due to error in reading: $@\n"; + next; + } + add_ip($self,$ipgen); + } bless($self,$class); - - return $self; -} - +} sub ip_add_parameter { - my ($self,$category,$module,$parameter,$default,$type,$content,$info,$glob_param,$redefine_param)=@_; - if (!defined($category) ) {return 0;} - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - $self->{categories}{$category}{names}{$module}{parameters}{$parameter}={}; - $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{"default"}=$default; - $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{type}=$type; - $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{content}=$content; - $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{info}=$info; - $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{glob_param}=$glob_param; - $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{redefine_param}=$redefine_param; - } + my ($self,$category,$module,$parameter,$default,$type,$content,$info,$glob_param,$redefine_param)=@_; + if (!defined($category) ) {return 0;} + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + $self->{categories}{$category}{names}{$module}{parameters}{$parameter}={}; + $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{"default"}=$default; + $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{type}=$type; + $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{content}=$content; + $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{info}=$info; + $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{glob_param}=$glob_param; + $self->{categories}{$category}{names}{$module}{parameters}{$parameter}{redefine_param}=$redefine_param; + } } - sub ip_remove_parameter { - my ($self,$category,$module,$parameter)=@_; - if (!defined($category) ) {return 0;} - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - delete $self->{categories}{$category}{names}{$module}{parameters}{$parameter}; - - }else{ return 0;} - return 1; + my ($self,$category,$module,$parameter)=@_; + if (!defined($category) ) {return 0;} + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + delete $self->{categories}{$category}{names}{$module}{parameters}{$parameter}; + }else{ return 0;} + return 1; } - - sub ip_get_parameter { - my ($self,$category,$module,$parameter)=@_; - my ($default,$type,$content,$info,$glob_param,$redefine_param); - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - $default =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{"default"}; - $type =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{type}; - $content =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{content}; - $info =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{info}; - $glob_param =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{glob_param}; - $redefine_param =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{redefine_param}; - } - return ($default,$type,$content,$info,$glob_param,$redefine_param); + my ($self,$category,$module,$parameter)=@_; + my ($default,$type,$content,$info,$glob_param,$redefine_param); + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + $default =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{"default"}; + $type =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{type}; + $content =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{content}; + $info =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{info}; + $glob_param =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{glob_param}; + $redefine_param =$self->{categories}{$category}{names}{$module}{parameters}{$parameter}{redefine_param}; + } + return ($default,$type,$content,$info,$glob_param,$redefine_param); } - sub ip_add_socket { - my ($self,$category,$module,$interface,$type,$value,$connection_num)=@_; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - $self->{categories}{$category}{names}{$module}{sockets}{$interface}{type}=$type; - $self->{categories}{$category}{names}{$module}{sockets}{$interface}{value}=$value; - if(defined $connection_num){$self->{categories}{$category}{names}{$module}{sockets}{$interface}{connection_num}=$connection_num;} - - - } + my ($self,$category,$module,$interface,$type,$value,$connection_num)=@_; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + $self->{categories}{$category}{names}{$module}{sockets}{$interface}{type}=$type; + $self->{categories}{$category}{names}{$module}{sockets}{$interface}{value}=$value; + if(defined $connection_num){$self->{categories}{$category}{names}{$module}{sockets}{$interface}{connection_num}=$connection_num;} + } } - sub ip_get_socket { - my ($self,$category,$module,$socket)=@_; - my ($type,$value,$connection_num); - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - $type =$self->{categories}{$category}{names}{$module}{sockets}{$socket}{type}; - $value =$self->{categories}{$category}{names}{$module}{sockets}{$socket}{value}; - $connection_num =$self->{categories}{$category}{names}{$module}{sockets}{$socket}{connection_num}; - } - return ($type,$value,$connection_num); + my ($self,$category,$module,$socket)=@_; + my ($type,$value,$connection_num); + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + $type =$self->{categories}{$category}{names}{$module}{sockets}{$socket}{type}; + $value =$self->{categories}{$category}{names}{$module}{sockets}{$socket}{value}; + $connection_num =$self->{categories}{$category}{names}{$module}{sockets}{$socket}{connection_num}; + } + return ($type,$value,$connection_num); } sub ip_get_module_sockets_list { - my ($self,$category,$module)=@_; - my @r; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{sockets}}){ - push (@r,$p); - } - } - return @r; -} - - + my ($self,$category,$module)=@_; + my @r; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{sockets}}){ + push (@r,$p); + } + } + return @r; +} sub ip_add_plug { - my ($self,$category,$module,$interface,$type,$value,$connection_num)=@_; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - $self->{categories}{$category}{names}{$module}{plugs}{$interface}{type}=$type; - $self->{categories}{$category}{names}{$module}{plugs}{$interface}{value}=$value; - if(defined $connection_num){ $self->{categories}{$category}{names}{$module}{plugs}{$interface}{connection_num}=$connection_num;} - - } + my ($self,$category,$module,$interface,$type,$value,$connection_num)=@_; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + $self->{categories}{$category}{names}{$module}{plugs}{$interface}{type}=$type; + $self->{categories}{$category}{names}{$module}{plugs}{$interface}{value}=$value; + if(defined $connection_num){ $self->{categories}{$category}{names}{$module}{plugs}{$interface}{connection_num}=$connection_num;} + } } sub ip_get_plug { - my ($self,$category,$module,$plug)=@_; - my ($type,$value,$connection_num); - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - $type =$self->{categories}{$category}{names}{$module}{plugs}{$plug}{type}; - $value =$self->{categories}{$category}{names}{$module}{plugs}{$plug}{value}; - $connection_num =$self->{categories}{$category}{names}{$module}{plugs}{$plug}{connection_num}; - } - return ($type,$value,$connection_num); + my ($self,$category,$module,$plug)=@_; + my ($type,$value,$connection_num); + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + $type =$self->{categories}{$category}{names}{$module}{plugs}{$plug}{type}; + $value =$self->{categories}{$category}{names}{$module}{plugs}{$plug}{value}; + $connection_num =$self->{categories}{$category}{names}{$module}{plugs}{$plug}{connection_num}; + } + return ($type,$value,$connection_num); } sub ip_get_module_plugs_list { - my ($self,$category,$module)=@_; - my @r; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{plugs}}){ - push (@r,$p); - } - } - return @r; -} - - - - + my ($self,$category,$module)=@_; + my @r; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{plugs}}){ + push (@r,$p); + } + } + return @r; +} sub ip_add_port{ - my ($self,$category,$module,$port,$type,$range,$intfc_name,$intfc_port)=@_; - if (!defined($category) ) {return 0;} - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - $self->{categories}{$category}{names}{$module}{ports}{$port}={}; - $self->{categories}{$category}{names}{$module}{ports}{$port}{type}=$type; - $self->{categories}{$category}{names}{$module}{ports}{$port}{range}=$range; - $self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_name}=$intfc_name; - $self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_port}=$intfc_port; - } + my ($self,$category,$module,$port,$type,$range,$intfc_name,$intfc_port)=@_; + if (!defined($category) ) {return 0;} + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + $self->{categories}{$category}{names}{$module}{ports}{$port}={}; + $self->{categories}{$category}{names}{$module}{ports}{$port}{type}=$type; + $self->{categories}{$category}{names}{$module}{ports}{$port}{range}=$range; + $self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_name}=$intfc_name; + $self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_port}=$intfc_port; + } } - sub ip_get_port{ - my ($self,$category,$module,$port)=@_; - my ($type,$range,$intfc_name,$intfc_port); - if ( exists ($self->{categories}{$category}{names}{$module}{ports}{$port}) ){ - $type =$self->{categories}{$category}{names}{$module}{ports}{$port}{type}; - $range =$self->{categories}{$category}{names}{$module}{ports}{$port}{range}; - $intfc_name =$self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_name}; - $intfc_port =$self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_port}; - } - return ($type,$range,$intfc_name,$intfc_port); + my ($self,$category,$module,$port)=@_; + my ($type,$range,$intfc_name,$intfc_port); + if ( exists ($self->{categories}{$category}{names}{$module}{ports}{$port}) ){ + $type =$self->{categories}{$category}{names}{$module}{ports}{$port}{type}; + $range =$self->{categories}{$category}{names}{$module}{ports}{$port}{range}; + $intfc_name =$self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_name}; + $intfc_port =$self->{categories}{$category}{names}{$module}{ports}{$port}{intfc_port}; + } + return ($type,$range,$intfc_name,$intfc_port); } sub ip_list_ports{ - my ($self,$category,$module)=@_; - my @ports; - - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - - foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{ports}}){ - push (@ports,$p); - } - } - return @ports; + my ($self,$category,$module)=@_; + my @ports; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{ports}}){ + push (@ports,$p); + } + } + return @ports; } - - sub ip_get_categories{ - my $self=shift; - my @r; - if (exists ($self->{categories})){ - foreach my $p (sort keys %{$self->{categories}}){ - push (@r,$p); - } - } - return @r; + my $self=shift; + my @r; + if (exists ($self->{categories})){ + foreach my $p (sort keys %{$self->{categories}}){ + push (@r,$p); + } + } + return @r; } - sub get_modules{ - my ($self,$category)=@_; - my @r; - if (exists ($self->{categories}{$category})){ - foreach my $p (sort keys %{$self->{categories}{$category}{names}}){ - push (@r,$p); - } - } - return @r; + my ($self,$category)=@_; + my @r; + if (exists ($self->{categories}{$category})){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}}){ + push (@r,$p); + } + } + return @r; } - sub get_param_default{ - my ($self,$category,$module)=@_; - my %r; - if (!defined($module) ) {return %r;} - foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{parameters}}){ - $r{$p}=$self->{categories}{$category}{names}{$module}{parameters}{$p}{"default"}; - #print "$p=$r{$p}\n"; - } - return %r; - + my ($self,$category,$module)=@_; + my %r; + if (!defined($module) ) {return %r;} + foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{parameters}}){ + $r{$p}=$self->{categories}{$category}{names}{$module}{parameters}{$p}{"default"}; + #print "$p=$r{$p}\n"; + } + return %r; } - - sub ip_add_socket_names{ - my($self,$ipgen,$category,$module, $socket)=@_; - my $num=0; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - - my $name= $ipgen->ipgen_get_socket_name($socket,$num); - do{ - $self->{categories}{$category}{names}{$module}{sockets}{$socket}{$num}{name}=$name; - ++$num; - $name= $ipgen->ipgen_get_socket_name($socket,$num); - }while(defined $name); - - } -} + my($self,$ipgen,$category,$module, $socket)=@_; + my $num=0; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + my $name= $ipgen->ipgen_get_socket_name($socket,$num); + do{ + $self->{categories}{$category}{names}{$module}{sockets}{$socket}{$num}{name}=$name; + ++$num; + $name= $ipgen->ipgen_get_socket_name($socket,$num); + }while(defined $name); + } +} sub ip_get_socket_name{ - my($self,$category,$module, $socket,$num)=@_; - my $name; - if ( exists ( $self->{categories}{$category}{names}{$module}{sockets}{$socket}{$num}{name}) ){ - $name= $self->{categories}{$category}{names}{$module}{sockets}{$socket}{$num}{name}; - - } - return $name; -} - - + my($self,$category,$module, $socket,$num)=@_; + my $name; + if ( exists ( $self->{categories}{$category}{names}{$module}{sockets}{$socket}{$num}{name}) ){ + $name= $self->{categories}{$category}{names}{$module}{sockets}{$socket}{$num}{name}; + } + return $name; +} sub ip_add_plug_names{ - my($self,$ipgen,$category,$module, $plug)=@_; - my $num=0; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - - my $name= $ipgen->ipgen_get_plug_name($plug,$num); - do{ - $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{name}=$name; - my ($addr,$width)= $ipgen->ipgen_get_wb_addr($plug,$num); - if (defined $addr){ - $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{addr}=$addr; - $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{width}=$width; - } - ++$num; - $name= $ipgen->ipgen_get_plug_name($plug,$num); - - - }while(defined $name); - - } + my($self,$ipgen,$category,$module, $plug)=@_; + my $num=0; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + my $name= $ipgen->ipgen_get_plug_name($plug,$num); + do{ + $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{name}=$name; + my ($addr,$width)= $ipgen->ipgen_get_wb_addr($plug,$num); + if (defined $addr){ + $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{addr}=$addr; + $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{width}=$width; + } + ++$num; + $name= $ipgen->ipgen_get_plug_name($plug,$num); + }while(defined $name); + } } sub ip_get_wb_addr{ - my($self,$category,$module,$plug,$num)=@_; - my ($addr , $width); - if(exists($self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{addr})){ - $addr = $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{addr}; - $width = $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{width}; - } - return ($addr , $width); -} - - + my($self,$category,$module,$plug,$num)=@_; + my ($addr , $width); + if(exists($self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{addr})){ + $addr = $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{addr}; + $width = $self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{width}; + } + return ($addr , $width); +} sub ip_get_plug_name{ - my($self,$category,$module, $plug,$num)=@_; - my $name; - if ( exists ($self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{name})){ - $name=$self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{name}; - } - return $name; + my($self,$category,$module, $plug,$num)=@_; + my $name; + if ( exists ($self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{name})){ + $name=$self->{categories}{$category}{names}{$module}{plugs}{$plug}{$num}{name}; + } + return $name; } - - - sub get_module_sokets_value{ - my ($self,$category,$module)=@_; - if (!defined($category) ) {return 0;} - my %r; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{sockets}}){ - $r{$p}=$self->{categories}{$category}{names}{$module}{sockets}{$p}{value}; - } - - } - return %r; -} - + my ($self,$category,$module)=@_; + if (!defined($category) ) {return 0;} + my %r; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{sockets}}){ + $r{$p}=$self->{categories}{$category}{names}{$module}{sockets}{$p}{value}; + } + } + return %r; +} sub get_module_sokets_type{ - my ($self,$category,$module)=@_; - if (!defined($category) ) {return 0;} - my %r; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{sockets}}){ - $r{$p}=$self->{categories}{$category}{names}{$module}{sockets}{$p}{type}; - } - - } - return %r; -} - + my ($self,$category,$module)=@_; + if (!defined($category) ) {return 0;} + my %r; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{sockets}}){ + $r{$p}=$self->{categories}{$category}{names}{$module}{sockets}{$p}{type}; + } + } + return %r; +} sub get_module_plugs_value{ - my ($self,$category,$module)=@_; - if (!defined($category) ) {return 0;} - my %r; - if ( exists ($self->{categories}{$category}{names}{$module}) ){ - foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{plugs}}){ - $r{$p}=$self->{categories}{$category}{names}{$module}{plugs}{$p}{value}; - } - - } - return %r; -} + my ($self,$category,$module)=@_; + if (!defined($category) ) {return 0;} + my %r; + if ( exists ($self->{categories}{$category}{names}{$module}) ){ + foreach my $p (sort keys %{$self->{categories}{$category}{names}{$module}{plugs}}){ + $r{$p}=$self->{categories}{$category}{names}{$module}{plugs}{$p}{value}; + } + } + return %r; +} sub ip_get_param_order{ - my ($self,$category,$module)=@_; - my @r; - if(exists $self->{categories}{$category}{names}{$module}{parameters_order}) { - @r=@{$self->{categories}{$category}{names}{$module}{parameters_order}}; - - } - return @r; + my ($self,$category,$module)=@_; + my @r; + if(exists $self->{categories}{$category}{names}{$module}{parameters_order}) { + @r=@{$self->{categories}{$category}{names}{$module}{parameters_order}}; + } + return @r; } - - - - - - sub ip_add{ - my ($self,$category,$module,$filed_name,$filed_data)=@_; - $self->{categories}{$category}{names}{$module}{$filed_name}=$filed_data; + my ($self,$category,$module,$filed_name,$filed_data)=@_; + $self->{categories}{$category}{names}{$module}{$filed_name}=$filed_data; } - sub ip_get{ - my ($self,$category,$module,$filed_name)=@_; - return $self->{categories}{$category}{names}{$module}{$filed_name}; + my ($self,$category,$module,$filed_name)=@_; + return $self->{categories}{$category}{names}{$module}{$filed_name}; } - sub ip_get_list{ - my ($self,$category,$module,$filed_name)=@_; - my @l; - if( defined $self->{categories}{$category}{names}{$module}{$filed_name}){ - @l=@{$self->{categories}{$category}{names}{$module}{$filed_name}}; - } - return @l; + my ($self,$category,$module,$filed_name)=@_; + my @l; + if( defined $self->{categories}{$category}{names}{$module}{$filed_name}){ + @l=@{$self->{categories}{$category}{names}{$module}{$filed_name}}; + } + return @l; } - sub ip_remove{ - my ($self,$category,$module,$filed_name)=@_; - delete $self->{categories}{$category}{names}{$module}{$filed_name}; + my ($self,$category,$module,$filed_name)=@_; + delete $self->{categories}{$category}{names}{$module}{$filed_name}; } - - - sub add_ip{ - - my ($self,$ipgen) =@_; - my $module; - $module = $ipgen->ipgen_get("ip_name"); - my $module_name =$ipgen->ipgen_get("module_name"); - if(!defined $module){ $module = $module_name} - my $category= $ipgen->ipgen_get("category"); - - - $self->{categories}{$category}{names}{$module}={}; - - $self->{categories}{$category}{names}{$module}{module_name}=$module_name; - my @plugs= $ipgen->ipgen_list_plugs(); - #print "$module:@plugs\n"; - foreach my $plug (@plugs){ - my ($type,$value,$connection_num)= $ipgen->ipgen_get_plug($plug); - ip_add_plug($self,$category,$module,$plug,$type,$value,$connection_num); - ip_add_plug_names($self,$ipgen,$category,$module, $plug); - - } - my @sockets= $ipgen->ipgen_list_sokets(); - #print "$module:@sockets\n"; - foreach my $socket (@sockets){ - my ($type,$value,$connection_num)= $ipgen->ipgen_get_socket($socket); - ip_add_socket($self,$category,$module, $socket,$type,$value,$connection_num); - ip_add_socket_names($self,$ipgen,$category,$module, $socket); - } - my @parameters= $ipgen->ipgen_get_all_parameters_list(); - foreach my $param (@parameters){ - my ($default,$type,$content,$info,$glob_param,$redefine_param)=$ipgen->ipgen_get_parameter_detail($param); - ip_add_parameter($self,$category,$module,$param,$default,$type,$content,$info,$glob_param,$redefine_param); - - } - - my @ports= $ipgen->ipgen_list_ports(); - foreach my $port (@ports){ - my($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($port); - ip_add_port($self,$category,$module,$port,$type,$range,$intfc_name,$intfc_port); - } - - my @fileds =("system_c","system_h","hdl_files","hdl_files_ticked","sw_files","gen_sw_files","gen_hw_files","sw_params_list","unused","parameters_order","description","version",'description_pdf'); - foreach my $p (@fileds){ - my $val=$ipgen->ipgen_get($p); - $self->{categories}{$category}{names}{$module}{$p}=$ipgen->ipgen_get($p) if(defined $val ); - } - - - -} - - + my ($self,$ipgen) =@_; + my $module; + $module = $ipgen->ipgen_get("ip_name"); + my $module_name =$ipgen->ipgen_get("module_name"); + if(!defined $module){ $module = $module_name} + my $category= $ipgen->ipgen_get("category"); + $self->{categories}{$category}{names}{$module}={}; + $self->{categories}{$category}{names}{$module}{module_name}=$module_name; + my @plugs= $ipgen->ipgen_list_plugs(); + #print "$module:@plugs\n"; + foreach my $plug (@plugs){ + my ($type,$value,$connection_num)= $ipgen->ipgen_get_plug($plug); + ip_add_plug($self,$category,$module,$plug,$type,$value,$connection_num); + ip_add_plug_names($self,$ipgen,$category,$module, $plug); + } + my @sockets= $ipgen->ipgen_list_sokets(); + #print "$module:@sockets\n"; + foreach my $socket (@sockets){ + my ($type,$value,$connection_num)= $ipgen->ipgen_get_socket($socket); + ip_add_socket($self,$category,$module, $socket,$type,$value,$connection_num); + ip_add_socket_names($self,$ipgen,$category,$module, $socket); + } + my @parameters= $ipgen->ipgen_get_all_parameters_list(); + foreach my $param (@parameters){ + my ($default,$type,$content,$info,$glob_param,$redefine_param)=$ipgen->ipgen_get_parameter_detail($param); + ip_add_parameter($self,$category,$module,$param,$default,$type,$content,$info,$glob_param,$redefine_param); + } + my @ports= $ipgen->ipgen_list_ports(); + foreach my $port (@ports){ + my($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($port); + ip_add_port($self,$category,$module,$port,$type,$range,$intfc_name,$intfc_port); + } + my @fileds =("system_c","system_h","hdl_files","hdl_files_ticked","sw_files","gen_sw_files","gen_hw_files","sw_params_list","unused","parameters_order","description","version",'description_pdf'); + foreach my $p (@fileds){ + my $val=$ipgen->ipgen_get($p); + $self->{categories}{$category}{names}{$module}{$p}=$ipgen->ipgen_get($p) if(defined $val ); + } +} sub object_add_attribute{ - my ($self,$attribute1,$attribute2,$value)=@_; - if(!defined $attribute2){$self->{$attribute1}=$value;} - else {$self->{$attribute1}{$attribute2}=$value;} - + my ($self,$attribute1,$attribute2,$value)=@_; + if(!defined $attribute2){$self->{$attribute1}=$value;} + else {$self->{$attribute1}{$attribute2}=$value;} } sub object_get_attribute{ - my ($self,$attribute1,$attribute2)=@_; - if(!defined $attribute2) {return $self->{$attribute1};} - return $self->{$attribute1}{$attribute2}; - - + my ($self,$attribute1,$attribute2)=@_; + if(!defined $attribute2) {return $self->{$attribute1};} + return $self->{$attribute1}{$attribute2}; } - - - - - - - - - - - - - - - - - - - - - - - - - - -1 +1; diff --git a/mpsoc/perl_gui/lib/perl/ip_gen.pl b/mpsoc/perl_gui/lib/perl/ip_gen.pl index fd36ba0..ce9e72f 100755 --- a/mpsoc/perl_gui/lib/perl/ip_gen.pl +++ b/mpsoc/perl_gui/lib/perl/ip_gen.pl @@ -2,10 +2,8 @@ use constant::boolean; use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - use wb_addr; use interface; use intfc_gen; @@ -13,1934 +11,1355 @@ use ip; use rvp; use Cwd 'abs_path'; - use File::Basename; use File::Path qw/make_path/; - - - - -require "widget.pl"; +require "widget.pl"; require "readme_gen.pl"; - - - ################ # check_input_file ################ - sub check_input_file{ - my ($file,$ipgen,$info)=@_; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.IP'){ - $ipgen->ipgen_add("file_name",$file); - set_gui_status($ipgen,"load_file",0); - - - }else{ - read_all_module ($file,$ipgen,$info); - - } - - -} - + my ($file,$ipgen,$info)=@_; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.IP'){ + $ipgen->ipgen_add("file_name",$file); + set_gui_status($ipgen,"load_file",0); + }else{ + read_all_module ($file,$ipgen,$info); + } +} sub read_all_module{ - my ($file,$ipgen,$info)=@_; - - if (!defined $file) { - add_colored_info($info,"No input file is given. Please set an input Verilog fle first.\n", 'red'); - - return; - } - - my $f=add_project_dir_to_addr($file); - - if (-f $f) { - my $vdb = read_verilog_file($f); - my @modules=sort $vdb->get_modules($f); - #foreach my $p(@module_list) {print "$p\n"} - $ipgen->ipgen_add("file_name",$file); - - - - $ipgen->ipgen_add("module_name",$modules[0]); - $ipgen->ipgen_set_module_list(@modules); - load_default_setting($ipgen,$modules[0]); - - - set_gui_status($ipgen,"file_selected",1); - add_info($info,"$f is loaded\n"); - - } - else { - add_colored_info($info,"File $file does not exist!\n", 'red'); - } -} - - - + my ($file,$ipgen,$info)=@_; + if (!defined $file) { + add_colored_info($info,"No input file is given. Please set an input Verilog fle first.\n", 'red'); + return; + } + my $f=add_project_dir_to_addr($file); + if (-f $f) { + my $vdb = read_verilog_file($f); + my @modules=sort $vdb->get_modules($f); + #foreach my $p(@module_list) {print "$p\n"} + $ipgen->ipgen_add("file_name",$file); + $ipgen->ipgen_add("module_name",$modules[0]); + $ipgen->ipgen_set_module_list(@modules); + load_default_setting($ipgen,$modules[0]); + set_gui_status($ipgen,"file_selected",1); + add_info($info,"$f is loaded\n"); + } + else { + add_colored_info($info,"File $file does not exist!\n", 'red'); + } +} sub save_ports_all{ - my ($ipgen,$vdb,$top_module)=@_; - - foreach my $sig (sort $vdb->get_modules_signals($top_module)) { - my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, - $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = - $vdb->get_module_signal($top_module,$sig); - - if($type eq "input" or $type eq "inout" or $type eq "output" ){ - $ipgen->ipgen_add_port($sig,$range,$type,'IO','IO'); - #print "$sig,$range,$type,'IO','IO'\n"; - - } - - - } - + my ($ipgen,$vdb,$top_module)=@_; + foreach my $sig (sort $vdb->get_modules_signals($top_module)) { + my ($line,$a_line,$i_line,$type,$file,$posedge,$negedge, + $type2,$s_file,$s_line,$range,$a_file,$i_file,$dims) = + $vdb->get_module_signal($top_module,$sig); + if($type eq "input" or $type eq "inout" or $type eq "output" ){ + $ipgen->ipgen_add_port($sig,$range,$type,'IO','IO'); + #print "$sig,$range,$type,'IO','IO'\n"; + } + } } - ############ -# file_info +# file_info ############# - sub ip_file_box { - my ($ipgen,$info,$table,$row)=@_; - my $label = gen_label_in_left(" Select file:"); - my $entry = gen_entry(); - #my $open= def_image_button("icons/select.png","Open"); - my $browse= def_image_button("icons/browse.png","Browse"); - my $file= $ipgen->ipgen_get("file_name"); - if(defined $file){$entry->set_text($file);} + my ($ipgen,$info,$table,$row)=@_; + my $label = gen_label_in_left(" Select file:"); + my $entry = gen_entry(); + #my $open= def_image_button("icons/select.png","Open"); + my $browse= def_image_button("icons/browse.png","Browse"); + my $file= $ipgen->ipgen_get("file_name"); + if(defined $file){$entry->set_text($file);} else {show_info($info,"Please select the verilog file containing the top level IP core\n");} - - - my $entry2=gen_label_info(" IP name:",gen_entry_object($ipgen,'ip_name',undef,undef,undef,undef)); - - - - #show_info($info,"Please select the verilog file containing the ip module\n"); - $browse->signal_connect("clicked"=> sub{ - my $entry_ref=$_[1]; - my $file; - my $dialog = gen_file_dialog (undef, 'v','IP'); - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - $$entry_ref->set_text($file); - check_input_file($file,$ipgen,$info); - } - $dialog->destroy; - } , \$entry); - - $entry->signal_connect("activate"=>sub{ - my $file_name=$entry->get_text(); - check_input_file($file_name,$ipgen,$info); - }); - - $entry->signal_connect("changed"=>sub{ - #my $file_name=$entry->get_text(); - #check_input_file($file_name,$ipgen,$info); - }); - - $table->attach_defaults ($label, 0, 1 , $row, $row+1); - $table->attach_defaults ($entry, 1, 8 , $row, $row+1); - $table->attach ($browse, 8, 9, $row, $row+1,,'expand','shrink',2,2); - $table->attach_defaults ($entry2, 9, 11, $row, $row+1); - - - + my $entry2=gen_label_info(" IP name:",gen_entry_object($ipgen,'ip_name',undef,undef,undef,undef)); + #show_info($info,"Please select the verilog file containing the ip module\n"); + $browse->signal_connect("clicked"=> sub{ + my $entry_ref=$_[1]; + my $file; + my $dialog = gen_file_dialog (undef, 'v','IP'); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + $$entry_ref->set_text($file); + check_input_file($file,$ipgen,$info); + } + $dialog->destroy; + } , \$entry); + $entry->signal_connect("activate"=>sub{ + my $file_name=$entry->get_text(); + check_input_file($file_name,$ipgen,$info); + }); + $entry->signal_connect("changed"=>sub{ + #my $file_name=$entry->get_text(); + #check_input_file($file_name,$ipgen,$info); + }); + $table->attach_defaults ($label, 0, 1 , $row, $row+1); + $table->attach_defaults ($entry, 1, 8 , $row, $row+1); + $table->attach ($browse, 8, 9, $row, $row+1,,'expand','shrink',2,2); + $table->attach_defaults ($entry2, 9, 11, $row, $row+1); } - - - sub select_module{ - my ($ipgen,$info,$table,$row)=@_; - - - my @modules= $ipgen->ipgen_get_module_list(); - my $saved_module=$ipgen->ipgen_get("module_name"); - my $pos=(defined $saved_module ) ? get_scolar_pos( $saved_module,@modules) : 0; - my $combo = gen_combo(\@modules, $pos); - my $top_module=gen_label_info(" Select\n module:",$combo); - - - - - my $param= def_image_button("icons/setting.png","Parameter\n setting"); - my $def= def_image_button("icons/setting.png","Definition\n file setting"); - - - - #Category - my $ip = ip->lib_new (); - my @categories= $ip->ip_get_categories(); - $ip =undef; - my $saved_category=$ipgen->ipgen_get("category"); - if(defined $saved_category ){ push(@categories,$saved_category) if(!( grep /^$saved_category$/, @categories ));} - my $content=join( ',', @categories); - my $combentry=gen_comboentry_object ($ipgen,'category',undef,$content,$saved_category,undef,undef); - my $category=gen_label_info(" Select\n Category:",$combentry,"Select the IP category form the given list or you can add a new category."); - - - - my $ipinfo= def_image_button("icons/add_info.png"," IP\n Description"); - my $header_h= def_image_button("icons/h_file.png","Add Software\n files"); - my $lib_hdl= def_image_button("icons/add-notes.png","Add HDL\n files"); - - - #$table->attach_defaults ($top_module, 0, 1 , $row, $row+1); - $table->attach ($top_module, 0, 4 , $row,$row+1,'fill','shrink',2,2); - $table->attach ($param, 4, 6 , $row, $row+1,'expand','shrink',2,2); - - $table->attach ($category, 6, 8 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($ipinfo, 8, 9 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($header_h, 9, 10 , $row, $row+1,'expand','shrink',2,2); - $table->attach ($lib_hdl, 10, 11 , $row, $row+1,'expand','shrink',2,2); - - - $combo->signal_connect("changed"=> sub{ - - my $module= $combo->get_active_text(); - load_default_setting($ipgen,$module); - set_gui_status($ipgen,'intfc_changed',0); - - - }); - - $param->signal_connect("clicked"=> sub{ - get_parameter_setting($ipgen,$info); - - - }); - - $def->signal_connect("clicked"=> sub{ - get_def_setting($ipgen,$info); - - - }); - - $ipinfo->signal_connect("clicked"=> sub{ - get_Description($ipgen,$info); - - }); - $header_h->signal_connect("clicked"=> sub{ - my %page_info; - my $help1="The files and folder that selected here will be copied in generated processing tile SW folder."; - my $help2="The file listed here can contain some variable with \${var_name} format. The file generator will replace them with their values during file generation. The variable can be selected from above listed global variables"; - my $help3='Define the header file for this peripheral device. You can use global variables listed at the top. This file contains peripheral device functions\' deceleration, memory-mapped register address definition, definitions of data types, and C preprocessor commands. Do not put function definitions in the header file. Functions should be defined in add to tile.c section. - -header file example - - #define ${IP}_REG_0 (*((volatile unsigned int *) ($BASE))) - #define ${IP}_REG_1 (*((volatile unsigned int *) ($BASE+4))) - - - #define ${IP}_WRITE_REG1(value) ${IP}_REG_1=value - #define ${IP}_READ_REG1() ${IP}_REG_1 - '; - - my $help4='Define peripheral device\'s functions in this file. You can use global variables listed at the top. -'; - - - $page_info{0}{page_name} = "_Add existing file/folder"; - $page_info{0}{filed_name}= "sw_files"; - $page_info{0}{filed_type}= "existing_file/folder"; - $page_info{0}{rename_file}=undef; - $page_info{0}{folder_en}=1; - $page_info{0}{help}=$help1; - - $page_info{1}{page_name} = "_Add files contain variables"; - $page_info{1}{filed_name}= "gen_sw_files"; - $page_info{1}{filed_type}= "file_with_variables"; - $page_info{1}{rename_file}=1; - $page_info{1}{folder_en}=0; - $page_info{1}{help}=$help2; - - $page_info{2}{page_name} = "_Add to tile.h"; - $page_info{2}{filed_name}= "system_h"; - $page_info{2}{filed_type}= "file_content"; - $page_info{2}{rename_file}=undef; - $page_info{2}{folder_en}=0; - $page_info{2}{help}=$help3; - - - $page_info{3}{page_name} = "_Add to tile.c"; - $page_info{3}{filed_name}= "system_c"; - $page_info{3}{filed_type}= "file_content"; - $page_info{3}{rename_file}=undef; - $page_info{3}{folder_en}=0; - $page_info{3}{help}=$help4; - - - - - - get_source_file($ipgen,$info,0,"Add software file(s)","SW",\%page_info); - #get_software_file($ipgen,$info,0); - - }); - $lib_hdl->signal_connect("clicked"=> sub{ - my $help1="The files and folder that selected here will be copied in the generated processing tile src_verilog folder. If you tick simulation only option for each file/folder, they will be copied in src_sim folder instead and will only be used for simulation."; - my $help2="The files listed here can contain some variables with \${var_name} format. The file generator will replace them with their values during file generation. The variable can be selected from the above listed global variables."; - my $help3='The content here will be added to the generated tile.v file. You can define functions/tasks etc...'; - - my %page_info; - $page_info{0}{page_name} = "_Add existing HDL file/folder"; - $page_info{0}{filed_name}= "hdl_files"; - $page_info{0}{filed_type}= "existing_file/folder"; - $page_info{0}{rename_file}=undef; - $page_info{0}{folder_en}=1; - $page_info{0}{help}=$help1; - $page_info{0}{tick}="Used only for Simulation"; - - $page_info{1}{page_name} = "_Add files contain variables"; - $page_info{1}{filed_name}= "gen_hw_files"; - $page_info{1}{filed_type}= "file_with_variables"; - $page_info{1}{rename_file}=1; - $page_info{1}{folder_en}=0; - $page_info{1}{help}=$help2; - - $page_info{2}{page_name} = "_Add to tile.v"; - $page_info{2}{filed_name}= "system_v"; - $page_info{2}{filed_type}= "file_content"; - $page_info{2}{rename_file}=undef; - $page_info{2}{folder_en}=0; - $page_info{2}{help}=$help3; - - - get_source_file($ipgen,$info,0,"Add HDL file(s)", "hw",\%page_info); - - #get_hdl_file($ipgen,$info); - - - }); + my ($ipgen,$info,$table,$row)=@_; + my @modules= $ipgen->ipgen_get_module_list(); + my $saved_module=$ipgen->ipgen_get("module_name"); + my $pos=(defined $saved_module ) ? get_scolar_pos( $saved_module,@modules) : 0; + my $combo = gen_combo(\@modules, $pos); + my $top_module=gen_label_info(" Select\n module:",$combo); + my $param= def_image_button("icons/setting.png","Parameter\n setting"); + my $def= def_image_button("icons/setting.png","Definition\n file setting"); + #Category + my $ip = ip->lib_new (); + my @categories= $ip->ip_get_categories(); + $ip =undef; + my $saved_category=$ipgen->ipgen_get("category"); + if(defined $saved_category ){ push(@categories,$saved_category) if(!( grep /^$saved_category$/, @categories ));} + my $content=join( ',', @categories); + my $combentry=gen_comboentry_object ($ipgen,'category',undef,$content,$saved_category,undef,undef); + my $category=gen_label_info(" Select\n Category:",$combentry,"Select the IP category form the given list or you can add a new category."); + my $ipinfo= def_image_button("icons/add_info.png"," IP\n Description"); + my $header_h= def_image_button("icons/h_file.png","Add Software\n files"); + my $lib_hdl= def_image_button("icons/add-notes.png","Add HDL\n files"); + #$table->attach_defaults ($top_module, 0, 1 , $row, $row+1); + $table->attach ($top_module, 0, 4 , $row,$row+1,'fill','shrink',2,2); + $table->attach ($param, 4, 6 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($category, 6, 8 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($ipinfo, 8, 9 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($header_h, 9, 10 , $row, $row+1,'expand','shrink',2,2); + $table->attach ($lib_hdl, 10, 11 , $row, $row+1,'expand','shrink',2,2); + $combo->signal_connect("changed"=> sub{ + my $module= $combo->get_active_text(); + load_default_setting($ipgen,$module); + set_gui_status($ipgen,'intfc_changed',0); + }); + $param->signal_connect("clicked"=> sub{ + get_parameter_setting($ipgen,$info); + }); + $def->signal_connect("clicked"=> sub{ + get_def_setting($ipgen,$info); + }); + $ipinfo->signal_connect("clicked"=> sub{ + get_Description($ipgen,$info); + }); + $header_h->signal_connect("clicked"=> sub{ + my %page_info; + my $help1="The files and folder that selected here will be copied in generated processing tile SW folder."; + my $help2="The file listed here can contain some variable with \${var_name} format. The file generator will replace them with their values during file generation. The variable can be selected from above listed global variables"; + my $help3='Define the header file for this peripheral device. You can use global variables listed at the top. This file contains peripheral device functions\' deceleration, memory-mapped register address definition, definitions of data types, and C preprocessor commands. Do not put function definitions in the header file. Functions should be defined in add to tile.c section. +header file example + #define ${IP}_REG_0 (*((volatile unsigned int *) ($BASE))) + #define ${IP}_REG_1 (*((volatile unsigned int *) ($BASE+4))) + #define ${IP}_WRITE_REG1(value) ${IP}_REG_1=value + #define ${IP}_READ_REG1() ${IP}_REG_1 + '; + my $help4='Define peripheral device\'s functions in this file. You can use global variables listed at the top. +'; + $page_info{0}{page_name} = "_Add existing file/folder"; + $page_info{0}{filed_name}= "sw_files"; + $page_info{0}{filed_type}= "existing_file/folder"; + $page_info{0}{rename_file}=undef; + $page_info{0}{folder_en}=1; + $page_info{0}{help}=$help1; + $page_info{1}{page_name} = "_Add files contain variables"; + $page_info{1}{filed_name}= "gen_sw_files"; + $page_info{1}{filed_type}= "file_with_variables"; + $page_info{1}{rename_file}=1; + $page_info{1}{folder_en}=0; + $page_info{1}{help}=$help2; + $page_info{2}{page_name} = "_Add to tile.h"; + $page_info{2}{filed_name}= "system_h"; + $page_info{2}{filed_type}= "file_content"; + $page_info{2}{rename_file}=undef; + $page_info{2}{folder_en}=0; + $page_info{2}{help}=$help3; + $page_info{3}{page_name} = "_Add to tile.c"; + $page_info{3}{filed_name}= "system_c"; + $page_info{3}{filed_type}= "file_content"; + $page_info{3}{rename_file}=undef; + $page_info{3}{folder_en}=0; + $page_info{3}{help}=$help4; + get_source_file($ipgen,$info,0,"Add software file(s)","SW",\%page_info); + #get_software_file($ipgen,$info,0); + }); + $lib_hdl->signal_connect("clicked"=> sub{ + my $help1="The files and folder that selected here will be copied in the generated processing tile src_verilog folder. If you tick simulation only option for each file/folder, they will be copied in src_sim folder instead and will only be used for simulation."; + my $help2="The files listed here can contain some variables with \${var_name} format. The file generator will replace them with their values during file generation. The variable can be selected from the above listed global variables."; + my $help3='The content here will be added to the generated tile.v file. You can define functions/tasks etc...'; + my %page_info; + $page_info{0}{page_name} = "_Add existing HDL file/folder"; + $page_info{0}{filed_name}= "hdl_files"; + $page_info{0}{filed_type}= "existing_file/folder"; + $page_info{0}{rename_file}=undef; + $page_info{0}{folder_en}=1; + $page_info{0}{help}=$help1; + $page_info{0}{tick}="Used only for Simulation"; + $page_info{1}{page_name} = "_Add files contain variables"; + $page_info{1}{filed_name}= "gen_hw_files"; + $page_info{1}{filed_type}= "file_with_variables"; + $page_info{1}{rename_file}=1; + $page_info{1}{folder_en}=0; + $page_info{1}{help}=$help2; + $page_info{2}{page_name} = "_Add to tile.v"; + $page_info{2}{filed_name}= "system_v"; + $page_info{2}{filed_type}= "file_content"; + $page_info{2}{rename_file}=undef; + $page_info{2}{folder_en}=0; + $page_info{2}{help}=$help3; + get_source_file($ipgen,$info,0,"Add HDL file(s)", "hw",\%page_info); + #get_hdl_file($ipgen,$info); + }); } sub load_default_setting{ - my ($ipgen,$module)=@_; - my $file= $ipgen->ipgen_get("file_name"); - $file=add_project_dir_to_addr($file); - $ipgen->ipgen_add("module_name",$module); - my $vdb =read_verilog_file($file); - my %parameters = $vdb->get_modules_parameters_not_local($module); - my @parameters_order= $vdb->get_modules_parameters_not_local_order($module); - my @ports_order=$vdb->get_module_ports_order($module); - #print "@port_order\n"; - - #add default parameter setting - $ipgen->ipgen_remove_all_parameters(); - foreach my $p (keys %parameters){ - #print "$p\n"; - my $v = $parameters{$p}; - $v =~s/[\n]//gs; - $ipgen->ipgen_add_parameter($p,$v,'Fixed','','Parameter',1); - - } - #add parameter order. - $ipgen->ipgen_add("parameters_order",\@parameters_order); - #add port order. - $ipgen->ipgen_add_ports_order(@ports_order); - #add ports - $ipgen->ipgen_remove_all_ports(); - save_ports_all($ipgen,$vdb,$module); - - - + my ($ipgen,$module)=@_; + my $file= $ipgen->ipgen_get("file_name"); + $file=add_project_dir_to_addr($file); + $ipgen->ipgen_add("module_name",$module); + my $vdb =read_verilog_file($file); + my %parameters = $vdb->get_modules_parameters_not_local($module); + my @parameters_order= $vdb->get_modules_parameters_not_local_order($module); + my @ports_order=$vdb->get_module_ports_order($module); + #print "@port_order\n"; + #add default parameter setting + $ipgen->ipgen_remove_all_parameters(); + foreach my $p (keys %parameters){ + #print "$p\n"; + my $v = $parameters{$p}; + $v =~s/[\n]//gs; + $ipgen->ipgen_add_parameter($p,$v,'Fixed','','Parameter',1); + } + #add parameter order. + $ipgen->ipgen_add("parameters_order",\@parameters_order); + #add port order. + $ipgen->ipgen_add_ports_order(@ports_order); + #add ports + $ipgen->ipgen_remove_all_ports(); + save_ports_all($ipgen,$vdb,$module); } sub file_info_box { - my($ipgen,$info)=@_; - my $table=def_table(2,11,FALSE); - my $table1=def_table(1,11,FALSE); - my $table2=def_table(1,11,FALSE); - ip_file_box ($ipgen,$info,$table1,0); - select_module($ipgen,$info,$table2,0); - $table->attach($table1,0,11,0,1,'fill','shrink',2,2); - $table->attach($table2,0,11,1,2,'fill','shrink',2,2); - return add_widget_to_scrolled_win($table); - - + my($ipgen,$info)=@_; + my $table=def_table(2,11,FALSE); + my $table1=def_table(1,11,FALSE); + my $table2=def_table(1,11,FALSE); + ip_file_box ($ipgen,$info,$table1,0); + select_module($ipgen,$info,$table2,0); + $table->attach($table1,0,11,0,1,'fill','shrink',2,2); + $table->attach($table2,0,11,1,2,'fill','shrink',2,2); + return add_widget_to_scrolled_win($table); } - - - - - - sub show_port_info{ - my($intfc,$ipgen,$info,$refresh_ref)=@_; - my $table = port_info_box($intfc,$ipgen,$info,$info); - my $scrolled_win = add_widget_to_scrolled_win($table); - - - - $$refresh_ref-> signal_connect("clicked" => sub{ - $table->destroy; - $table = port_info_box($intfc,$ipgen,$info,$info); - - add_widget_to_scrolled_win($table,$scrolled_win); - $table->show; - $scrolled_win->show_all; - - - - - }); - - return $scrolled_win; - + my($intfc,$ipgen,$info,$refresh_ref)=@_; + my $table = port_info_box($intfc,$ipgen,$info,$info); + my $scrolled_win = add_widget_to_scrolled_win($table); + $$refresh_ref-> signal_connect("clicked" => sub{ + $table->destroy; + $table = port_info_box($intfc,$ipgen,$info,$info); + add_widget_to_scrolled_win($table,$scrolled_win); + $table->show; + $scrolled_win->show_all; + }); + return $scrolled_win; } - - - - - - - - ############ # get_parameter_setting ########## -sub get_parameter_setting { - my ($ipgen,$info)=@_; - - - my $file= $ipgen->ipgen_get("file_name"); - if (!defined $file) { - message_dialog("The input Verilog file is empty"); - #return; - - } - my $module = $ipgen->ipgen_get("module_name"); - - - my $window = def_popwin_size(85,50,"Define parameters detail",'percent'); - - - - - my @widget_type_list=("Fixed","Entry","Combo-box","Spin-button"); - my @param_type_list=("Parameter","Localparam","Don't include"); - my $type_info="Define the parameter type: - +sub get_parameter_setting { + my ($ipgen,$info)=@_; + my $file= $ipgen->ipgen_get("file_name"); + if (!defined $file) { + message_dialog("The input Verilog file is empty"); + #return; + } + my $module = $ipgen->ipgen_get("module_name"); + my $window = def_popwin_size(85,50,"Define parameters detail",'percent'); + my @widget_type_list=("Fixed","Entry","Combo-box","Spin-button"); + my @param_type_list=("Parameter","Localparam","Don't include"); + my $type_info="Define the parameter type: Fixed: The parameter is fixed and get the default value. Users can not see or change the parameter value. - Entry: The parameter value is received via entry. The user can type anything. - Combo-box: The parameter value can be selected from a list of predefined value. - Spin-button: The parameter is numeric and will be obtained using spin button."; - my $content_info=' + my $content_info=' For Fixed and Entry leave it empty. For Combo box define the parameters which must be shown in combo box as: "PAEAMETER1","PARAMETER2"...,"PARAMETERn". For Spin button define it as "minimum, maximum, step" e.g 0,10,1.'; - my $param_info='Define how parameter is included in the top module containig this IP core.'; - - my $redefine_info=' - If checked, the defined parameter/localparam in SoC will be passed to the IP core'; - - #TABLE - my $table = def_table(12,8,FALSE); - my @positions=(0,1,2,3,4,5,6,7,8); - my $col=0; - #title - my @title; - $title[0]=gen_label_in_center("Parameter name"); - $title[1]=gen_label_in_center("Default value"); - $title[2]=gen_label_help($type_info,"Widget type"); - $title[3]=gen_label_help($content_info,"Widget content"); - $title[4]=gen_label_help($param_info,"Type"); - $title[5]=gen_label_help($redefine_info,""); - $title[6]=gen_label_help("You can add additional information about this parameter.","info"); - $title[7]=gen_label_in_center("add/remove"); - - - foreach my $t (@title){ - $table->attach ($title[$col], $positions[$col], $positions[$col+1], 0, 1,'expand','shrink',2,2); $col++; - - } - - - my @parameters=$ipgen->ipgen_get_all_parameters_list(); - my @params_order= $ipgen->ipgen_get_list("parameters_order"); - if((@params_order)) {@parameters=@params_order;} - - my $ok = def_image_button('icons/select.png','OK'); - - - my ($b,$new_param)= def_h_labeled_entry("Add new parameter name:"); - my $add = def_image_button('icons/plus.png','Add parameter'); - my $addbox=def_hbox(FALSE,0); - $addbox->pack_start($b,FALSE, FALSE,0); - $addbox->pack_start($add, FALSE, FALSE,0); - - my @allowed; - - my $row=1; - my $error; - push(@parameters,"#new#"); - foreach my $p (@parameters) { - my ($saved_default,$saved_widget_type,$saved_content,$saved_info,$vfile_param_type,$redefine_param)= $ipgen->ipgen_get_parameter_detail($p); - #print "($saved_default,$saved_type,$saved_content)\n"; - my $parameter_box = def_hbox(TRUE,5); - my $param_name; - my $add_remove; - if($p ne "#new#"){ - $param_name= def_label($p); - $add_remove=def_image_button("icons/cancel.png","remove"); - } else { - $param_name= gen_entry(); - $add_remove=def_image_button("icons/plus.png","add"); - } - - my $default_entry= gen_entry($saved_default); - my $pos=(defined $saved_widget_type ) ? get_scolar_pos( $saved_widget_type,@widget_type_list) : 0; - my $widget_type_combo=gen_combo(\@widget_type_list, $pos); - my $content_entry= gen_entry($saved_content); - - - - $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); - $vfile_param_type= "Parameter" if ($vfile_param_type eq 1); - $vfile_param_type= "Localparam" if ($vfile_param_type eq 0); - $pos=get_scolar_pos($vfile_param_type,@param_type_list); - my $check_param= gen_combo(\@param_type_list, $pos); - - - #$check_param->set_active($vfile_param_type) if(defined $vfile_param_type ); - my $check_redefine= gen_checkbutton('Redefine'); - $check_redefine->set_active(1) ; - $check_redefine->set_active($redefine_param) if(defined $redefine_param ); - - my $info=def_image_button("icons/add_info.png"); - #print "\$vfile_param_type =$vfile_param_type\n"; - - $col=0; - my @all_widget=($param_name,$default_entry,$widget_type_combo,$content_entry,$check_param,$check_redefine,$info,$add_remove); - foreach my $t (@all_widget){ - $table->attach ($t, $positions[$col], $positions[$col+1], $row, $row+1,'expand','shrink',2,2);$col++; - - } - - - $info->signal_connect (clicked => sub{ - - get_param_info($ipgen,\$saved_info); - }); - - - $ok->signal_connect (clicked => sub{ - if($p ne "#new#"){ - my $default=$default_entry->get_text(); - my $type= $widget_type_combo->get_active_text(); - my $content=$content_entry->get_text(); - my $vfile_param_type=$check_param->get_active_text(); - my $check_result=$check_redefine->get_active(); - my $redefine_param=($check_result eq 1)? 1:0; - $ipgen->ipgen_add_parameter($p,$default,$type,$content,$saved_info,$vfile_param_type,$redefine_param); - - if ($type eq "Spin-button"){ - my @d=split(/\s*,\s*/,$content); - if( scalar @d != 3){ - $error=$error."wrong content setting for parameter $p\n" ; - print "$error"; - } - } - - - } - }); - $add_remove->signal_connect (clicked => sub{ - if($p eq "#new#"){ #add new parameter - my $param= $param_name->get_text(); - $param=remove_all_white_spaces($param); - - if( length($param) ){ - my $default=$default_entry->get_text(); - my $type=$widget_type_combo->get_active_text(); - my $content=$content_entry->get_text(); - my $vfile_param_type=$check_param->get_active_text(); - my $check_result=$check_redefine->get_active(); - my $redefine_param=($check_result eq 1)? 1:0; - $ipgen->ipgen_add_parameter($param,$default,$type,$content,$saved_info,$vfile_param_type,$redefine_param); - $ipgen->ipgen_push_parameters_order($param); - set_gui_status($ipgen,"change_parameter",0); - $ok->clicked; - #$window->destroy(); - } - - } else { #remove the parameter - $ipgen->ipgen_remove_parameter($p); - $ipgen->ipgen_remove_parameters_order($p); - $p = "#new#"; - set_gui_status($ipgen,"change_parameter",0); - $ok->clicked; - #$window->destroy(); - - } - #my $param_name=$new_param->get_text(); - # if( length($param_name) ){ - # print "$param_name\n"; - # $ipgen->ipgen_add_parameter($param_name,undef); - # set_gui_status($ipgen,"change_parameter",0); - # $window->destroy(); - - }); - - - - $row++; - } - - - - - - my $scrolled_win = add_widget_to_scrolled_win($table); - - - - - - - - - $add->signal_connect (clicked => sub{ - my $param_name=$new_param->get_text(); - if( length($param_name) ){ - #print "$param_name\n"; - $ipgen->ipgen_add_parameter($param_name,undef); - set_gui_status($ipgen,"change_parameter",0); - $window->destroy(); - } - + my $param_info='Define how parameter is included in the top module containig this IP core.'; + my $redefine_info=' + If checked, the defined parameter/localparam in SoC will be passed to the IP core'; + #TABLE + my $table = def_table(12,8,FALSE); + my @positions=(0,1,2,3,4,5,6,7,8); + my $col=0; + #title + my @title; + $title[0]=gen_label_in_center("Parameter name"); + $title[1]=gen_label_in_center("Default value"); + $title[2]=gen_label_help($type_info,"Widget type"); + $title[3]=gen_label_help($content_info,"Widget content"); + $title[4]=gen_label_help($param_info,"Type"); + $title[5]=gen_label_help($redefine_info,""); + $title[6]=gen_label_help("You can add additional information about this parameter.","info"); + $title[7]=gen_label_in_center("add/remove"); + foreach my $t (@title){ + $table->attach ($title[$col], $positions[$col], $positions[$col+1], 0, 1,'expand','shrink',2,2); $col++; + } + my @parameters=$ipgen->ipgen_get_all_parameters_list(); + my @params_order= $ipgen->ipgen_get_list("parameters_order"); + if((@params_order)) {@parameters=@params_order;} + my $ok = def_image_button('icons/select.png','OK'); + my ($b,$new_param)= def_h_labeled_entry("Add new parameter name:"); + my $add = def_image_button('icons/plus.png','Add parameter'); + my $addbox=def_hbox(FALSE,0); + $addbox->pack_start($b,FALSE, FALSE,0); + $addbox->pack_start($add, FALSE, FALSE,0); + my @allowed; + my $row=1; + my $error; + push(@parameters,"#new#"); + foreach my $p (@parameters) { + my ($saved_default,$saved_widget_type,$saved_content,$saved_info,$vfile_param_type,$redefine_param)= $ipgen->ipgen_get_parameter_detail($p); + #print "($saved_default,$saved_type,$saved_content)\n"; + my $parameter_box = def_hbox(TRUE,5); + my $param_name; + my $add_remove; + if($p ne "#new#"){ + $param_name= def_label($p); + $add_remove=def_image_button("icons/cancel.png","remove"); + } else { + $param_name= gen_entry(); + $add_remove=def_image_button("icons/plus.png","add"); + } + my $default_entry= gen_entry($saved_default); + my $pos=(defined $saved_widget_type ) ? get_scolar_pos( $saved_widget_type,@widget_type_list) : 0; + my $widget_type_combo=gen_combo(\@widget_type_list, $pos); + my $content_entry= gen_entry($saved_content); + $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); + $vfile_param_type= "Parameter" if ($vfile_param_type eq 1); + $vfile_param_type= "Localparam" if ($vfile_param_type eq 0); + $pos=get_scolar_pos($vfile_param_type,@param_type_list); + my $check_param= gen_combo(\@param_type_list, $pos); + #$check_param->set_active($vfile_param_type) if(defined $vfile_param_type ); + my $check_redefine= gen_checkbutton('Redefine'); + $check_redefine->set_active(1) ; + $check_redefine->set_active($redefine_param) if(defined $redefine_param ); + my $info=def_image_button("icons/add_info.png"); + #print "\$vfile_param_type =$vfile_param_type\n"; + $col=0; + my @all_widget=($param_name,$default_entry,$widget_type_combo,$content_entry,$check_param,$check_redefine,$info,$add_remove); + foreach my $t (@all_widget){ + $table->attach ($t, $positions[$col], $positions[$col+1], $row, $row+1,'expand','shrink',2,2);$col++; + } + $info->signal_connect (clicked => sub{ + get_param_info($ipgen,\$saved_info); + }); + $ok->signal_connect (clicked => sub{ + if($p ne "#new#"){ + my $default=$default_entry->get_text(); + my $type= $widget_type_combo->get_active_text(); + my $content=$content_entry->get_text(); + my $vfile_param_type=$check_param->get_active_text(); + my $check_result=$check_redefine->get_active(); + my $redefine_param=($check_result eq 1)? 1:0; + $ipgen->ipgen_add_parameter($p,$default,$type,$content,$saved_info,$vfile_param_type,$redefine_param); + if ($type eq "Spin-button"){ + my @d=split(/\s*,\s*/,$content); + if( scalar @d != 3){ + $error=$error."wrong content setting for parameter $p\n" ; + print "$error"; + } + } + } + }); + $add_remove->signal_connect (clicked => sub{ + if($p eq "#new#"){ #add new parameter + my $param= $param_name->get_text(); + $param=remove_all_white_spaces($param); + if( length($param) ){ + my $default=$default_entry->get_text(); + my $type=$widget_type_combo->get_active_text(); + my $content=$content_entry->get_text(); + my $vfile_param_type=$check_param->get_active_text(); + my $check_result=$check_redefine->get_active(); + my $redefine_param=($check_result eq 1)? 1:0; + $ipgen->ipgen_add_parameter($param,$default,$type,$content,$saved_info,$vfile_param_type,$redefine_param); + $ipgen->ipgen_push_parameters_order($param); + set_gui_status($ipgen,"change_parameter",0); + $ok->clicked; + #$window->destroy(); + } + } else { #remove the parameter + $ipgen->ipgen_remove_parameter($p); + $ipgen->ipgen_remove_parameters_order($p); + $p = "#new#"; + set_gui_status($ipgen,"change_parameter",0); + $ok->clicked; + #$window->destroy(); + } + #my $param_name=$new_param->get_text(); + # if( length($param_name) ){ + # print "$param_name\n"; + # $ipgen->ipgen_add_parameter($param_name,undef); + # set_gui_status($ipgen,"change_parameter",0); + # $window->destroy(); + }); + $row++; + } + my $scrolled_win = add_widget_to_scrolled_win($table); + $add->signal_connect (clicked => sub{ + my $param_name=$new_param->get_text(); + if( length($param_name) ){ + #print "$param_name\n"; + $ipgen->ipgen_add_parameter($param_name,undef); + set_gui_status($ipgen,"change_parameter",0); + $window->destroy(); + } #/*******************************************************************************************************************************/ - - }); - - $ok->signal_connect (clicked => sub{ - - - - - - - if (defined $error){ - message_dialog("$error",'error'); - $error=undef; - }else { - $window->destroy(); - } - - }); - - my $mtable = def_table(10, 1, FALSE); - $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable->attach($ok,0,1,9,10,'expand','shrink',2,2); - - $window->add ($mtable); - $window->show_all(); - - - + }); + $ok->signal_connect (clicked => sub{ + if (defined $error){ + message_dialog("$error",'error'); + $error=undef; + }else { + $window->destroy(); + } + }); + my $mtable = def_table(10, 1, FALSE); + $mtable->attach_defaults($scrolled_win,0,1,0,9); + $mtable->attach($ok,0,1,9,10,'expand','shrink',2,2); + $window->add ($mtable); + $window->show_all(); } - - - ############ # get_def_setting ########## -sub get_def_setting { - my ($ipgen,$info)=@_; - my $table = def_table (15, 15, TRUE); - my $table2 = def_table (15, 15, TRUE); - my $window = def_popwin_size(70,70,"Add definition file",'percent'); - my $ok=def_image_button("icons/select.png",' Ok '); - - my $scrwin = add_widget_to_scrolled_win($table2); - - my $label=gen_label_help("You ","Select the Verilog file containing the definitions."); - my $brows=def_image_button("icons/browse.png",' Browse'); - $table->attach_defaults($label,0,10,0,1); - $table->attach($brows,10,12,1,2,'expand','shrink',2,2); - $table->attach_defaults($scrwin,0,15,2,14); - $table->attach($ok,6,9,14,15,'expand','shrink',2,2); - - $window->add($table); - $window->show_all; - - +sub get_def_setting { + my ($ipgen,$info)=@_; + my $table = def_table (15, 15, TRUE); + my $table2 = def_table (15, 15, TRUE); + my $window = def_popwin_size(70,70,"Add definition file",'percent'); + my $ok=def_image_button("icons/select.png",' Ok '); + my $scrwin = add_widget_to_scrolled_win($table2); + my $label=gen_label_help("You ","Select the Verilog file containing the definitions."); + my $brows=def_image_button("icons/browse.png",' Browse'); + $table->attach_defaults($label,0,10,0,1); + $table->attach($brows,10,12,1,2,'expand','shrink',2,2); + $table->attach_defaults($scrwin,0,15,2,14); + $table->attach($ok,6,9,14,15,'expand','shrink',2,2); + $window->add($table); + $window->show_all; } - ########### -# get description +# get description ######### - sub get_Description{ - my ($ipgen,$info)=@_; - my $description = $ipgen->ipgen_get("description"); - my $table = def_table (15, 15, FALSE); - my $window = def_popwin_size(40,40, "Add description",'percent'); - my ($scrwin,$text_view)=create_txview(); - #my $buffer = $textbox->get_buffer(); - my $ok=def_image_button("icons/select.png",' Ok '); - $table->attach_defaults(gen_label_help("User can open the PDF file when opening IP parameter setting","IP Documentation file in PDF"),0,7,0,1); - $table->attach_defaults(gen_label_help("Description will be shown on IP generator text view when selecting this IP","Short Description"),5,10,1,2); - $table->attach_defaults(get_file_name_object ( $ipgen, 'description_pdf',undef,"pdf",undef),7,15,0,1); - $table->attach_defaults($scrwin,0,15,2,14); - $table->attach($ok,6,9,14,15,'expand','shrink',2,2); - my $text_buffer = $text_view->get_buffer; - if(defined $description) {$text_buffer->set_text($description)}; - - $ok->signal_connect("clicked"=> sub { - $window->destroy; - - my $text = $text_buffer->get_text($text_buffer->get_bounds, TRUE); - $ipgen->ipgen_add("description",$text); - #print "$text\n"; - - }); - - $window->add($table); - $window->show_all(); - -} - - - - - + my ($ipgen,$info)=@_; + my $description = $ipgen->ipgen_get("description"); + my $table = def_table (15, 15, FALSE); + my $window = def_popwin_size(40,40, "Add description",'percent'); + my ($scrwin,$text_view)=create_txview(); + #my $buffer = $textbox->get_buffer(); + my $ok=def_image_button("icons/select.png",' Ok '); + $table->attach_defaults(gen_label_help("User can open the PDF file when opening IP parameter setting","IP Documentation file in PDF"),0,7,0,1); + $table->attach_defaults(gen_label_help("Description will be shown on IP generator text view when selecting this IP","Short Description"),5,10,1,2); + $table->attach_defaults(get_file_name_object ( $ipgen, 'description_pdf',undef,"pdf",undef),7,15,0,1); + $table->attach_defaults($scrwin,0,15,2,14); + $table->attach($ok,6,9,14,15,'expand','shrink',2,2); + my $text_buffer = $text_view->get_buffer; + if(defined $description) {$text_buffer->set_text($description)}; + $ok->signal_connect("clicked"=> sub { + $window->destroy; + my $text = $text_buffer->get_text($text_buffer->get_bounds, TRUE); + $ipgen->ipgen_add("description",$text); + #print "$text\n"; + }); + $window->add($table); + $window->show_all(); +} ########## -# gen_file_list +# gen_file_list ######### - sub gen_file_list{ - my ($ipgen,$list_name,$window,$rename_file_en,$tick)=@_; - - - my $table=def_table(10,10,FALSE);# my ($row,$col,$homogeneous)=@_; - my $ok=def_image_button("icons/select.png",' Ok '); - my $scrolled_win = add_widget_to_scrolled_win($table); - - $table->attach (gen_label_in_center("File path"), 0, 5 , 0, 1,'expand','shrink',2,2); - $table->attach (gen_label_help("The target name can contain any of Global variables e.g \$IP\$.h","Copy as"), 5, 9 , 0, 1,'expand','shrink',2,2) if(defined $rename_file_en); - $table->attach (gen_label_in_center("$tick"), 9, 10 , 0, 1,'expand','shrink',2,2) if (defined $tick); - my $col=0; + my ($ipgen,$list_name,$window,$rename_file_en,$tick)=@_; + my $table=def_table(10,10,FALSE);# my ($row,$col,$homogeneous)=@_; + my $ok=def_image_button("icons/select.png",' Ok '); + my $scrolled_win = add_widget_to_scrolled_win($table); + $table->attach (gen_label_in_center("File path"), 0, 5 , 0, 1,'expand','shrink',2,2); + $table->attach (gen_label_help("The target name can contain any of Global variables e.g \$IP\$.h","Copy as"), 5, 9 , 0, 1,'expand','shrink',2,2) if(defined $rename_file_en); + $table->attach (gen_label_in_center("$tick"), 9, 10 , 0, 1,'expand','shrink',2,2) if (defined $tick); + my $col=0; my $row=1; - my @files= $ipgen->ipgen_get_list($list_name); #@{$ref}; - my $file_num= scalar @files; - foreach my $p(@files){ - my ($path,$rename)=split('frename_sep_t',$p); - my $entry=gen_entry($path); - my $entry2=gen_entry($rename); - - my $remove=def_image_button("icons/cancel.png"); - $table->attach ($entry, 0, 5 , $row, $row+1,'fill','shrink',2,2); - $table->attach ($entry2, 5, 9 , $row, $row+1,'fill','shrink',2,2) if(defined $rename_file_en); - $table->attach ($remove, 10,11 , $row, $row+1,'expand','shrink',2,2); - my $check= gen_checkbutton(); - if (defined $tick){ - $table->attach ($check, 9,10 , $row, $row+1,'expand','shrink',2,2); - $check-> signal_connect("toggled" => sub{ - my @ticked_files=$ipgen->ipgen_get_list($list_name."_ticked"); - @ticked_files =() if (!@ticked_files); - - - if($check->get_active()){ - push(@ticked_files,$p); - }else{ - @ticked_files=remove_scolar_from_array(\@ticked_files,$p); - } - $ipgen->ipgen_add($list_name."_ticked",\@ticked_files); - }); - - } - $row++; - - - $remove->signal_connect("clicked"=> sub { - my @saved_files=$ipgen->ipgen_get_list($list_name); - @saved_files=remove_scolar_from_array(\@saved_files,$p); - $ipgen->ipgen_add($list_name,\@saved_files); - - my @ticked_files=$ipgen->ipgen_get_list($list_name."_ticked"); - @ticked_files=remove_scolar_from_array(\@ticked_files,$p); - $ipgen->ipgen_add($list_name."_ticked",\@ticked_files); - - - $entry->destroy; - $entry2->destroy if(defined $rename_file_en); - $remove->destroy; - - }); - $ok->signal_connect("clicked"=> sub { - if(defined $entry){ - my $n= $entry->get_text(); - if(defined $rename_file_en){ - $n= $n.'frename_sep_t'.$entry2->get_text() ; - } - if($p ne $n){ - my @saved_files=$ipgen->ipgen_get_list($list_name); - @saved_files=replace_in_array(\@saved_files,$p, $n); - $ipgen->ipgen_add($list_name,\@saved_files); - } - - } - - - - }); - - - - } - - - - $ok->signal_connect("clicked"=> sub { - $window->destroy; - }); - + my @files= $ipgen->ipgen_get_list($list_name); #@{$ref}; + my $file_num= scalar @files; + foreach my $p(@files){ + my ($path,$rename)=split('frename_sep_t',$p); + my $entry=gen_entry($path); + my $entry2=gen_entry($rename); + my $remove=def_image_button("icons/cancel.png"); + $table->attach ($entry, 0, 5 , $row, $row+1,'fill','shrink',2,2); + $table->attach ($entry2, 5, 9 , $row, $row+1,'fill','shrink',2,2) if(defined $rename_file_en); + $table->attach ($remove, 10,11 , $row, $row+1,'expand','shrink',2,2); + my $check= gen_checkbutton(); + if (defined $tick){ + $table->attach ($check, 9,10 , $row, $row+1,'expand','shrink',2,2); + $check-> signal_connect("toggled" => sub{ + my @ticked_files=$ipgen->ipgen_get_list($list_name."_ticked"); + @ticked_files =() if (!@ticked_files); + if($check->get_active()){ + push(@ticked_files,$p); + }else{ + @ticked_files=remove_scolar_from_array(\@ticked_files,$p); + } + $ipgen->ipgen_add($list_name."_ticked",\@ticked_files); + }); + } + $row++; + $remove->signal_connect("clicked"=> sub { + my @saved_files=$ipgen->ipgen_get_list($list_name); + @saved_files=remove_scolar_from_array(\@saved_files,$p); + $ipgen->ipgen_add($list_name,\@saved_files); + my @ticked_files=$ipgen->ipgen_get_list($list_name."_ticked"); + @ticked_files=remove_scolar_from_array(\@ticked_files,$p); + $ipgen->ipgen_add($list_name."_ticked",\@ticked_files); + $entry->destroy; + $entry2->destroy if(defined $rename_file_en); + $remove->destroy; + }); + $ok->signal_connect("clicked"=> sub { + if(defined $entry){ + my $n= $entry->get_text(); + if(defined $rename_file_en){ + $n= $n.'frename_sep_t'.$entry2->get_text() ; + } + if($p ne $n){ + my @saved_files=$ipgen->ipgen_get_list($list_name); + @saved_files=replace_in_array(\@saved_files,$p, $n); + $ipgen->ipgen_add($list_name,\@saved_files); + } + } + }); + } + $ok->signal_connect("clicked"=> sub { + $window->destroy; + }); # while( $row<10){ - # my $label=gen_label_in_left(' '); - # $table->attach_defaults ($label, 0, 1 , $row, $row+1);$row++; - #} - - - return ($scrolled_win,$ok); + # my $label=gen_label_in_left(' '); + # $table->attach_defaults ($label, 0, 1 , $row, $row+1);$row++; + #} + return ($scrolled_win,$ok); } - - sub get_param_info{ - my ($ipgen,$saved_info)=@_; - my $table = def_table (15, 15, FALSE); - my $window = def_popwin_size(50,50,"Add description",'percent'); - my ($scrwin,$text_view)=create_txview(); - my $ok=def_image_button("icons/select.png",' Ok '); - - $table->attach_defaults($scrwin,0,15,0,14); - $table->attach($ok,6,9,14,15,'expand','shrink',2,2); - my $text_buffer = $text_view->get_buffer; - if(defined $$saved_info) {$text_buffer->set_text($$saved_info)}; - - $ok->signal_connect("clicked"=> sub { - $window->destroy; - - $$saved_info = $text_buffer->get_text($text_buffer->get_bounds, TRUE); - - - }); - - $window->add($table); - $window->show_all(); - - -} - - + my ($ipgen,$saved_info)=@_; + my $table = def_table (15, 15, FALSE); + my $window = def_popwin_size(50,50,"Add description",'percent'); + my ($scrwin,$text_view)=create_txview(); + my $ok=def_image_button("icons/select.png",' Ok '); + $table->attach_defaults($scrwin,0,15,0,14); + $table->attach($ok,6,9,14,15,'expand','shrink',2,2); + my $text_buffer = $text_view->get_buffer; + if(defined $$saved_info) {$text_buffer->set_text($$saved_info)}; + $ok->signal_connect("clicked"=> sub { + $window->destroy; + $$saved_info = $text_buffer->get_text($text_buffer->get_bounds, TRUE); + }); + $window->add($table); + $window->show_all(); +} sub interface_info_box { - my($intfc,$ipgen,$info)=@_; - my $table=def_table(7,7,FALSE); - my @sokets=$ipgen->ipgen_list_sokets; - my @plugs=$ipgen->ipgen_list_plugs; - - my @positions=(0,1,2,4,5,6,7); - - - my $row=0; - my $col=0; - $table->attach (gen_label_in_center(" Interface name"), $positions[0], $positions[1], $row, $row+1,'expand','shrink',2,2); - $table->attach (gen_label_in_center("Type"), $positions[1], $positions[2], $row, $row+1,'expand','shrink',2,2); - $table->attach (gen_label_in_left("Interface Num"), $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); - - $row++; - my @type_list=('plug','socket'); - - foreach my $p( @sokets){ - #my ($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($p); - my ($type,$value,$connection_num)= $ipgen->ipgen_get_socket($p); - my $label_name=gen_label_in_center($p); - my $combo_type=gen_combo(\@type_list,1); - my $remove= def_image_button('icons/cancel.png','Remove'); - my $name_setting=def_image_button('icons/setting.png'); - $remove->signal_connect ('clicked'=> sub{ - $ipgen->ipgen_remove_socket($p); - set_gui_status($ipgen,'intfc_changed',0); - - } ); - $name_setting->signal_connect ('clicked'=> sub{ - get_intfc_setting($ipgen,$p,'socket'); - - - }); - $combo_type ->signal_connect ('changed'=> sub{ - $ipgen->ipgen_remove_socket($p); - add_intfc_to_ip($intfc,$ipgen,$p,'plug',$info); - - } ); - $table->attach ($remove, $positions[4], $positions[5], $row, $row+1,'expand','shrink',2,2); + my($intfc,$ipgen,$info)=@_; + my $table=def_table(7,7,FALSE); + my @sokets=$ipgen->ipgen_list_sokets; + my @plugs=$ipgen->ipgen_list_plugs; + my @positions=(0,1,2,4,5,6,7); + my $row=0; + my $col=0; + $table->attach (gen_label_in_center(" Interface name"), $positions[0], $positions[1], $row, $row+1,'expand','shrink',2,2); + $table->attach (gen_label_in_center("Type"), $positions[1], $positions[2], $row, $row+1,'expand','shrink',2,2); + $table->attach (gen_label_in_left("Interface Num"), $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); + $row++; + my @type_list=('plug','socket'); + foreach my $p( @sokets){ + #my ($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($p); + my ($type,$value,$connection_num)= $ipgen->ipgen_get_socket($p); + my $label_name=gen_label_in_center($p); + my $combo_type=gen_combo(\@type_list,1); + my $remove= def_image_button('icons/cancel.png','Remove'); + my $name_setting=def_image_button('icons/setting.png'); + $remove->signal_connect ('clicked'=> sub{ + $ipgen->ipgen_remove_socket($p); + set_gui_status($ipgen,'intfc_changed',0); + } ); + $name_setting->signal_connect ('clicked'=> sub{ + get_intfc_setting($ipgen,$p,'socket'); + }); + $combo_type ->signal_connect ('changed'=> sub{ + $ipgen->ipgen_remove_socket($p); + add_intfc_to_ip($intfc,$ipgen,$p,'plug',$info); + } ); + $table->attach ($remove, $positions[4], $positions[5], $row, $row+1,'expand','shrink',2,2); + if ($type eq 'num'){ + my ($type_box,$type_spin)=gen_spin_help ('Define the number of this interface in module', 1,1024,1); + $type_box->pack_start($name_setting,FALSE,FALSE,0); + $type_spin->set_value($value); + my $advance_button=def_image_button('icons/advance.png','separate'); + $table->attach ($type_box, $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); + $table->attach ($advance_button, $positions[3], $positions[4], $row, $row+1,'expand','shrink',2,2); + $type_spin->signal_connect("value_changed"=>sub{ + my $wiget=shift; + my $num=$wiget->get_value_as_int(); + $ipgen->ipgen_add_soket($p,'num',$num); + set_gui_status($ipgen,'intfc_changed',0); + }); + $advance_button->signal_connect("clicked"=>sub{ + $ipgen->ipgen_add_soket($p,'param'); + set_gui_status($ipgen,'intfc_changed',0); + }); + } + else { + my @parameters=$ipgen->ipgen_get_all_parameters_list(); + my $pos= get_scolar_pos( $value,@parameters); + if(!defined $pos){ + $pos=0; + $ipgen->ipgen_add_soket($p,'param',$parameters[0]); + } + my ($type_box,$type_combo)=gen_combo_help ('Define the parameter which determine the number of this interface in module',\@parameters,$pos); + $type_box->pack_start($name_setting,FALSE,FALSE,0); + my $advance_button=def_image_button('icons/advance.png','concatenate'); + $table->attach ($type_box, $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); + $table->attach ($advance_button, $positions[3], $positions[4], $row, $row+1,'expand','shrink',2,2); + $type_combo->signal_connect("changed"=>sub{ + my $wiget=shift; + my $value=$wiget->get_active_text(); + $ipgen->ipgen_add_soket($p,'param',$value); + set_gui_status($ipgen,'intfc_changed',0); + }); + $advance_button->signal_connect("clicked"=>sub{ + $ipgen->ipgen_add_soket($p,'num',0); + set_gui_status($ipgen,'intfc_changed',0); + }); + } + $table->attach ($label_name, $positions[0], $positions[1], $row, $row+1,'expand','shrink',2,2); + $table->attach ($combo_type, $positions[1], $positions[2], $row, $row+1,'expand','shrink',2,2); + $row++; + } + foreach my $q( @plugs){ + #my ($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($p); + my ($type,$value)= $ipgen->ipgen_get_plug($q); + my $label_name=gen_label_in_center($q); + my $combo_type=gen_combo(\@type_list,0); + my $remove= def_image_button('icons/cancel.png','Remove'); + my $name_setting=def_image_button('icons/setting.png'); + $table->attach ($remove, $positions[4], $positions[5], $row, $row+1,'expand','shrink',2,2); + $remove->signal_connect ('clicked'=> sub{ + $ipgen->ipgen_remove_plug($q); + set_gui_status($ipgen,'intfc_changed',0); + } ); + $name_setting->signal_connect ('clicked'=> sub{ + get_intfc_setting($ipgen,$q,'plug'); + } ); + $combo_type ->signal_connect ('changed'=> sub{ + $ipgen->ipgen_remove_plug($q); + add_intfc_to_ip($intfc,$ipgen,$q,'socket',$info); + } ); + #my $range_entry=gen_entry($range); + if ($type eq 'num'){ + my ($type_box,$type_spin)=gen_spin_help ('Define the number of this interface in module', 1,1024,1); + $type_box->pack_start($name_setting,FALSE,FALSE,0); + $type_spin->set_value($value); + $table->attach ($type_box, $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); + $type_spin->signal_connect("value_changed"=>sub{ + my $wiget=shift; + my $num=$wiget->get_value_as_int(); + $ipgen->ipgen_add_plug($q,'num',$num); + set_gui_status($ipgen,'intfc_changed',0); + }); + } + $table->attach ($label_name, $positions[0], $positions[1], $row, $row+1,'expand','shrink',2,2); + $table->attach ($combo_type, $positions[1], $positions[2], $row, $row+1,'expand','shrink',2,2); + #$table->attach_defaults ($range_entry, 2, 4, $row, $row+1); + #wishbone address seting + #print "$q eq 'wb_slave'\n"; + if($q eq 'wb_slave'){ + my ($saved_addr,$saved_width)=$ipgen->ipgen_get_wb_addr($q,0); + my $addr; + if(!defined $saved_addr){ + $addr= def_image_button('icons/warning.png'); + $addr->signal_connect ('clicked'=> sub{ + message_dialog("Wishbone slave address range has not been set yet! "); + } ); + }else{ + $addr= def_image_button('icons/select.png'); + } + $table->attach ($addr, $positions[5], $positions[6], $row, $row+1,'expand','shrink',2,2); + } + $row++; + } + return add_widget_to_scrolled_win($table); +} - - if ($type eq 'num'){ - my ($type_box,$type_spin)=gen_spin_help ('Define the number of this interface in module', 1,1024,1); - $type_box->pack_start($name_setting,FALSE,FALSE,0); - $type_spin->set_value($value); - my $advance_button=def_image_button('icons/advance.png','separate'); - $table->attach ($type_box, $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); - $table->attach ($advance_button, $positions[3], $positions[4], $row, $row+1,'expand','shrink',2,2); - $type_spin->signal_connect("value_changed"=>sub{ - my $wiget=shift; - my $num=$wiget->get_value_as_int(); - $ipgen->ipgen_add_soket($p,'num',$num); - set_gui_status($ipgen,'intfc_changed',0); - - }); - $advance_button->signal_connect("clicked"=>sub{ - $ipgen->ipgen_add_soket($p,'param'); - set_gui_status($ipgen,'intfc_changed',0); - - }); - - } - else { - my @parameters=$ipgen->ipgen_get_all_parameters_list(); - my $pos= get_scolar_pos( $value,@parameters); - if(!defined $pos){ - $pos=0; - $ipgen->ipgen_add_soket($p,'param',$parameters[0]); - } - my ($type_box,$type_combo)=gen_combo_help ('Define the parameter which determine the number of this interface in module',\@parameters,$pos); - $type_box->pack_start($name_setting,FALSE,FALSE,0); - my $advance_button=def_image_button('icons/advance.png','concatenate'); - $table->attach ($type_box, $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); - $table->attach ($advance_button, $positions[3], $positions[4], $row, $row+1,'expand','shrink',2,2); - $type_combo->signal_connect("changed"=>sub{ - my $wiget=shift; - my $value=$wiget->get_active_text(); - $ipgen->ipgen_add_soket($p,'param',$value); - set_gui_status($ipgen,'intfc_changed',0); - - }); - $advance_button->signal_connect("clicked"=>sub{ - $ipgen->ipgen_add_soket($p,'num',0); - set_gui_status($ipgen,'intfc_changed',0); - - }); - - } - - - - - - - $table->attach ($label_name, $positions[0], $positions[1], $row, $row+1,'expand','shrink',2,2); - $table->attach ($combo_type, $positions[1], $positions[2], $row, $row+1,'expand','shrink',2,2); - - - - - $row++; - } - foreach my $q( @plugs){ - #my ($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($p); - my ($type,$value)= $ipgen->ipgen_get_plug($q); - my $label_name=gen_label_in_center($q); - my $combo_type=gen_combo(\@type_list,0); - my $remove= def_image_button('icons/cancel.png','Remove'); - my $name_setting=def_image_button('icons/setting.png'); - - $table->attach ($remove, $positions[4], $positions[5], $row, $row+1,'expand','shrink',2,2); - $remove->signal_connect ('clicked'=> sub{ - $ipgen->ipgen_remove_plug($q); - set_gui_status($ipgen,'intfc_changed',0); - - } ); - $name_setting->signal_connect ('clicked'=> sub{ - get_intfc_setting($ipgen,$q,'plug'); - - - } ); - $combo_type ->signal_connect ('changed'=> sub{ - $ipgen->ipgen_remove_plug($q); - add_intfc_to_ip($intfc,$ipgen,$q,'socket',$info); - - } ); - #my $range_entry=gen_entry($range); - if ($type eq 'num'){ - my ($type_box,$type_spin)=gen_spin_help ('Define the number of this interface in module', 1,1024,1); - $type_box->pack_start($name_setting,FALSE,FALSE,0); - $type_spin->set_value($value); - $table->attach ($type_box, $positions[2], $positions[3], $row, $row+1,'expand','shrink',2,2); - $type_spin->signal_connect("value_changed"=>sub{ - my $wiget=shift; - my $num=$wiget->get_value_as_int(); - $ipgen->ipgen_add_plug($q,'num',$num); - set_gui_status($ipgen,'intfc_changed',0); - - }); - - } - $table->attach ($label_name, $positions[0], $positions[1], $row, $row+1,'expand','shrink',2,2); - $table->attach ($combo_type, $positions[1], $positions[2], $row, $row+1,'expand','shrink',2,2); - #$table->attach_defaults ($range_entry, 2, 4, $row, $row+1); - - #wishbone address seting - #print "$q eq 'wb_slave'\n"; - if($q eq 'wb_slave'){ - my ($saved_addr,$saved_width)=$ipgen->ipgen_get_wb_addr($q,0); - my $addr; - if(!defined $saved_addr){ - $addr= def_image_button('icons/warning.png'); - $addr->signal_connect ('clicked'=> sub{ - message_dialog("Wishbone slave address range has not been set yet! "); - - } ); - }else{ - $addr= def_image_button('icons/select.png'); - - } - $table->attach ($addr, $positions[5], $positions[6], $row, $row+1,'expand','shrink',2,2); - - - } - - - $row++; - } - - return add_widget_to_scrolled_win($table); - -} ######## -# get_intfc_setting +# get_intfc_setting ######## - sub get_intfc_setting{ - - my ($ipgen,$intfc_name, $intfc_type)=@_; - my $window = def_popwin_size(70,70,"Interface parameter setting",'percent'); - my $table=def_table(7,6,FALSE); - my $ok = def_image_button('icons/select.png','OK'); - - my $scrolled_win = add_widget_to_scrolled_win($table); - - #title - my $label1=gen_label_in_left("interface name"); - $table->attach ( $label1,0,2,0,1,'expand','shrink',2,2); - - - - - my ($type,$value); - if($intfc_type eq 'plug'){ - ($type,$value)= $ipgen->ipgen_get_plug($intfc_name); - }else { - ($type,$value)= $ipgen->ipgen_get_socket($intfc_name); - - } - if ($type ne 'num'){ $value=1;} - my $i=0; - for ( $i=0; $i < $value; $i++) { - #intfc name - my $saved_name; - my $number=$i; - if($intfc_type eq 'plug') {$saved_name= $ipgen->ipgen_get_plug_name($intfc_name,$number);} - else {$saved_name= $ipgen->ipgen_get_socket_name($intfc_name,$number);} - my $entry_name=gen_entry($saved_name); - - $table->attach($entry_name,0,2,$i+1,$i+2,'expand','shrink',2,2); - $ok->signal_connect('clicked'=>sub{ - my $new_name=$entry_name->get_text(); - #print "my new name is: $new_name\n"; - if($intfc_type eq 'plug'){ $ipgen->ipgen_set_plug_name($intfc_name,$number,$new_name); } - else { $ipgen->ipgen_set_socket_name($intfc_name,$number,$new_name);} - - }); - - - } - - - #wishbone addr - if($intfc_name eq 'wb_slave' && $intfc_type eq 'plug'){ - my $label2=gen_label_in_center("address range: (start end name)"); - my $label3=gen_label_help("This field defines the total memory_map address which is required by this module in byte. ( =2 ^ block_address_width). + my ($ipgen,$intfc_name, $intfc_type)=@_; + my $window = def_popwin_size(70,70,"Interface parameter setting",'percent'); + my $table=def_table(7,6,FALSE); + my $ok = def_image_button('icons/select.png','OK'); + my $scrolled_win = add_widget_to_scrolled_win($table); + #title + my $label1=gen_label_in_left("interface name"); + $table->attach ( $label1,0,2,0,1,'expand','shrink',2,2); + my ($type,$value); + if($intfc_type eq 'plug'){ + ($type,$value)= $ipgen->ipgen_get_plug($intfc_name); + }else { + ($type,$value)= $ipgen->ipgen_get_socket($intfc_name); + } + if ($type ne 'num'){ $value=1;} + my $i=0; + for ( $i=0; $i < $value; $i++) { + #intfc name + my $saved_name; + my $number=$i; + if($intfc_type eq 'plug') {$saved_name= $ipgen->ipgen_get_plug_name($intfc_name,$number);} + else {$saved_name= $ipgen->ipgen_get_socket_name($intfc_name,$number);} + my $entry_name=gen_entry($saved_name); + $table->attach($entry_name,0,2,$i+1,$i+2,'expand','shrink',2,2); + $ok->signal_connect('clicked'=>sub{ + my $new_name=$entry_name->get_text(); + #print "my new name is: $new_name\n"; + if($intfc_type eq 'plug'){ $ipgen->ipgen_set_plug_name($intfc_name,$number,$new_name); } + else { $ipgen->ipgen_set_socket_name($intfc_name,$number,$new_name);} + }); + } + #wishbone addr + if($intfc_name eq 'wb_slave' && $intfc_type eq 'plug'){ + my $label2=gen_label_in_center("address range: (start end name)"); + my $label3=gen_label_help("This field defines the total memory_map address which is required by this module in byte. ( =2 ^ block_address_width). You can define a fixed value or assign it to any of module parameter","block address width"); - - $table->attach ( $label2,2,5,0,1,'expand','shrink',2,2); - $table->attach ( $label3,5,6,0,1,'expand','shrink',2,2); - - my $plug=$intfc_name; - my $wb= wb_addr->wb_addr_new(); - my @ip_names=$wb->wb_list_names(); - my @list; - foreach my $p(@ip_names){ - my($start,$end,$cashed,$size)=$wb->wb_get_addr_info($p); - push (@list,"$start\t$end\t\t$p"); - - } - - my ($type,$value,$connection_num)=$ipgen->ipgen_get_plug($plug); - $i=0; - - for ( $i=0; $i < $value; $i++) { - my ($saved_addr,$saved_width)=$ipgen->ipgen_get_wb_addr($plug,$i); - my $num=$i; - my $pos; - if(!defined $saved_addr){ - $pos=0; - $saved_width=1; - $ipgen->ipgen_save_wb_addr($plug,$num,$list[0],1); - } - else{ - $pos= get_scolar_pos($saved_addr,@list); - } - - my $name_combo=gen_combo(\@list,$pos); - my $sbox=def_hbox(FALSE,0); - my $widget; - my $size_lab; - my @l=("Fixed","Parameterizable"); - - if(!defined $saved_width){ - $pos=0; - $saved_width=1; - - } - else{ - if(is_integer($saved_width)){ - $pos= 0; - $widget=gen_spin(1,31,1); - $widget->set_value($saved_width); - my $d=2**$saved_width; - $size_lab=gen_label_in_left(metric_conversion($d). " Bytes"); - } else{ - $pos= 1; - my @parameters=$ipgen->ipgen_get_all_parameters_list(); - my $p=get_scolar_pos($saved_width,@parameters); - - $widget=gen_combo(\@parameters, $p); - $size_lab=gen_label_in_left(" "); - - } - - - } - - - - my $comb=gen_combo(\@l, $pos); - #$widget->set_value($saved_width); - $sbox->pack_start($comb,FALSE,FALSE,3); - $sbox->pack_end($widget,FALSE,FALSE,3); - $sbox->pack_end($size_lab,FALSE,FALSE,3); - $comb->signal_connect('changed'=>sub{ - my $condition=$comb->get_active_text(); - $widget->destroy; - $size_lab->destroy; - my @parameters=$ipgen->ipgen_get_all_parameters_list(); - $widget=($condition eq "Fixed" )? gen_spin(1,31,1):gen_combo(\@parameters, 0); - $size_lab=($condition eq "Fixed" )? gen_label_in_left("2 Bytes"): gen_label_in_left(" "); - $sbox->pack_end($widget,FALSE,FALSE,3); - $sbox->pack_end($size_lab,FALSE,FALSE,3); - $sbox->show_all(); - $widget->signal_connect('changed'=>sub{ - $size_lab->destroy; - my $in=$comb->get_active_text(); - my $width=($in eq "Fixed" )? $widget->get_value_as_int(): $widget->get_active_text() ; - my $d=($in eq "Fixed" )? 2**$width:0; - - $size_lab=($in eq "Fixed" )? gen_label_in_left( metric_conversion($d). " Bytes"):gen_label_in_left(" "); - $sbox->pack_end($size_lab,FALSE,FALSE,3); - $sbox->show_all(); - }); - }); - $widget->signal_connect('changed'=>sub{ - $size_lab->destroy; - my $in=$comb->get_active_text(); - my $width=($in eq "Fixed" )? $widget->get_value_as_int(): $widget->get_active_text() ; - my $d=($in eq "Fixed" )? 2**$width:0; - - $size_lab=($in eq "Fixed" )? gen_label_in_left(metric_conversion($d). " Bytes"):gen_label_in_left(" "); - $sbox->pack_end($size_lab,FALSE,FALSE,3); - $sbox->show_all(); - }); - - $table->attach ($name_combo,2,5,$i+1,$i+2 ,'expand','shrink',2,2); - $table->attach ($sbox,5,6,$i+1,$i+2,'expand','shrink',2,2); - $ok->signal_connect('clicked'=>sub{ - my $addr=$name_combo->get_active_text(); - my $in=$comb->get_active_text(); - my $width=($in eq "Fixed" )? $widget->get_value_as_int(): $widget->get_active_text() ; - $ipgen->ipgen_save_wb_addr($plug,$num,$addr,$width); - - }); - - - } - - - - } - - - - - - my $mtable = def_table(10, 1, FALSE); - $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable->attach($ok,0,1,9,10,'expand','shrink',2,2); - - $window->add ($mtable); - $window->show_all(); - - - - - $ok->signal_connect('clicked'=>sub{ - $window->destroy; - set_gui_status($ipgen,"interface_selected",1); - - } ); - - - - + $table->attach ( $label2,2,5,0,1,'expand','shrink',2,2); + $table->attach ( $label3,5,6,0,1,'expand','shrink',2,2); + my $plug=$intfc_name; + my $wb= wb_addr->wb_addr_new(); + my @ip_names=$wb->wb_list_names(); + my @list; + foreach my $p(@ip_names){ + my($start,$end,$cashed,$size)=$wb->wb_get_addr_info($p); + push (@list,"$start\t$end\t\t$p"); + } + my ($type,$value,$connection_num)=$ipgen->ipgen_get_plug($plug); + $i=0; + for ( $i=0; $i < $value; $i++) { + my ($saved_addr,$saved_width)=$ipgen->ipgen_get_wb_addr($plug,$i); + my $num=$i; + my $pos; + if(!defined $saved_addr){ + $pos=0; + $saved_width=1; + $ipgen->ipgen_save_wb_addr($plug,$num,$list[0],1); + } + else{ + $pos= get_scolar_pos($saved_addr,@list); + } + my $name_combo=gen_combo(\@list,$pos); + my $sbox=def_hbox(FALSE,0); + my $widget; + my $size_lab; + my @l=("Fixed","Parameterizable"); + if(!defined $saved_width){ + $pos=0; + $saved_width=1; + } + else{ + if(is_integer($saved_width)){ + $pos= 0; + $widget=gen_spin(1,31,1); + $widget->set_value($saved_width); + my $d=2**$saved_width; + $size_lab=gen_label_in_left(metric_conversion($d). " Bytes"); + } else{ + $pos= 1; + my @parameters=$ipgen->ipgen_get_all_parameters_list(); + my $p=get_scolar_pos($saved_width,@parameters); + $widget=gen_combo(\@parameters, $p); + $size_lab=gen_label_in_left(" "); + } + } + my $comb=gen_combo(\@l, $pos); + #$widget->set_value($saved_width); + $sbox->pack_start($comb,FALSE,FALSE,3); + $sbox->pack_end($widget,FALSE,FALSE,3); + $sbox->pack_end($size_lab,FALSE,FALSE,3); + $comb->signal_connect('changed'=>sub{ + my $condition=$comb->get_active_text(); + $widget->destroy; + $size_lab->destroy; + my @parameters=$ipgen->ipgen_get_all_parameters_list(); + $widget=($condition eq "Fixed" )? gen_spin(1,31,1):gen_combo(\@parameters, 0); + $size_lab=($condition eq "Fixed" )? gen_label_in_left("2 Bytes"): gen_label_in_left(" "); + $sbox->pack_end($widget,FALSE,FALSE,3); + $sbox->pack_end($size_lab,FALSE,FALSE,3); + $sbox->show_all(); + $widget->signal_connect('changed'=>sub{ + $size_lab->destroy; + my $in=$comb->get_active_text(); + my $width=($in eq "Fixed" )? $widget->get_value_as_int(): $widget->get_active_text() ; + my $d=($in eq "Fixed" )? 2**$width:0; + $size_lab=($in eq "Fixed" )? gen_label_in_left( metric_conversion($d). " Bytes"):gen_label_in_left(" "); + $sbox->pack_end($size_lab,FALSE,FALSE,3); + $sbox->show_all(); + }); + }); + $widget->signal_connect('changed'=>sub{ + $size_lab->destroy; + my $in=$comb->get_active_text(); + my $width=($in eq "Fixed" )? $widget->get_value_as_int(): $widget->get_active_text() ; + my $d=($in eq "Fixed" )? 2**$width:0; + $size_lab=($in eq "Fixed" )? gen_label_in_left(metric_conversion($d). " Bytes"):gen_label_in_left(" "); + $sbox->pack_end($size_lab,FALSE,FALSE,3); + $sbox->show_all(); + }); + $table->attach ($name_combo,2,5,$i+1,$i+2 ,'expand','shrink',2,2); + $table->attach ($sbox,5,6,$i+1,$i+2,'expand','shrink',2,2); + $ok->signal_connect('clicked'=>sub{ + my $addr=$name_combo->get_active_text(); + my $in=$comb->get_active_text(); + my $width=($in eq "Fixed" )? $widget->get_value_as_int(): $widget->get_active_text() ; + $ipgen->ipgen_save_wb_addr($plug,$num,$addr,$width); + }); + } + } + my $mtable = def_table(10, 1, FALSE); + $mtable->attach_defaults($scrolled_win,0,1,0,9); + $mtable->attach($ok,0,1,9,10,'expand','shrink',2,2); + $window->add ($mtable); + $window->show_all(); + $ok->signal_connect('clicked'=>sub{ + $window->destroy; + set_gui_status($ipgen,"interface_selected",1); + } ); } - - - - - ############# # add_intfc_to_ip ############## - - sub add_intfc_to_ip{ - my ($intfc,$ipgen,$infc_name,$infc_type,$info)=@_; - if($infc_type eq 'socket'){ - my ($connection_num,$connect_to)=$intfc->get_socket($infc_name); - $ipgen->ipgen_add_soket($infc_name,'num',1,$connection_num); - } - else { $ipgen->ipgen_add_plug($infc_name,'num',1);} - set_gui_status($ipgen,"interface_selected",1); - -} - + my ($intfc,$ipgen,$infc_name,$infc_type,$info)=@_; + if($infc_type eq 'socket'){ + my ($connection_num,$connect_to)=$intfc->get_socket($infc_name); + $ipgen->ipgen_add_soket($infc_name,'num',1,$connection_num); + } + else { $ipgen->ipgen_add_plug($infc_name,'num',1);} + set_gui_status($ipgen,"interface_selected",1); +} sub add_plug_interface_from_tree{ - my ($ipgen,$category,$infc_name,$info)=@_; - $ipgen->ipgen_add_plug($infc_name,'num',1); - set_gui_status($ipgen,"interface_selected",1); + my ($ipgen,$category,$infc_name,$info)=@_; + $ipgen->ipgen_add_plug($infc_name,'num',1); + set_gui_status($ipgen,"interface_selected",1); } sub show_interface_description { - my ($soc,$category,$infc_name,$info)=@_; - my $intfc=interface->interface_new(); - my $describ=$intfc->get_description($category,$infc_name); - if($describ){ - show_info($info,$describ); - } - undef $intfc; + my ($soc,$category,$infc_name,$info)=@_; + my $intfc=interface->interface_new(); + my $describ=$intfc->get_description($category,$infc_name); + if($describ){ + show_info($info,$describ); + } + undef $intfc; } ################# -# get_list_of_all_interfaces +# get_list_of_all_interfaces ################ - sub get_list_of_all_interfaces{ - my ($ipgen)=@_; - my @sockets =$ipgen->ipgen_list_sokets(); - my @plugs =$ipgen->ipgen_list_plugs(); - my @interfaces=('IO'); - my @interfaces_name=('IO'); - foreach my $p( @sockets){ - my ($type,$value)= $ipgen->ipgen_get_socket($p); - if($type eq 'num'){ - for(my $i=0; $i<$value; $i++){ - push(@interfaces,"socket:$p\[$i\]"); - my $socket_name=$ipgen->ipgen_get_socket_name($p,$i); - push(@interfaces_name,"socket:$socket_name"); - }#for - - }#if - else { - push(@interfaces,"socket:$p\[array\]"); - my $socket_name=$ipgen->ipgen_get_socket_name($p,0); - push(@interfaces_name,"socket:$socket_name"); - - - }#else - - }#foreach - foreach my $p( @plugs){ - my ($type,$value)= $ipgen->ipgen_get_plug($p); - if($type eq 'num'){ - for(my $i=0; $i<$value; $i++){ - push(@interfaces,"plug:$p\[$i\]"); - my $plug_name=$ipgen->ipgen_get_plug_name($p,$i); - push(@interfaces_name,"plug:$plug_name"); - - }#for - - }#if - else { - my $plug_name=$ipgen->ipgen_get_plug_name($p,0); - push(@interfaces,"plug:$p\[array\]"); - push(@interfaces_name,"plug:$plug_name"); - - - }#else - - }#foreach - return (\@interfaces_name,\@interfaces); - -} + my ($ipgen)=@_; + my @sockets =$ipgen->ipgen_list_sokets(); + my @plugs =$ipgen->ipgen_list_plugs(); + my @interfaces=('IO'); + my @interfaces_name=('IO'); + foreach my $p( @sockets){ + my ($type,$value)= $ipgen->ipgen_get_socket($p); + if($type eq 'num'){ + for(my $i=0; $i<$value; $i++){ + push(@interfaces,"socket:$p\[$i\]"); + my $socket_name=$ipgen->ipgen_get_socket_name($p,$i); + push(@interfaces_name,"socket:$socket_name"); + }#for + }#if + else { + push(@interfaces,"socket:$p\[array\]"); + my $socket_name=$ipgen->ipgen_get_socket_name($p,0); + push(@interfaces_name,"socket:$socket_name"); + }#else + }#foreach + foreach my $p( @plugs){ + my ($type,$value)= $ipgen->ipgen_get_plug($p); + if($type eq 'num'){ + for(my $i=0; $i<$value; $i++){ + push(@interfaces,"plug:$p\[$i\]"); + my $plug_name=$ipgen->ipgen_get_plug_name($p,$i); + push(@interfaces_name,"plug:$plug_name"); + }#for + }#if + else { + my $plug_name=$ipgen->ipgen_get_plug_name($p,0); + push(@interfaces,"plug:$p\[array\]"); + push(@interfaces_name,"plug:$plug_name"); + }#else + }#foreach + return (\@interfaces_name,\@interfaces); +} sub gen_intfc_port_combo{ - my ($intfc,$ipgen,$intfc_name,$porttype,$portname)=@_; - - my($type,$name,$num)= split("[:\[ \\]]", $intfc_name); - my @all_ports; - my @ports; - - if($type eq 'socket'){ - @all_ports= $intfc->get_socket_port_list($name); - foreach my $p(@all_ports){ - my ($r,$t,$c)=$intfc->get_port_info_of_socket($name,$p); - if ($t eq $porttype){ push (@ports,$p);} - } - - }elsif($type eq 'plug'){ - @all_ports= $intfc->get_plug_port_list($name); - - foreach my $p(@all_ports){ - my ($r,$t,$c)=$intfc->get_port_info_of_plug($name,$p); - #print "($t eq $porttype)\n"; - if ($t eq $porttype){ push (@ports,$p);} - } - - } - else { - @ports=('IO','NC'); - } - my $saved_intfc_port=$ipgen->ipgen_get_port_intfc_port($portname); - my $pos=(defined $saved_intfc_port ) ? get_scolar_pos( $saved_intfc_port,@ports) : undef; - if (!defined $pos){ - $pos=find_the_most_similar_position( $portname ,@ports); - $ipgen->ipgen_set_port_intfc_port($portname,$ports[$pos]); - #print "$ports[$pos]\n;" - } - my $intfc_port_combo=gen_combo(\@ports,$pos); - $intfc_port_combo->signal_connect('changed'=> sub { - my $intfc_port=$intfc_port_combo->get_active_text(); - $ipgen->ipgen_set_port_intfc_port($portname,$intfc_port); - - }); - - - return $intfc_port_combo; + my ($intfc,$ipgen,$intfc_name,$porttype,$portname)=@_; + my($type,$name,$num)= split("[:\[ \\]]", $intfc_name); + my @all_ports; + my @ports; + if($type eq 'socket'){ + @all_ports= $intfc->get_socket_port_list($name); + foreach my $p(@all_ports){ + my ($r,$t,$c)=$intfc->get_port_info_of_socket($name,$p); + if ($t eq $porttype){ push (@ports,$p);} + } + }elsif($type eq 'plug'){ + @all_ports= $intfc->get_plug_port_list($name); + foreach my $p(@all_ports){ + my ($r,$t,$c)=$intfc->get_port_info_of_plug($name,$p); + #print "($t eq $porttype)\n"; + if ($t eq $porttype){ push (@ports,$p);} + } + } + else { + @ports=('IO','NC'); + } + my $saved_intfc_port=$ipgen->ipgen_get_port_intfc_port($portname); + my $pos=(defined $saved_intfc_port ) ? get_scolar_pos( $saved_intfc_port,@ports) : undef; + if (!defined $pos){ + $pos=find_the_most_similar_position( $portname ,@ports); + $ipgen->ipgen_set_port_intfc_port($portname,$ports[$pos]); + #print "$ports[$pos]\n;" + } + my $intfc_port_combo=gen_combo(\@ports,$pos); + $intfc_port_combo->signal_connect('changed'=> sub { + my $intfc_port=$intfc_port_combo->get_active_text(); + $ipgen->ipgen_set_port_intfc_port($portname,$intfc_port); + }); + return $intfc_port_combo; } - - sub port_info_box { - my($intfc,$ipgen,$info)=@_; - my $table=def_table(8,10,FALSE); - my @ports=$ipgen->ipgen_list_ports; - my $row=0; - my ($name_ref,$ref)=get_list_of_all_interfaces($ipgen); - my @interfaces_name=@{$name_ref}; - my @interfaces=@{$ref}; - #print "@interfaces_name\n"; - - $table->attach (gen_label_in_left(" Type "), 0, 1, $row, $row+1,'expand','shrink',2,2); - $table->attach (gen_label_in_left(" Port name "), 1, 3, $row, $row+1,'expand','shrink',2,2); - $table->attach (gen_label_in_left(" Interface name "), 3, 5, $row, $row+1,'expand','shrink',2,2); - $table->attach (gen_label_in_center(" Interface port "), 5, 7, $row, $row+1,'fill','shrink',2,2); - $table->attach (gen_label_in_left(" Port Range "), 7, 9, $row, $row+1,'expand','shrink',2,2); - $row++; - #print @interfaces; - my @ports_order=$ipgen->ipgen_get_ports_order(); - if(scalar(@ports_order) >1 ){ @ports= @ports_order} - - - - - foreach my $p( @ports){ - my ($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($p); - #my $label_name=gen_label_in_left(" $p "); - my $name_entry=gen_label_in_left($p); - my $label_type=gen_label_in_left(" $type "); - my $range_entry=gen_entry($range); - my $pos=(defined $intfc_name ) ? get_scolar_pos( $intfc_name,@interfaces) : 0; - if (!defined $pos){ - $pos=0; - $ipgen->ipgen_set_port_intfc_name($p,'IO'); - }; - my $intfc_name_combo=gen_combo(\@interfaces_name,$pos); - my $intfc_port_combo=gen_intfc_port_combo($intfc,$ipgen,$intfc_name,$type,$p); - - - $table->attach ($label_type, 0, 1, $row, $row+1,'expand','shrink',2,2); - $table->attach ($name_entry, 1, 3, $row, $row+1,'expand','shrink',2,2); - $table->attach ($intfc_name_combo,3, 5, $row, $row+1,'expand','shrink',2,2); - $table->attach ($intfc_port_combo, 5, 7, $row, $row+1,'fill','shrink',2,2); - $table->attach ($range_entry ,7, 9, $row, $row+1,'fill','shrink',2,2); - - $intfc_name_combo->signal_connect('changed'=>sub{ - my $intfc_name=$intfc_name_combo->get_active_text(); - my $pos= get_scolar_pos( $intfc_name,@interfaces_name); - #my($type,$name,$num)= split("[:\[ \\]]", $intfc_name); - #print "$type,$name,$num\n"; - $ipgen->ipgen_set_port_intfc_name($p,$interfaces[$pos]); - set_gui_status($ipgen,"interface_selected",1); - }); - $range_entry->signal_connect('changed'=>sub{ - my $new_range=$range_entry->get_text(); - $ipgen->ipgen_add_port($p,$new_range,$type,$intfc_name,$intfc_port); - }); - - $row++; - } - - - - - return add_widget_to_scrolled_win($table); - - + my($intfc,$ipgen,$info)=@_; + my $table=def_table(8,10,FALSE); + my @ports=$ipgen->ipgen_list_ports; + my $row=0; + my ($name_ref,$ref)=get_list_of_all_interfaces($ipgen); + my @interfaces_name=@{$name_ref}; + my @interfaces=@{$ref}; + #print "@interfaces_name\n"; + $table->attach (gen_label_in_left(" Type "), 0, 1, $row, $row+1,'expand','shrink',2,2); + $table->attach (gen_label_in_left(" Port name "), 1, 3, $row, $row+1,'expand','shrink',2,2); + $table->attach (gen_label_in_left(" Interface name "), 3, 5, $row, $row+1,'expand','shrink',2,2); + $table->attach (gen_label_in_center(" Interface port "), 5, 7, $row, $row+1,'fill','shrink',2,2); + $table->attach (gen_label_in_left(" Port Range "), 7, 9, $row, $row+1,'expand','shrink',2,2); + $row++; + #print @interfaces; + my @ports_order=$ipgen->ipgen_get_ports_order(); + if(scalar(@ports_order) >1 ){ @ports= @ports_order} + foreach my $p( @ports){ + my ($range,$type,$intfc_name,$intfc_port)=$ipgen->ipgen_get_port($p); + #my $label_name=gen_label_in_left(" $p "); + my $name_entry=gen_label_in_left($p); + my $label_type=gen_label_in_left(" $type "); + my $range_entry=gen_entry($range); + my $pos=(defined $intfc_name ) ? get_scolar_pos( $intfc_name,@interfaces) : 0; + if (!defined $pos){ + $pos=0; + $ipgen->ipgen_set_port_intfc_name($p,'IO'); + }; + my $intfc_name_combo=gen_combo(\@interfaces_name,$pos); + my $intfc_port_combo=gen_intfc_port_combo($intfc,$ipgen,$intfc_name,$type,$p); + $table->attach ($label_type, 0, 1, $row, $row+1,'expand','shrink',2,2); + $table->attach ($name_entry, 1, 3, $row, $row+1,'expand','shrink',2,2); + $table->attach ($intfc_name_combo,3, 5, $row, $row+1,'expand','shrink',2,2); + $table->attach ($intfc_port_combo, 5, 7, $row, $row+1,'fill','shrink',2,2); + $table->attach ($range_entry ,7, 9, $row, $row+1,'fill','shrink',2,2); + $intfc_name_combo->signal_connect('changed'=>sub{ + my $intfc_name=$intfc_name_combo->get_active_text(); + my $pos= get_scolar_pos( $intfc_name,@interfaces_name); + #my($type,$name,$num)= split("[:\[ \\]]", $intfc_name); + #print "$type,$name,$num\n"; + $ipgen->ipgen_set_port_intfc_name($p,$interfaces[$pos]); + set_gui_status($ipgen,"interface_selected",1); + }); + $range_entry->signal_connect('changed'=>sub{ + my $new_range=$range_entry->get_text(); + $ipgen->ipgen_add_port($p,$new_range,$type,$intfc_name,$intfc_port); + }); + $row++; + } + return add_widget_to_scrolled_win($table); } - sub write_ip{ - my $ipgen=shift; - my $name=$ipgen->ipgen_get("module_name"); - my $category=$ipgen->ipgen_get("category"); - my $ip_name= $ipgen->ipgen_get("ip_name"); - my $dir = Cwd::getcwd(); - - #Increase IP version - my $v=$ipgen->object_get_attribute("version",undef); - $v = 0 if(!defined $v); - $v++; - $ipgen->object_add_attribute("version",undef,$v); - #print "$v\n"; - - # Write - mkpath("$dir/lib/ip/$category/",1,01777); - open(FILE, ">lib/ip/$category/$ip_name.IP") || die "Can not open: $!"; - print FILE perl_file_header("$ip_name.IP"); - print FILE Data::Dumper->Dump([\%$ipgen],["ipgen"]); - close(FILE) || die "Error closing file: $!"; - my $message="IP $ip_name has been generated successfully. In order to see the generated IP in processing tile generator you need to reset the ProNoC. Do you want to reset the ProNoC now?" ; - - my $response = yes_no_dialog($message); - if ($response eq 'yes') { - exec($^X, $0, @ARGV);# reset ProNoC to apply changes - } + my $ipgen=shift; + my $name=$ipgen->ipgen_get("module_name"); + my $category=$ipgen->ipgen_get("category"); + my $ip_name= $ipgen->ipgen_get("ip_name"); + my $dir = Cwd::getcwd(); + #Increase IP version + my $v=$ipgen->object_get_attribute("version",undef); + $v = 0 if(!defined $v); + $v++; + $ipgen->object_add_attribute("version",undef,$v); + #print "$v\n"; + # Write + mkpath("$dir/lib/ip/$category/",1,01777); + open(FILE, ">lib/ip/$category/$ip_name.IP") || die "Can not open: $!"; + print FILE perl_file_header("$ip_name.IP"); + print FILE Data::Dumper->Dump([\%$ipgen],["ipgen"]); + close(FILE) || die "Error closing file: $!"; + my $message="IP $ip_name has been generated successfully. In order to see the generated IP in processing tile generator you need to reset the ProNoC. Do you want to reset the ProNoC now?" ; + my $response = yes_no_dialog($message); + if ($response eq 'yes') { + exec($^X, $0, @ARGV);# reset ProNoC to apply changes + } } - - sub generate_ip{ - my $ipgen=shift; - my $name=$ipgen->ipgen_get("module_name"); - my $category=$ipgen->ipgen_get("category"); - my $ip_name= $ipgen->ipgen_get("ip_name"); - my $dir = Cwd::getcwd(); - - - - #check if name has been set - if(defined ($name) && defined ($category)){ - if (!defined $ip_name) {$ip_name= $name} - my $error = check_verilog_identifier_syntax($ip_name); - if ( defined $error ){ - message_dialog("The IP name \"$ip_name\" is given with an unacceptable formatting. This name will be used as a verilog module name so it must follow Verilog identifier declaration formatting:\n $error"); - return ; - } - - - - #check if any source file has been added for this ip - my @l=$ipgen->ipgen_get_list("hdl_files"); - if( scalar @l ==0){ - my $mwindow; - my $response = yes_no_dialog("No HDL library file has been set for this IP. Do you want to generate this IP?"); - - if ($response eq 'yes') { - write_ip($ipgen); - } - - }else{ - write_ip($ipgen); - } - }else{ - my $message; - if(!defined ($name)){ $message="Input file has not been selected yet.\nNothing has been generated!";} - elsif(!defined ($category)){ $message="Category must be defined!" ;} - message_dialog($message); - - } + my $ipgen=shift; + my $name=$ipgen->ipgen_get("module_name"); + my $category=$ipgen->ipgen_get("category"); + my $ip_name= $ipgen->ipgen_get("ip_name"); + my $dir = Cwd::getcwd(); + #check if name has been set + if(defined ($name) && defined ($category)){ + if (!defined $ip_name) {$ip_name= $name} + my $error = check_verilog_identifier_syntax($ip_name); + if ( defined $error ){ + message_dialog("The IP name \"$ip_name\" is given with an unacceptable formatting. This name will be used as a verilog module name so it must follow Verilog identifier declaration formatting:\n $error"); + return ; + } + #check if any source file has been added for this ip + my @l=$ipgen->ipgen_get_list("hdl_files"); + if( scalar @l ==0){ + my $mwindow; + my $response = yes_no_dialog("No HDL library file has been set for this IP. Do you want to generate this IP?"); + if ($response eq 'yes') { + write_ip($ipgen); + } + }else{ + write_ip($ipgen); + } + }else{ + my $message; + if(!defined ($name)){ $message="Input file has not been selected yet.\nNothing has been generated!";} + elsif(!defined ($category)){ $message="Category must be defined!" ;} + message_dialog($message); + } #$hashref = retrieve('file'); - - - -return 1; -} - - - +return 1; +} ######### -# load_ip +# load_ip ######## - sub load_ip{ - my ($ipgen)=@_; - my $file; - my $dialog = gen_file_dialog (undef, 'IP'); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/ip"); - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.IP'){ - $ipgen->ipgen_add("file_name",$file); - set_gui_status($ipgen,"load_file",0); - } - } - $dialog->destroy; + my ($ipgen)=@_; + my $file; + my $dialog = gen_file_dialog (undef, 'IP'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/lib/ip"); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.IP'){ + $ipgen->ipgen_add("file_name",$file); + set_gui_status($ipgen,"load_file",0); + } + } + $dialog->destroy; } - - ############ -# get_source_file +# get_source_file ########### - - - sub get_source_file{ - my($ipgen,$info,$page,$title,$dest,$page_info_ref)=@_; - - - my $var_list='${parameter_name}: Verilog module parameter values. - + my($ipgen,$info,$page,$title,$dest,$page_info_ref)=@_; + my $var_list='${parameter_name}: Verilog module parameter values. ${CORE_ID} Each wishbone bus based SoC will have a unique CORE_ID that represents its location in NoC topology. CORE_ID=((y * number_of_nodes_in_x_ dimension) + x) where (x,y) are the node location in x and y axes. If the generated tile is used as top level module CORE_ID will take the default value of zero. - ${IP}: is the peripheral device instance name. - ${CORE}: is the peripheral device module name. - -${BASE}: is the wishbone base address(s) and will be added during soc generation to system.h. If more than one slave wishbone bus are used define them as ${BASE0}, ${BASE1}... . +${BASE}: is the wishbone base address(s) and will be added during soc generation to system.h. If more than one slave wishbone bus are used define them as ${BASE0}, ${BASE1}... . ' ; - my $var_help=gen_button_message($var_list,"icons/info.png","Global variables"); - - - my $window = def_popwin_size(75,75,$title,'percent'); - - my $notebook=source_notebook($ipgen,$info,$window,$page,$dest,$page_info_ref); - my $table=def_table (15, 15, FALSE); - - - $table->attach ($var_help, 5, 7, 0, 1,'expand','shrink',2,2); - $table->attach_defaults ($notebook , 0, 15, 1, 15); - - $window->add($table); - $window->show_all; - return $window; - + my $var_help=gen_button_message($var_list,"icons/info.png","Global variables"); + my $window = def_popwin_size(75,75,$title,'percent'); + my $notebook=source_notebook($ipgen,$info,$window,$page,$dest,$page_info_ref); + my $table=def_table (15, 15, FALSE); + $table->attach ($var_help, 5, 7, 0, 1,'expand','shrink',2,2); + $table->attach_defaults ($notebook , 0, 15, 1, 15); + $window->add($table); + $window->show_all; + return $window; } ########## # source_notebook ########## - sub source_notebook{ - my($ipgen,$info,$window,$page,$dest,$page_info_ref)=@_; - my $notebook = gen_notebook(); - my %page_info=%{$page_info_ref}; - foreach my $p (sort keys %page_info){ - my $page_ref; - $page_ref=get_file_folder($ipgen,$info,$window,$p,$page_info_ref) if($page_info{$p}{filed_type} eq "existing_file/folder"); - $page_ref=get_file_folder($ipgen,$info,$window,$p,$page_info_ref) if($page_info{$p}{filed_type} eq "file_with_variables"); - $page_ref=get_file_content($ipgen,$info,$window,$page_info{$p},$page_info_ref) if($page_info{$p}{filed_type} eq "file_content"); - $notebook->append_page ($page_ref,gen_label_with_mnemonic ($page_info{$p}{page_name})); - - } - $notebook->show_all; - $notebook->set_current_page($page) if(defined $page); - return $notebook; - + my($ipgen,$info,$window,$page,$dest,$page_info_ref)=@_; + my $notebook = gen_notebook(); + my %page_info=%{$page_info_ref}; + foreach my $p (sort keys %page_info){ + my $page_ref; + $page_ref=get_file_folder($ipgen,$info,$window,$p,$page_info_ref) if($page_info{$p}{filed_type} eq "existing_file/folder"); + $page_ref=get_file_folder($ipgen,$info,$window,$p,$page_info_ref) if($page_info{$p}{filed_type} eq "file_with_variables"); + $page_ref=get_file_content($ipgen,$info,$window,$page_info{$p},$page_info_ref) if($page_info{$p}{filed_type} eq "file_content"); + $notebook->append_page ($page_ref,gen_label_with_mnemonic ($page_info{$p}{page_name})); + } + $notebook->show_all; + $notebook->set_current_page($page) if(defined $page); + return $notebook; } ########## # get_file_folder ######### - sub get_file_folder{ - my ($ipgen,$info,$window,$page,$page_info_ref)=@_; - my %page_info=%{$page_info_ref}; - my @sw_dir = $ipgen->ipgen_get_list($page_info{$page}{filed_name}); - my $table = def_table (15, 15, FALSE); - my $help=gen_label_help($page_info{$page}{help}); - $table->attach ($help,0,2,0,1,'expand','shrink',2,2); - my $tick = $page_info{$page}{'tick'}; - my ($scrwin,$ok)=gen_file_list($ipgen,$page_info{$page}{filed_name},$window,$page_info{$page}{rename_file},$tick); - - my $label=gen_label_in_left("Select file(s):"); - my $brows=def_image_button("icons/browse.png",' Browse'); - $table->attach ($label,2,4,0,1,'expand','shrink',2,2); - $table->attach($brows,4,6,0,1,'expand','shrink',2,2); - - my $dir = Cwd::getcwd(); - my $project_dir = abs_path("$dir/../../"); #mpsoc directory address - - - $brows->signal_connect("clicked"=> sub { - my @files; - my $dialog = gen_file_dialog (undef); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/..") ; - $dialog->set_select_multiple(TRUE); - - if ( "ok" eq $dialog->run ) { - @files = get_filenames_from_dialog($dialog); - @sw_dir=$ipgen->ipgen_get_list($page_info{$page}{filed_name}); - foreach my $p (@files){ - #remove $project_dir form beginning of each file - $p =~ s/$project_dir//; - my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$"); - $p=$p.'frename_sep_t'.$name.$suffix if (defined $page_info{$page}{rename_file}); - if(! grep (/^$p$/,@sw_dir)){push(@sw_dir,$p)}; - } - $ipgen->ipgen_add($page_info{$page}{filed_name},\@sw_dir); - get_source_file($ipgen,$info,$page,"Add software file(s)","SW",$page_info_ref); - $window->destroy; - - } - $dialog->destroy; - } );# # ,\$entry); - - if($page_info{$page}{folder_en} eq 1){ - my $label2=gen_label_in_left("Select folder(s):"); - my $brows2=def_image_button("icons/browse.png",' Browse'); - $table->attach($label2,7,9,0,1,'expand','shrink',2,2); - $table->attach($brows2,9,11,0,1,'expand','shrink',2,2); - - $brows2->signal_connect("clicked"=> sub { - my @files; - my $dialog = gen_folder_dialog ('Select Folder(s)'); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/..") ; - $dialog->set_select_multiple(TRUE); - - if ( "ok" eq $dialog->run ) { - @files = get_filenames_from_dialog($dialog); - - @sw_dir=$ipgen->ipgen_get_list($page_info{$page}{filed_name}); - foreach my $p (@files){ - #remove $project_dir form beginning of each file - $p =~ s/$project_dir//; - if(! grep (/^$p$/,@sw_dir)){push(@sw_dir,$p)}; - - } - - $ipgen->ipgen_add($page_info{$page}{filed_name},\@sw_dir); - get_source_file($ipgen,$info,$page,"Add software file(s)","SW",$page_info_ref); - $window->destroy; - - - #$$entry_ref->set_text($file); - - #print "file = $file\n"; - } - $dialog->destroy; - - - - } );# # ,\$entry); - } - - - - - - - $table->attach_defaults($scrwin,0,15,1,14); - $table->attach($ok,6,9,14,15,'expand','shrink',2,2); - - return ($table) - - -} - - + my ($ipgen,$info,$window,$page,$page_info_ref)=@_; + my %page_info=%{$page_info_ref}; + my @sw_dir = $ipgen->ipgen_get_list($page_info{$page}{filed_name}); + my $table = def_table (15, 15, FALSE); + my $help=gen_label_help($page_info{$page}{help}); + $table->attach ($help,0,2,0,1,'expand','shrink',2,2); + my $tick = $page_info{$page}{'tick'}; + my ($scrwin,$ok)=gen_file_list($ipgen,$page_info{$page}{filed_name},$window,$page_info{$page}{rename_file},$tick); + my $label=gen_label_in_left("Select file(s):"); + my $brows=def_image_button("icons/browse.png",' Browse'); + $table->attach ($label,2,4,0,1,'expand','shrink',2,2); + $table->attach($brows,4,6,0,1,'expand','shrink',2,2); + my $dir = Cwd::getcwd(); + my $project_dir = abs_path("$dir/../../"); #mpsoc directory address + $brows->signal_connect("clicked"=> sub { + my @files; + my $dialog = gen_file_dialog (undef); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/..") ; + $dialog->set_select_multiple(TRUE); + if ( "ok" eq $dialog->run ) { + @files = get_filenames_from_dialog($dialog); + @sw_dir=$ipgen->ipgen_get_list($page_info{$page}{filed_name}); + foreach my $p (@files){ + #remove $project_dir form beginning of each file + $p =~ s/$project_dir//; + my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$"); + $p=$p.'frename_sep_t'.$name.$suffix if (defined $page_info{$page}{rename_file}); + if(! grep (/^$p$/,@sw_dir)){push(@sw_dir,$p)}; + } + $ipgen->ipgen_add($page_info{$page}{filed_name},\@sw_dir); + get_source_file($ipgen,$info,$page,"Add software file(s)","SW",$page_info_ref); + $window->destroy; + } + $dialog->destroy; + } );# # ,\$entry); + if($page_info{$page}{folder_en} eq 1){ + my $label2=gen_label_in_left("Select folder(s):"); + my $brows2=def_image_button("icons/browse.png",' Browse'); + $table->attach($label2,7,9,0,1,'expand','shrink',2,2); + $table->attach($brows2,9,11,0,1,'expand','shrink',2,2); + $brows2->signal_connect("clicked"=> sub { + my @files; + my $dialog = gen_folder_dialog ('Select Folder(s)'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/..") ; + $dialog->set_select_multiple(TRUE); + if ( "ok" eq $dialog->run ) { + @files = get_filenames_from_dialog($dialog); + @sw_dir=$ipgen->ipgen_get_list($page_info{$page}{filed_name}); + foreach my $p (@files){ + #remove $project_dir form beginning of each file + $p =~ s/$project_dir//; + if(! grep (/^$p$/,@sw_dir)){push(@sw_dir,$p)}; + } + $ipgen->ipgen_add($page_info{$page}{filed_name},\@sw_dir); + get_source_file($ipgen,$info,$page,"Add software file(s)","SW",$page_info_ref); + $window->destroy; + #$$entry_ref->set_text($file); + #print "file = $file\n"; + } + $dialog->destroy; + } );# # ,\$entry); + } + $table->attach_defaults($scrwin,0,15,1,14); + $table->attach($ok,6,9,14,15,'expand','shrink',2,2); + return ($table) +} ########### -# get_file_content +# get_file_content ######### - sub get_file_content{ - my ($ipgen,$info,$window,$page_info_ref)=@_; - my %page_info=%{$page_info_ref}; - #my $hdr = $ipgen->ipgen_get_hdr(); - my $hdr = $ipgen-> ipgen_get($page_info{filed_name}); - my $table = def_table (14, 15, FALSE); - my ($scrwin,$text_view)=create_txview(); - - my $help=gen_label_help($page_info{help}); - $table->attach ($help,0,8,0,1,'expand','shrink',2,2); - $table->attach_defaults($scrwin,0,15,1,14); - my $text_buffer = $text_view->get_buffer; - if(defined $hdr) {$text_buffer->set_text($hdr)}; - - my $ok=def_image_button("icons/select.png",' Save '); - $ok->signal_connect("clicked"=> sub {# - my $text = $text_buffer->get_text($text_buffer->get_bounds, TRUE); - $ipgen->ipgen_add($page_info{filed_name},$text); - $window->destroy; - - }); - - $table->attach($ok,6,7,14,15,'expand','shrink',2,2); - return ($table); - -} - - - - - - - - - - - - - - - + my ($ipgen,$info,$window,$page_info_ref)=@_; + my %page_info=%{$page_info_ref}; + #my $hdr = $ipgen->ipgen_get_hdr(); + my $hdr = $ipgen-> ipgen_get($page_info{filed_name}); + my $table = def_table (14, 15, FALSE); + my ($scrwin,$text_view)=create_txview(); + my $help=gen_label_help($page_info{help}); + $table->attach ($help,0,8,0,1,'expand','shrink',2,2); + $table->attach_defaults($scrwin,0,15,1,14); + my $text_buffer = $text_view->get_buffer; + if(defined $hdr) {$text_buffer->set_text($hdr)}; + my $ok=def_image_button("icons/select.png",' Save '); + $ok->signal_connect("clicked"=> sub {# + my $text = $text_buffer->get_text($text_buffer->get_bounds, TRUE); + $ipgen->ipgen_add($page_info{filed_name},$text); + $window->destroy; + }); + $table->attach($ok,6,7,14,15,'expand','shrink',2,2); + return ($table); +} ############ -# get_unused_intfc_ports_list +# get_unused_intfc_ports_list ########### - sub get_unused_intfc_ports_list { - my($intfc,$ipgen,$info)=@_; - my @ports=$ipgen->ipgen_list_ports; - my ($name_ref,$ref)=get_list_of_all_interfaces($ipgen); - my @interfaces_name=@{$name_ref}; - my @interfaces=@{$ref}; - $ipgen->ipgen_remove("unused"); - foreach my $intfc_name (@interfaces) - { - #print "$intfc_name\n"; - my($type,$name,$num)= split("[:\[ \\]]", $intfc_name); - my @all_ports; - if($type eq 'socket'){ - @all_ports= $intfc->get_socket_port_list($name); - - }elsif($type eq 'plug'){ - @all_ports= $intfc->get_plug_port_list($name); - } - foreach my $p(@all_ports){ - my $r= check_intfc_port_exits($intfc,$ipgen,$info,$intfc_name,$p); - if ($r eq "0"){ - $ipgen->ipgen_add_unused_intfc_port( $intfc_name,$p ); - } - - } - - } + my($intfc,$ipgen,$info)=@_; + my @ports=$ipgen->ipgen_list_ports; + my ($name_ref,$ref)=get_list_of_all_interfaces($ipgen); + my @interfaces_name=@{$name_ref}; + my @interfaces=@{$ref}; + $ipgen->ipgen_remove("unused"); + foreach my $intfc_name (@interfaces) + { + #print "$intfc_name\n"; + my($type,$name,$num)= split("[:\[ \\]]", $intfc_name); + my @all_ports; + if($type eq 'socket'){ + @all_ports= $intfc->get_socket_port_list($name); + }elsif($type eq 'plug'){ + @all_ports= $intfc->get_plug_port_list($name); + } + foreach my $p(@all_ports){ + my $r= check_intfc_port_exits($intfc,$ipgen,$info,$intfc_name,$p); + if ($r eq "0"){ + $ipgen->ipgen_add_unused_intfc_port( $intfc_name,$p ); + } + } + } } sub check_intfc_port_exits{ - my($intfc,$ipgen,$info,$intfc_name,$intfc_port)=@_; - my @ports=$ipgen->ipgen_list_ports; - - - my $result="0"; - foreach my $p( @ports){ - my ($range,$type,$assigned_intfc_name,$assigned_intfc_port)=$ipgen->ipgen_get_port($p); - #print "if($intfc_name eq $assigned_intfc_name && $intfc_port eq $assigned_intfc_port);\n"; - - if($intfc_name eq $assigned_intfc_name && $intfc_port eq $assigned_intfc_port){ - if($result eq "1"){# one interface port has been connected to multiple IP port - - } - $result = "1"; - - } - } - return $result; - + my($intfc,$ipgen,$info,$intfc_name,$intfc_port)=@_; + my @ports=$ipgen->ipgen_list_ports; + my $result="0"; + foreach my $p( @ports){ + my ($range,$type,$assigned_intfc_name,$assigned_intfc_port)=$ipgen->ipgen_get_port($p); + #print "if($intfc_name eq $assigned_intfc_name && $intfc_port eq $assigned_intfc_port);\n"; + if($intfc_name eq $assigned_intfc_name && $intfc_port eq $assigned_intfc_port){ + if($result eq "1"){# one interface port has been connected to multiple IP port + } + $result = "1"; + } + } + return $result; } - - - - - - - - - - - - - - - - ############ # main ############ sub ipgen_main{ - my $ipgen=shift; - my $intfc=interface->interface_new(); - if(!defined $ipgen) { $ipgen=ip_gen->ip_gen_new();} - set_gui_status($ipgen,"ideal",0); - - # The main table containing the lib tree, selected modules and info section - my $main_table = def_table (15, 12, FALSE); - - - - - # The box which holds the info, warning, error ... mesages - my ($infobox,$info)= create_txview(); - my $generate = def_image_button('icons/gen.png','Generate'); - - - # A tree view for holding a library - my %tree_text; - my @categories= $intfc->get_categories(); - foreach my $p (@categories) - { - my @intfc_names= $intfc->get_intfcs_of_category($p); - $tree_text{$p}=\@intfc_names; - - } - - - my $tree_box = create_tree ($ipgen,'Interfaces list',$info,\%tree_text,\&show_interface_description ,\&add_plug_interface_from_tree); - - - my $file_info=file_info_box($ipgen,$info); - my $port_info=port_info_box($intfc,$ipgen,$info); - my $intfc_info=interface_info_box($intfc,$ipgen,$info); - - - my $open = def_image_button('icons/browse.png','Load IP'); - - - $main_table->set_row_spacings (4); - $main_table->set_col_spacings (1); - - - - - #$table->attach_defaults ($event_box, $col, $col+1, $row, $row+1); - - my $v1=gen_vpaned($file_info,.2,$intfc_info); - my $v2=gen_vpaned($v1,.4,$port_info); - my $h1=gen_hpaned($tree_box,.15,$v2); - my $v3=gen_vpaned($h1,.6,$infobox); - - - $main_table->attach_defaults ($v3, 0, 12, 0,14); - $main_table->attach ($generate, 6, 8, 14,15,'expand','shrink',2,2); - $main_table->attach ($open,0, 1, 14,15,'expand','shrink',2,2); - - #check soc status every 0.5 second. refresh device table if there is any changes -Glib::Timeout->add (100, sub{ - - my ($state,$timeout)= get_gui_status($ipgen); - if($state eq "load_file"){ - my $file=$ipgen->ipgen_get("file_name"); - my ($pp,$r,$err) = regen_object($file); - if ($r){ - add_colored_info($info,"**Error reading $file file: $err\n",'red'); - - return; - } - clone_obj($ipgen,$pp); - show_info($info,"$file is loaded!\n "); - set_gui_status($ipgen,"ref",1); - - - }elsif ($timeout>0){ - $timeout--; - set_gui_status($ipgen,$state,$timeout); - } - elsif( $state eq "change_parameter" ){ - get_parameter_setting($ipgen,$info); - set_gui_status($ipgen,"ideal",0); - - - - } - elsif( $state ne "ideal" ){ - $file_info->destroy; - $port_info->destroy; - $intfc_info->destroy; - $file_info=file_info_box($ipgen,$info); - $port_info=port_info_box($intfc,$ipgen,$info); - $intfc_info=interface_info_box($intfc,$ipgen,$info); - - $v1 -> pack1($file_info, TRUE, TRUE); - $v1 -> pack2($intfc_info, TRUE, TRUE); - $v2 -> pack2($port_info, TRUE, TRUE); - $v1->show_all; - $v2->show_all; - set_gui_status($ipgen,"ideal",0); - - - } - return TRUE; - - } ); - - - - - $open-> signal_connect("clicked" => sub{ - load_ip($ipgen); - - }); - - $generate-> signal_connect("clicked" => sub{ - get_unused_intfc_ports_list ($intfc,$ipgen,$info); - generate_ip($ipgen); - - set_gui_status($ipgen,"ref",1); - - }); - - return add_widget_to_scrolled_win($main_table); - + my $ipgen=shift; + my $intfc=interface->interface_new(); + if(!defined $ipgen) { $ipgen=ip_gen->ip_gen_new();} + set_gui_status($ipgen,"ideal",0); + # The main table containing the lib tree, selected modules and info section + my $main_table = def_table (15, 12, FALSE); + # The box which holds the info, warning, error ... mesages + my ($infobox,$info)= create_txview(); + my $generate = def_image_button('icons/gen.png','Generate'); + # A tree view for holding a library + my %tree_text; + my @categories= $intfc->get_categories(); + foreach my $p (@categories) + { + my @intfc_names= $intfc->get_intfcs_of_category($p); + $tree_text{$p}=\@intfc_names; + } + my $tree_box = create_tree ($ipgen,'Interfaces list',$info,\%tree_text,\&show_interface_description ,\&add_plug_interface_from_tree); + my $file_info=file_info_box($ipgen,$info); + my $port_info=port_info_box($intfc,$ipgen,$info); + my $intfc_info=interface_info_box($intfc,$ipgen,$info); + my $open = def_image_button('icons/browse.png','Load IP'); + $main_table->set_row_spacings (4); + $main_table->set_col_spacings (1); + #$table->attach_defaults ($event_box, $col, $col+1, $row, $row+1); + my $v1=gen_vpaned($file_info,.2,$intfc_info); + my $v2=gen_vpaned($v1,.4,$port_info); + my $h1=gen_hpaned($tree_box,.15,$v2); + my $v3=gen_vpaned($h1,.6,$infobox); + $main_table->attach_defaults ($v3, 0, 12, 0,14); + $main_table->attach ($generate, 6, 8, 14,15,'expand','shrink',2,2); + $main_table->attach ($open,0, 1, 14,15,'expand','shrink',2,2); + #check soc status every 0.5 second. refresh device table if there is any changes + Glib::Timeout->add (100, sub{ + my ($state,$timeout)= get_gui_status($ipgen); + if($state eq "load_file"){ + my $file=$ipgen->ipgen_get("file_name"); + my ($pp,$r,$err) = regen_object($file); + if ($r){ + add_colored_info($info,"**Error reading $file file: $err\n",'red'); + return; + } + clone_obj($ipgen,$pp); + show_info($info,"$file is loaded!\n "); + set_gui_status($ipgen,"ref",1); + }elsif ($timeout>0){ + $timeout--; + set_gui_status($ipgen,$state,$timeout); + } + elsif( $state eq "change_parameter" ){ + get_parameter_setting($ipgen,$info); + set_gui_status($ipgen,"ideal",0); + } + elsif( $state ne "ideal" ){ + $file_info->destroy; + $port_info->destroy; + $intfc_info->destroy; + $file_info=file_info_box($ipgen,$info); + $port_info=port_info_box($intfc,$ipgen,$info); + $intfc_info=interface_info_box($intfc,$ipgen,$info); + $v1 -> pack1($file_info, TRUE, TRUE); + $v1 -> pack2($intfc_info, TRUE, TRUE); + $v2 -> pack2($port_info, TRUE, TRUE); + $v1->show_all; + $v2->show_all; + set_gui_status($ipgen,"ideal",0); + } + return TRUE; + } ); + $open-> signal_connect("clicked" => sub{ + load_ip($ipgen); + }); + $generate-> signal_connect("clicked" => sub{ + get_unused_intfc_ports_list ($intfc,$ipgen,$info); + generate_ip($ipgen); + set_gui_status($ipgen,"ref",1); + }); + return add_widget_to_scrolled_win($main_table); } - - - +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/ip_gen.pm b/mpsoc/perl_gui/lib/perl/ip_gen.pm index 6633db6..2f28270 100755 --- a/mpsoc/perl_gui/lib/perl/ip_gen.pm +++ b/mpsoc/perl_gui/lib/perl/ip_gen.pm @@ -1,692 +1,567 @@ #!/usr/bin/perl -w -I .. ############################################################################### -# # File: interface.pm -# -# ############################################################################### + use warnings; use strict; - - - package ip_gen; #use Clone 'clone'; - - sub ip_gen_new { # be backwards compatible with non-OO call my $class = ("ARRAY" eq ref $_[0]) ? "ip_gen" : shift; my $self; - - $self = {}; - $self->{file_name} = (); + $self->{file_name} = (); $self->{parameters_order}=[]; $self->{ports_order}=[]; $self->{hdl_files}=[]; - $self->{hdl_files_ticked}=[]; - - + $self->{hdl_files_ticked}=[]; bless($self,$class); - - return $self; -} - - +} sub ipgen_set_module_list{ - my ($self,@list)=@_; - $self->{modules}={}; - foreach my $p(@list) { - $self->{modules}{$p}={}; - } - -} - - + my ($self,@list)=@_; + $self->{modules}={}; + foreach my $p(@list) { + $self->{modules}{$p}={}; + } +} sub ipgen_get_module_list{ - my ($self)=@_; - my @modules; - if(exists($self->{modules})){ - @modules=keys %{$self->{modules}}; - } - return @modules; -} - - + my ($self)=@_; + my @modules; + if(exists($self->{modules})){ + @modules=keys %{$self->{modules}}; + } + return @modules; +} sub ipgen_add_parameter{ - my ($self,$parameter,$default,$type,$content,$info,$global_param,$redefine)=@_; - $self->{parameters}{$parameter}{"default"}=$default; - $self->{parameters}{$parameter}{type}=$type; - $self->{parameters}{$parameter}{content}=$content; - $self->{parameters}{$parameter}{info}=$info; - $self->{parameters}{$parameter}{global_param}=$global_param; - $self->{parameters}{$parameter}{redefine_param}=$redefine; -} - - - - - + my ($self,$parameter,$default,$type,$content,$info,$global_param,$redefine)=@_; + $self->{parameters}{$parameter}{"default"}=$default; + $self->{parameters}{$parameter}{type}=$type; + $self->{parameters}{$parameter}{content}=$content; + $self->{parameters}{$parameter}{info}=$info; + $self->{parameters}{$parameter}{global_param}=$global_param; + $self->{parameters}{$parameter}{redefine_param}=$redefine; +} sub ipgen_push_parameters_order{ - my ($self,$param)=@_; - if(defined $param){ - push(@{$self->{parameters_order}},$param); - } - + my ($self,$param)=@_; + if(defined $param){ + push(@{$self->{parameters_order}},$param); + } } sub ipgen_remove_parameters_order{ - my ($self,$param)=@_; - my @r=@{$self->{parameters_order}}; - my @n; - foreach my $p(@r){ - if( $p ne $param) {push(@n,$p)}; - - } - $self->{parameters_order}=\@n; - + my ($self,$param)=@_; + my @r=@{$self->{parameters_order}}; + my @n; + foreach my $p(@r){ + if( $p ne $param) {push(@n,$p)}; + } + $self->{parameters_order}=\@n; } - sub ipgen_add_ports_order{ - my ($self,@ports_order) =@_; - $self->{ports_order}=\@ports_order; + my ($self,@ports_order) =@_; + $self->{ports_order}=\@ports_order; } - - sub ipgen_get_ports_order{ - my $self =shift; - my @order=(defined $self->{ports_order})? @{$self->{ports_order}} : undef; + my $self =shift; + my @order=(defined $self->{ports_order})? @{$self->{ports_order}} : undef; return @order; } - - - sub ipgen_remove_parameter{ - my ($self,$parameter)=@_; - if(exists ( $self->{parameters}{$parameter})){ - delete $self->{parameters}{$parameter}; - } -} - + my ($self,$parameter)=@_; + if(exists ( $self->{parameters}{$parameter})){ + delete $self->{parameters}{$parameter}; + } +} + sub ipgen_get_parameter_detail{ - my ($self,$parameter)=@_; - my ($default,$type,$content,$info,$global_param,$redefine); - if(exists ($self->{parameters}{$parameter})){ - $default =$self->{parameters}{$parameter}{"default"}; - $type =$self->{parameters}{$parameter}{type}; - $content =$self->{parameters}{$parameter}{content}; - $info =$self->{parameters}{$parameter}{info}; - $global_param =$self->{parameters}{$parameter}{global_param}; - $redefine =$self->{parameters}{$parameter}{redefine_param}; - - } - return ($default,$type,$content,$info,$global_param,$redefine); -} + my ($self,$parameter)=@_; + my ($default,$type,$content,$info,$global_param,$redefine); + if(exists ($self->{parameters}{$parameter})){ + $default =$self->{parameters}{$parameter}{"default"}; + $type =$self->{parameters}{$parameter}{type}; + $content =$self->{parameters}{$parameter}{content}; + $info =$self->{parameters}{$parameter}{info}; + $global_param =$self->{parameters}{$parameter}{global_param}; + $redefine =$self->{parameters}{$parameter}{redefine_param}; + } + return ($default,$type,$content,$info,$global_param,$redefine); +} sub ipgen_get_all_parameters_list{ - my ($self)=@_; - my @parameters; - if(exists ($self->{parameters})){ - foreach my $p ( keys %{$self->{parameters}}){ - push(@parameters,$p); - } - } - return @parameters; -} + my ($self)=@_; + my @parameters; + if(exists ($self->{parameters})){ + foreach my $p ( keys %{$self->{parameters}}){ + push(@parameters,$p); + } + } + return @parameters; +} sub ipgen_remove_all_parameters{ - my ($self)=@_; - if (exists ($self->{parameters})){ - delete $self->{parameters}; - } -} - - + my ($self)=@_; + if (exists ($self->{parameters})){ + delete $self->{parameters}; + } +} sub ipgen_add_port{ - my($self,$port,$range,$type,$intfc_name,$intfc_port)=@_; - $self->{ports}{$port}{range}=$range; - $self->{ports}{$port}{type}=$type; - $self->{ports}{$port}{intfc_name}=$intfc_name; - $self->{ports}{$port}{intfc_port}=$intfc_port; + my($self,$port,$range,$type,$intfc_name,$intfc_port)=@_; + $self->{ports}{$port}{range}=$range; + $self->{ports}{$port}{type}=$type; + $self->{ports}{$port}{intfc_name}=$intfc_name; + $self->{ports}{$port}{intfc_port}=$intfc_port; } sub ipgen_get_port{ - my($self,$port)=@_; - my($range,$type,$intfc_name,$intfc_port); - if(exists ($self->{ports}{$port})){ - $range=$self->{ports}{$port}{range}; - $type=$self->{ports}{$port}{type}; - $intfc_name=$self->{ports}{$port}{intfc_name}; - $intfc_port=$self->{ports}{$port}{intfc_port}; - } - return ($range,$type,$intfc_name,$intfc_port); + my($self,$port)=@_; + my($range,$type,$intfc_name,$intfc_port); + if(exists ($self->{ports}{$port})){ + $range=$self->{ports}{$port}{range}; + $type=$self->{ports}{$port}{type}; + $intfc_name=$self->{ports}{$port}{intfc_name}; + $intfc_port=$self->{ports}{$port}{intfc_port}; + } + return ($range,$type,$intfc_name,$intfc_port); } - sub ipgen_list_ports{ - my($self)=@_; - my @ports; - foreach my $p (keys %{$self->{ports}}){ - push (@ports,$p); - } - return @ports; + my($self)=@_; + my @ports; + foreach my $p (keys %{$self->{ports}}){ + push (@ports,$p); + } + return @ports; } - - sub ipgen_remove_all_ports{ - my $self=shift; - if (exists ($self->{ports})){ - delete $self->{ports}; - } - -} + my $self=shift; + if (exists ($self->{ports})){ + delete $self->{ports}; + } +} sub ipgen_add_soket{ - my ($self,$socket,$type,$value,$connection_num)=@_; - $self->{sockets}{$socket}{type}=$type; - if(defined $value) { - $self->{sockets}{$socket}{value}=$value; - - } - if(defined $connection_num) {$self->{sockets}{$socket}{connection_num}=$connection_num;} - if($type eq 'num'){ - if($value == 1) {ipgen_set_socket_name($self,$socket,0,$socket);} - else{ - for (my $i=0; $i<$value; $i++){ - my $name="$socket\_$i"; - ipgen_set_socket_name($self,$socket,$i,$name); - } - - } - - } - else{ipgen_set_socket_name($self,$socket,0,$socket);} - - #print "\$self->{sockets}{$socket}{type}=$type;\n" + my ($self,$socket,$type,$value,$connection_num)=@_; + $self->{sockets}{$socket}{type}=$type; + if(defined $value) { + $self->{sockets}{$socket}{value}=$value; + } + if(defined $connection_num) {$self->{sockets}{$socket}{connection_num}=$connection_num;} + if($type eq 'num'){ + if($value == 1) {ipgen_set_socket_name($self,$socket,0,$socket);} + else{ + for (my $i=0; $i<$value; $i++){ + my $name="$socket\_$i"; + ipgen_set_socket_name($self,$socket,$i,$name); + } + } + } + else{ipgen_set_socket_name($self,$socket,0,$socket);} + #print "\$self->{sockets}{$socket}{type}=$type;\n" } sub ipgen_add_plug{ - my ($self,$plug,$type,$value)=@_; - $self->{plugs}{$plug}{type}=$type; - if(defined $value){$self->{plugs}{$plug}{value}=$value}; - if($type eq 'num'){ - if($value == 1) {ipgen_set_plug_name($self,$plug,0,$plug);} - else{ - for (my $i=0; $i<$value; $i++){ - my $name="$plug\_$i"; - ipgen_set_plug_name($self,$plug,$i,$name); - } - - } - - } - else{ipgen_set_plug_name($self,$plug,0,$plug);} - -} + my ($self,$plug,$type,$value)=@_; + $self->{plugs}{$plug}{type}=$type; + if(defined $value){$self->{plugs}{$plug}{value}=$value}; + if($type eq 'num'){ + if($value == 1) {ipgen_set_plug_name($self,$plug,0,$plug);} + else{ + for (my $i=0; $i<$value; $i++){ + my $name="$plug\_$i"; + ipgen_set_plug_name($self,$plug,$i,$name); + } + } + } + else{ipgen_set_plug_name($self,$plug,0,$plug);} +} sub ipgen_list_sokets{ - my ($self)=@_; - my @sokets; - - if(exists ($self->{sockets})){ - foreach my $p(keys %{$self->{sockets}}){ - push (@sokets,$p); - } - } - return @sokets; + my ($self)=@_; + my @sokets; + if(exists ($self->{sockets})){ + foreach my $p(keys %{$self->{sockets}}){ + push (@sokets,$p); + } + } + return @sokets; } - sub ipgen_list_plugs{ - my ($self)=@_; - my @plugs; - if(exists ($self->{plugs})){ - foreach my $p(keys %{$self->{plugs}}){ - push (@plugs,$p); - } - } - return @plugs; + my ($self)=@_; + my @plugs; + if(exists ($self->{plugs})){ + foreach my $p(keys %{$self->{plugs}}){ + push (@plugs,$p); + } + } + return @plugs; } - - sub ipgen_get_socket{ - my ($self,$socket)=@_; - my ($type,$value,$connection_num); - if(exists ($self->{sockets}{$socket})){ - $type =$self->{sockets}{$socket}{type}; - $value =$self->{sockets}{$socket}{value}; - $connection_num= $self->{sockets}{$socket}{connection_num}; - #print "$type,$value\n" - } - return ($type,$value,$connection_num); + my ($self,$socket)=@_; + my ($type,$value,$connection_num); + if(exists ($self->{sockets}{$socket})){ + $type =$self->{sockets}{$socket}{type}; + $value =$self->{sockets}{$socket}{value}; + $connection_num= $self->{sockets}{$socket}{connection_num}; + #print "$type,$value\n" + } + return ($type,$value,$connection_num); } sub ipgen_get_plug{ - my ($self,$plug)=@_; - my ($type,$value,$connection_num); - if(exists ($self->{plugs}{$plug})){ - $type =$self->{plugs}{$plug}{type}; - $value =$self->{plugs}{$plug}{value}; - $connection_num=$self->{plugs}{$plug}{connection_num}; - } - return ($type,$value,$connection_num); + my ($self,$plug)=@_; + my ($type,$value,$connection_num); + if(exists ($self->{plugs}{$plug})){ + $type =$self->{plugs}{$plug}{type}; + $value =$self->{plugs}{$plug}{value}; + $connection_num=$self->{plugs}{$plug}{connection_num}; + } + return ($type,$value,$connection_num); } sub ipgen_remove_socket{ - my ($self,$socket)=@_; - if(exists ($self->{sockets}{$socket})) { - delete $self->{sockets}{$socket}; - } -} + my ($self,$socket)=@_; + if(exists ($self->{sockets}{$socket})) { + delete $self->{sockets}{$socket}; + } +} sub ipgen_remove_plug{ - my ($self,$plug)=@_; - if(exists ($self->{plugs}{$plug})) { - delete $self->{plugs}{$plug}; - } -} - - + my ($self,$plug)=@_; + if(exists ($self->{plugs}{$plug})) { + delete $self->{plugs}{$plug}; + } +} sub ipgen_set_port_intfc_name{ - my ($self,$port,$intfc_name)=@_; - if(exists ($self->{ports}{$port})){ - $self->{ports}{$port}{intfc_name}=$intfc_name; - } - + my ($self,$port,$intfc_name)=@_; + if(exists ($self->{ports}{$port})){ + $self->{ports}{$port}{intfc_name}=$intfc_name; + } } sub ipgen_get_port_intfc_name{ - my ($self,$port)=@_; - my $intfc_name; - if(exists ($self->{ports}{$port}{intfc_name})){ - $intfc_name=$self->{ports}{$port}{intfc_name}; - } - return ($intfc_name); -} + my ($self,$port)=@_; + my $intfc_name; + if(exists ($self->{ports}{$port}{intfc_name})){ + $intfc_name=$self->{ports}{$port}{intfc_name}; + } + return ($intfc_name); +} sub ipgen_set_port_intfc_port{ - my ($self,$port,$intfc_port)=@_; - if(exists ($self->{ports}{$port})){ - $self->{ports}{$port}{intfc_port}=$intfc_port; - } - + my ($self,$port,$intfc_port)=@_; + if(exists ($self->{ports}{$port})){ + $self->{ports}{$port}{intfc_port}=$intfc_port; + } } sub ipgen_get_port_intfc_port{ - my ($self,$port)=@_; - my $intfc_port; - if(exists ($self->{ports}{$port}{intfc_port})){ - $intfc_port=$self->{ports}{$port}{intfc_port}; - } - return ($intfc_port); -} - - + my ($self,$port)=@_; + my $intfc_port; + if(exists ($self->{ports}{$port}{intfc_port})){ + $intfc_port=$self->{ports}{$port}{intfc_port}; + } + return ($intfc_port); +} sub ipgen_save_wb_addr{ - my ($self,$plug,$num,$addr,$width)=@_; - $self->{plugs}{$plug}{$num}{addr}=$addr; - $self->{plugs}{$plug}{$num}{width}=$width; - -} - + my ($self,$plug,$num,$addr,$width)=@_; + $self->{plugs}{$plug}{$num}{addr}=$addr; + $self->{plugs}{$plug}{$num}{width}=$width; +} + sub ipgen_get_wb_addr{ - my ($self,$plug,$num)=@_; - my($addr,$width); - if(exists ($self->{plugs}{$plug}{$num})){ - $addr= $self->{plugs}{$plug}{$num}{addr}; - $width=$self->{plugs}{$plug}{$num}{width}; - } - return ($addr,$width); -} - -sub ipgen_set_plug_name{ - my ($self,$plug,$num,$name)=@_; - if(exists ($self->{plugs}{$plug})){ - $self->{plugs}{$plug}{$num}{name}=$name; - - } - -} + my ($self,$plug,$num)=@_; + my($addr,$width); + if(exists ($self->{plugs}{$plug}{$num})){ + $addr= $self->{plugs}{$plug}{$num}{addr}; + $width=$self->{plugs}{$plug}{$num}{width}; + } + return ($addr,$width); +} +sub ipgen_set_plug_name{ + my ($self,$plug,$num,$name)=@_; + if(exists ($self->{plugs}{$plug})){ + $self->{plugs}{$plug}{$num}{name}=$name; + } +} sub ipgen_get_plug_name{ - my ($self,$plug,$num)=@_; - my $name; - if(exists ($self->{plugs}{$plug}{$num}{name})){ - $name=$self->{plugs}{$plug}{$num}{name}; - - } - return $name; + my ($self,$plug,$num)=@_; + my $name; + if(exists ($self->{plugs}{$plug}{$num}{name})){ + $name=$self->{plugs}{$plug}{$num}{name}; + } + return $name; } sub ipgen_set_socket_name { - my ($self,$socket,$num,$name)= @_; - if(exists ($self->{sockets}{$socket})){ - $self->{sockets}{$socket}{$num}{name}=$name; - - } - -} + my ($self,$socket,$num,$name)= @_; + if(exists ($self->{sockets}{$socket})){ + $self->{sockets}{$socket}{$num}{name}=$name; + } +} sub ipgen_get_socket_name{ - my ($self,$socket,$num)=@_; - my $name; - if(exists ($self->{sockets}{$socket}{$num}{name})){ - $name=$self->{sockets}{$socket}{$num}{name}; - - } - return $name; - -} - - + my ($self,$socket,$num)=@_; + my $name; + if(exists ($self->{sockets}{$socket}{$num}{name})){ + $name=$self->{sockets}{$socket}{$num}{name}; + } + return $name; +} sub ipgen_add_unused_intfc_port{ - my ($self,$intfc_name,$port)=@_; - push(@{$self->{unused}{$intfc_name}},$port); + my ($self,$intfc_name,$port)=@_; + push(@{$self->{unused}{$intfc_name}},$port); } - - - - - #add,read,remove object fileds - sub ipgen_add{ - my ($self,$filed_name,$filed_data)=@_; - $self->{$filed_name}=$filed_data; + my ($self,$filed_name,$filed_data)=@_; + $self->{$filed_name}=$filed_data; } sub ipgen_remove{ - my ($self,$filed_name)=@_; - $self->{$filed_name}=undef; + my ($self,$filed_name)=@_; + $self->{$filed_name}=undef; } sub ipgen_get{ - my ($self,$filed_name)=@_; - return $self->{$filed_name} + my ($self,$filed_name)=@_; + return $self->{$filed_name} } sub ipgen_get_list{ - my ($self,$list_name)=@_; - my @l; - if ( defined $self->{$list_name} ){ - @l=@{$self->{$list_name}}; - } - - return @l; + my ($self,$list_name)=@_; + my @l; + if ( defined $self->{$list_name} ){ + @l=@{$self->{$list_name}}; + } + return @l; } - - - - ###################################### - - - - sub top_gen_new { # be backwards compatible with non-OO call my $class = shift; my $self; - - $self = {}; $self->{instance_ids}={}; bless($self,$class); - - return $self; -} +} sub top_add_def_to_instance { - my ($self,$inst,$def,$value )=@_; - $self->{instance_ids}{$inst}{$def}=$value; + my ($self,$inst,$def,$value )=@_; + $self->{instance_ids}{$inst}{$def}=$value; } sub top_get_def_of_instance { - my ($self,$inst,$def)=@_; - my $val; - $val=$self->{instance_ids}{$inst}{$def} if(exists $self->{instance_ids}{$inst}{$def}) ; - return $val; + my ($self,$inst,$def)=@_; + my $val; + $val=$self->{instance_ids}{$inst}{$def} if(exists $self->{instance_ids}{$inst}{$def}) ; + return $val; } - sub top_add_port{ - my($self,$inst,$port,$range,$type,$intfc_name,$intfc_port)=@_; - - #all ports - $self->{ports}{$port}{range}=$range; - $self->{ports}{$port}{type}=$type; - $self->{ports}{$port}{intfc_name}=$intfc_name; - $self->{ports}{$port}{intfc_port}=$intfc_port; - $self->{ports}{$port}{instance_name}=$inst; - - - #based on instance name - $self->{instance_ids}{$inst}{ports}{$port}{range}=$range; - $self->{instance_ids}{$inst}{ports}{$port}{type}=$type; - $self->{instance_ids}{$inst}{ports}{$port}{intfc_name}=$intfc_name; - $self->{instance_ids}{$inst}{ports}{$port}{intfc_port}=$intfc_port; - - #based on interface name - $self->{interface}{$intfc_name}{ports}{$port}{range}=$range; - $self->{interface}{$intfc_name}{ports}{$port}{type}=$type; - $self->{interface}{$intfc_name}{ports}{$port}{instance_name}=$inst; - $self->{interface}{$intfc_name}{ports}{$port}{intfc_port}=$intfc_port; + my($self,$inst,$port,$range,$type,$intfc_name,$intfc_port)=@_; + #all ports + $self->{ports}{$port}{range}=$range; + $self->{ports}{$port}{type}=$type; + $self->{ports}{$port}{intfc_name}=$intfc_name; + $self->{ports}{$port}{intfc_port}=$intfc_port; + $self->{ports}{$port}{instance_name}=$inst; + #based on instance name + $self->{instance_ids}{$inst}{ports}{$port}{range}=$range; + $self->{instance_ids}{$inst}{ports}{$port}{type}=$type; + $self->{instance_ids}{$inst}{ports}{$port}{intfc_name}=$intfc_name; + $self->{instance_ids}{$inst}{ports}{$port}{intfc_port}=$intfc_port; + #based on interface name + $self->{interface}{$intfc_name}{ports}{$port}{range}=$range; + $self->{interface}{$intfc_name}{ports}{$port}{type}=$type; + $self->{interface}{$intfc_name}{ports}{$port}{instance_name}=$inst; + $self->{interface}{$intfc_name}{ports}{$port}{intfc_port}=$intfc_port; } - sub top_get_interface{ - my($self,$intfc_name,$port)=@_; - my $range= $self->{interface}{$intfc_name}{ports}{$port}{range}; - my $type= $self->{interface}{$intfc_name}{ports}{$port}{type}; - my $inst = $self->{interface}{$intfc_name}{ports}{$port}{instance_name}; - my $intfc_port=$self->{interface}{$intfc_name}{ports}{$port}{intfc_port}; - return ($range,$type,$inst,$intfc_port); + my($self,$intfc_name,$port)=@_; + my $range= $self->{interface}{$intfc_name}{ports}{$port}{range}; + my $type= $self->{interface}{$intfc_name}{ports}{$port}{type}; + my $inst = $self->{interface}{$intfc_name}{ports}{$port}{instance_name}; + my $intfc_port=$self->{interface}{$intfc_name}{ports}{$port}{intfc_port}; + return ($range,$type,$inst,$intfc_port); } - sub top_get_port{ - my($self,$port)=@_; - my($inst,$range,$type,$intfc_name,$intfc_port); - $inst =$self->{ports}{$port}{instance_name}; - $range =$self->{ports}{$port}{range}; - $type =$self->{ports}{$port}{type}; - $intfc_name =$self->{ports}{$port}{intfc_name}; - $intfc_port =$self->{ports}{$port}{intfc_port}; - return ($inst,$range,$type,$intfc_name,$intfc_port); + my($self,$port)=@_; + my($inst,$range,$type,$intfc_name,$intfc_port); + $inst =$self->{ports}{$port}{instance_name}; + $range =$self->{ports}{$port}{range}; + $type =$self->{ports}{$port}{type}; + $intfc_name =$self->{ports}{$port}{intfc_name}; + $intfc_port =$self->{ports}{$port}{intfc_port}; + return ($inst,$range,$type,$intfc_name,$intfc_port); } sub top_get_port_list{ - my$self=shift; - my @l; - if(exists $self->{ports}){ - @l= sort keys %{$self->{ports}}; - } - return @l; + my$self=shift; + my @l; + if(exists $self->{ports}){ + @l= sort keys %{$self->{ports}}; + } + return @l; } - - sub top_add_parameter{ - my ($self,$inst,$parameter,$default,$type,$content,$info,$global_param,$redefine)=@_; - $self->{instance_ids}{$inst}{parameters}{$parameter}{"default"}=$default; - $self->{instance_ids}{$inst}{parameters}{$parameter}{type}=$type; - $self->{instance_ids}{$inst}{parameters}{$parameter}{content}=$content; - $self->{instance_ids}{$inst}{parameters}{$parameter}{info}=$info; - $self->{instance_ids}{$inst}{parameters}{$parameter}{global_param}=$global_param; - $self->{instance_ids}{$inst}{parameters}{$parameter}{redefine_param}=$redefine; -} + my ($self,$inst,$parameter,$default,$type,$content,$info,$global_param,$redefine)=@_; + $self->{instance_ids}{$inst}{parameters}{$parameter}{"default"}=$default; + $self->{instance_ids}{$inst}{parameters}{$parameter}{type}=$type; + $self->{instance_ids}{$inst}{parameters}{$parameter}{content}=$content; + $self->{instance_ids}{$inst}{parameters}{$parameter}{info}=$info; + $self->{instance_ids}{$inst}{parameters}{$parameter}{global_param}=$global_param; + $self->{instance_ids}{$inst}{parameters}{$parameter}{redefine_param}=$redefine; +} sub top_add_localparam{ - my ($self,$inst,$parameter,$default,$type,$content,$info,$global_param,$redefine)=@_; - $self->{instance_ids}{$inst}{localparam}{$parameter}{"default"}=$default; - $self->{instance_ids}{$inst}{localparam}{$parameter}{type}=$type; - $self->{instance_ids}{$inst}{localparam}{$parameter}{content}=$content; - $self->{instance_ids}{$inst}{localparam}{$parameter}{info}=$info; - $self->{instance_ids}{$inst}{localparam}{$parameter}{global_param}=$global_param; - $self->{instance_ids}{$inst}{localparam}{$parameter}{redefine_param}=$redefine; -} - + my ($self,$inst,$parameter,$default,$type,$content,$info,$global_param,$redefine)=@_; + $self->{instance_ids}{$inst}{localparam}{$parameter}{"default"}=$default; + $self->{instance_ids}{$inst}{localparam}{$parameter}{type}=$type; + $self->{instance_ids}{$inst}{localparam}{$parameter}{content}=$content; + $self->{instance_ids}{$inst}{localparam}{$parameter}{info}=$info; + $self->{instance_ids}{$inst}{localparam}{$parameter}{global_param}=$global_param; + $self->{instance_ids}{$inst}{localparam}{$parameter}{redefine_param}=$redefine; +} sub top_get_parameter{ - my ($self,$inst,$parameter)=@_; - my ($default,$type,$content,$info,$global_param,$redefine); - $default=$self->{instance_ids}{$inst}{parameters}{$parameter}{"default"}; - $type=$self->{instance_ids}{$inst}{parameters}{$parameter}{type}; - $content=$self->{instance_ids}{$inst}{parameters}{$parameter}{content}; - $info=$self->{instance_ids}{$inst}{parameters}{$parameter}{info}; - $global_param=$self->{instance_ids}{$inst}{parameters}{$parameter}{global_param}; - $redefine=$self->{instance_ids}{$inst}{parameters}{$parameter}{redefine_param}; - return ($default,$type,$content,$info,$global_param,$redefine); -} + my ($self,$inst,$parameter)=@_; + my ($default,$type,$content,$info,$global_param,$redefine); + $default=$self->{instance_ids}{$inst}{parameters}{$parameter}{"default"}; + $type=$self->{instance_ids}{$inst}{parameters}{$parameter}{type}; + $content=$self->{instance_ids}{$inst}{parameters}{$parameter}{content}; + $info=$self->{instance_ids}{$inst}{parameters}{$parameter}{info}; + $global_param=$self->{instance_ids}{$inst}{parameters}{$parameter}{global_param}; + $redefine=$self->{instance_ids}{$inst}{parameters}{$parameter}{redefine_param}; + return ($default,$type,$content,$info,$global_param,$redefine); +} sub top_get_parameter_list{ - my($self,$inst)=@_; - my @l; - if(exists $self->{instance_ids}{$inst}{parameters}){ - @l= sort keys %{$self->{instance_ids}{$inst}{parameters}}; - } - return @l; + my($self,$inst)=@_; + my @l; + if(exists $self->{instance_ids}{$inst}{parameters}){ + @l= sort keys %{$self->{instance_ids}{$inst}{parameters}}; + } + return @l; } - - - sub top_add_default_soc_param{ - my ($self,$param_ref)=@_; - my %l=%{$param_ref}; - foreach my $p (sort keys %l){ - $self->{parameters}{$p}=$l{$p}; - #print"$self->{parameters}{$p}=$l{$p};\n"; - } -} + my ($self,$param_ref)=@_; + my %l=%{$param_ref}; + foreach my $p (sort keys %l){ + $self->{parameters}{$p}=$l{$p}; + #print"$self->{parameters}{$p}=$l{$p};\n"; + } +} sub top_get_default_soc_param{ - my $self=shift; - my %l; - if(exists $self->{parameters}){ - %l=%{$self->{parameters}}; - } - return %l; -} - - -sub top_get_all_instances{ - my ($self)=shift; - my @r= keys %{$self->{instance_ids}}; - return @r; - + my $self=shift; + my %l; + if(exists $self->{parameters}){ + %l=%{$self->{parameters}}; + } + return %l; } +sub top_get_all_instances{ + my ($self)=shift; + my @r= keys %{$self->{instance_ids}}; + return @r; +} sub top_get_intfc_list{ - my ($self)=shift; - my @intfcs; - if(exists $self->{interface}){ - @intfcs= sort keys %{$self->{interface}}; - } - - return @intfcs; + my ($self)=shift; + my @intfcs; + if(exists $self->{interface}){ + @intfcs= sort keys %{$self->{interface}}; + } + return @intfcs; } - - - sub top_get_intfc_ports_list{ - my($self,$intfc_name)=@_; - my @ports; - if( exists $self->{interface}{$intfc_name}{ports}){ - @ports= sort keys %{$self->{interface}{$intfc_name}{ports}}; - } - return @ports; + my($self,$intfc_name)=@_; + my @ports; + if( exists $self->{interface}{$intfc_name}{ports}){ + @ports= sort keys %{$self->{interface}{$intfc_name}{ports}}; + } + return @ports; } - sub top_add_custom_soc_param{ - my ($self,$param_ref,$tile)=@_; - my %l=%{$param_ref}; - foreach my $p (sort keys %l){ - $self->{tiles}{$tile}{parameters}{$p}=$l{$p}; - #print"$self->{parameters}{$p}=$l{$p};\n"; - } -} - + my ($self,$param_ref,$tile)=@_; + my %l=%{$param_ref}; + foreach my $p (sort keys %l){ + $self->{tiles}{$tile}{parameters}{$p}=$l{$p}; + #print"$self->{parameters}{$p}=$l{$p};\n"; + } +} sub top_get_custom_tile_list{ - my ($self)=@_; - my %tiles_hash; - %tiles_hash=%{$self->{'tiles'}} if(defined $self->{'tiles'} ); - my @tiles = sort keys %tiles_hash; - return @tiles; -} - - + my ($self)=@_; + my %tiles_hash; + %tiles_hash=%{$self->{'tiles'}} if(defined $self->{'tiles'} ); + my @tiles = sort keys %tiles_hash; + return @tiles; +} - - - - sub top_get_custom_soc_param{ - my ($self,$tile)=@_; - my %l; - if(exists $self->{tiles}{$tile}{parameters}){#get custom param - %l=%{$self->{tiles}{$tile}{parameters}}; - }elsif (exists $self->{parameters}){#get default param - %l=%{$self->{parameters}}; - } - return %l; - -} - - + my ($self,$tile)=@_; + my %l; + if(exists $self->{tiles}{$tile}{parameters}){#get custom param + %l=%{$self->{tiles}{$tile}{parameters}}; + }elsif (exists $self->{parameters}){#get default param + %l=%{$self->{parameters}}; + } + return %l; +} sub object_add_attribute{ - my ($self,$attribute1,$attribute2,$value)=@_; - if(!defined $attribute2){$self->{$attribute1}=$value;} - else {$self->{$attribute1}{$attribute2}=$value;} - + my ($self,$attribute1,$attribute2,$value)=@_; + if(!defined $attribute2){$self->{$attribute1}=$value;} + else {$self->{$attribute1}{$attribute2}=$value;} } sub object_get_attribute{ - my ($self,$attribute1,$attribute2)=@_; - if(!defined $attribute2) {return $self->{$attribute1};} - return $self->{$attribute1}{$attribute2}; - - + my ($self,$attribute1,$attribute2)=@_; + if(!defined $attribute2) {return $self->{$attribute1};} + return $self->{$attribute1}{$attribute2}; } sub object_add_attribute_order{ - my ($self,$attribute,@param)=@_; - my $r = $self->{'parameters_order'}{$attribute}; - my @a; - @a = @{$r} if(defined $r); - push (@a,@param); - @a=List::MoreUtils(@a); - $self->{'parameters_order'}{$attribute} =\@a; + my ($self,$attribute,@param)=@_; + my $r = $self->{'parameters_order'}{$attribute}; + my @a; + @a = @{$r} if(defined $r); + push (@a,@param); + @a=List::MoreUtils(@a); + $self->{'parameters_order'}{$attribute} =\@a; } sub object_get_attribute_order{ - my ($self,$attribute)=@_; - return @{$self->{parameters_order}{$attribute}}; + my ($self,$attribute)=@_; + return @{$self->{parameters_order}{$attribute}}; } - - - - 1 +1; diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl index 75e8e93..f77bc7d 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl @@ -2,7 +2,6 @@ use warnings; use FindBin; use lib $FindBin::Bin; - use mpsoc; use soc; use ip; @@ -10,969 +9,756 @@ use Cwd; use rvp; - sub mpsoc_generate_verilog{ - my ($mpsoc,$sw_dir,$txview)=@_; - my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); - my $top_ip=ip_gen->top_gen_new(); - - - - - my $param_as_in_v; - # generate top - - - - #generate socs_parameter - my $socs_param= gen_socs_param($mpsoc); - - #generate noc_parameter - my ($noc_param,$pass_param)=gen_noc_param_v($mpsoc); - - #generate the noc - my $noc_v=gen_noc_v($mpsoc,$pass_param); - - #generate socs - my ($socs_v,$io_short,$io_full,$top_io_short,$top_io_full,$top_io_pass,$href)=gen_socs_v($mpsoc,$top_ip,$sw_dir,$txview); - my %jtag_info=%{$href}; - my $jtag_v=add_jtag_ctrl (\%jtag_info,$txview); - - my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($mpsoc); - - $top_io_short=$top_io_short.",\n$clk_io_sim" if (defined $clk_io_sim); - $top_io_full=$top_io_full."\n$clk_io_full"; + my ($mpsoc,$sw_dir,$txview)=@_; + my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); + my $top_ip=ip_gen->top_gen_new(); + my $param_as_in_v; + # generate top + #generate socs_parameter + my $socs_param= gen_socs_param($mpsoc); + #generate noc_parameter + my ($noc_param,$pass_param)=gen_noc_param_v($mpsoc); + #generate the noc + my $noc_v=gen_noc_v($mpsoc,$pass_param); + #generate socs + my ($socs_v,$io_short,$io_full,$top_io_short,$top_io_full,$top_io_pass,$href)=gen_socs_v($mpsoc,$top_ip,$sw_dir,$txview); + my %jtag_info=%{$href}; + my $jtag_v=add_jtag_ctrl (\%jtag_info,$txview); + my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($mpsoc); + $top_io_short=$top_io_short.",\n$clk_io_sim" if (defined $clk_io_sim); + $top_io_full=$top_io_full."\n$clk_io_full"; $top_io_pass=$top_io_pass.",\n$clk_assigned_port" if (defined $clk_assigned_port); - - #functions - my $functions=get_functions(); - $param_as_in_v = (defined $param_as_in_v)? "$param_as_in_v,\nparameter NOC_ID=0\n" : "parameter NOC_ID=0\n"; - my $global_localparam=get_golal_param_v(); - my $pdef = "`include \"pronoc_def.v\""; - my $mpsoc_v = (defined $param_as_in_v )? " $pdef\nmodule $mpsoc_name\n\t #(\n $param_as_in_v)(\n$io_short\n);\n\t`NOC_CONF": "$pdef\nmodule $mpsoc_name\n \t (\n$io_short\n);\n\t`NOC_CONF"; - $mpsoc_v=$mpsoc_v. " -$global_localparam + #functions + my $functions=get_functions(); + $param_as_in_v = (defined $param_as_in_v)? "$param_as_in_v,\nparameter NOC_ID=0\n" : "parameter NOC_ID=0\n"; + my $global_localparam=get_golal_param_v(); + my $pdef = "`include \"pronoc_def.v\""; + my $mpsoc_v = (defined $param_as_in_v )? " $pdef\nmodule $mpsoc_name\n\t #(\n $param_as_in_v)(\n$io_short\n);\n\t`NOC_CONF": "$pdef\nmodule $mpsoc_name\n \t (\n$io_short\n);\n\t`NOC_CONF"; + $mpsoc_v=$mpsoc_v. " +$global_localparam $socs_param $io_full $noc_v $socs_v endmodule "; - - - my $top_v = (defined $param_as_in_v )? "$pdef\nmodule ${mpsoc_name}_top #(\n $param_as_in_v\n)(\n$top_io_short\n);\n": "$pdef\nmodule ${mpsoc_name}_top (\n $top_io_short\n);\n"; - + my $top_v = (defined $param_as_in_v )? "$pdef\nmodule ${mpsoc_name}_top #(\n $param_as_in_v\n)(\n$top_io_short\n);\n": "$pdef\nmodule ${mpsoc_name}_top (\n $top_io_short\n);\n"; $top_v=$top_v." -$global_localparam +$global_localparam $socs_param $top_io_full $clk_set -$jtag_v +$jtag_v \t${mpsoc_name} the_${mpsoc_name} ( $top_io_pass - \t); endmodule -"; - - - - - -# my $mp=get_top_ip($mpsoc,'mpsoc'); - -# mkpath("$dir/lib/ip/mpsoc/",1,01777); -# open(FILE, ">$dir/lib/ip/mpsoc/MPSOC.IP") || die "Can not open: $!"; -# print FILE perl_file_header("MPSOC.IP"); -# print FILE Data::Dumper->Dump([\%$mp],["ipgen"]); -# close(FILE) || die "Error closing file: $!"; - - -# my ($mp_v,$top_v)=soc_generate_verilog($top_soc,"target_dir/sw1",$txview); - - - - #my $ins= gen_mpsoc_instance_v($mpsoc,$mpsoc_name,$param_pass_v); - - #add_text_to_string(\$top_v,$local_param_v_all."\n".$io_full_v_all); - #add_text_to_string(\$top_v,$ins); - $mpsoc->object_add_attribute('top_ip',undef,$top_ip); - - my @chains = (sort { $b <=> $a } keys %jtag_info); - $mpsoc->object_add_attribute('JTAG','M_CHAIN',$chains[0]); - - return ($mpsoc_v,$top_v,$noc_param); +"; +# my $mp=get_top_ip($mpsoc,'mpsoc'); +# mkpath("$dir/lib/ip/mpsoc/",1,01777); +# open(FILE, ">$dir/lib/ip/mpsoc/MPSOC.IP") || die "Can not open: $!"; +# print FILE perl_file_header("MPSOC.IP"); +# print FILE Data::Dumper->Dump([\%$mp],["ipgen"]); +# close(FILE) || die "Error closing file: $!"; +# my ($mp_v,$top_v)=soc_generate_verilog($top_soc,"target_dir/sw1",$txview); + #my $ins= gen_mpsoc_instance_v($mpsoc,$mpsoc_name,$param_pass_v); + #add_text_to_string(\$top_v,$local_param_v_all."\n".$io_full_v_all); + #add_text_to_string(\$top_v,$ins); + $mpsoc->object_add_attribute('top_ip',undef,$top_ip); + my @chains = (sort { $b <=> $a } keys %jtag_info); + $mpsoc->object_add_attribute('JTAG','M_CHAIN',$chains[0]); + return ($mpsoc_v,$top_v,$noc_param); } sub add_sources_to_top_ip{ - my ($mpsoc,$top_ip)=@_; - my $sourc_short; - my $source_full=""; - my @sources=('clk','reset'); - foreach my $s (@sources){ - my $num = $mpsoc->object_get_attribute('SOURCE_SET',"${s}_number"); - $num=1 if (!defined $num); - for (my $n=0;$n<$num;$n++){ - my $name=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); - $name=$s if(!defined $name); - $top_ip->top_add_port('IO',$name,'', 'input' ,"plug:$s\[$n\]","${s}_i"); - $sourc_short= (defined $sourc_short)? $sourc_short.",\n\t$name" : "\t$name"; - #$source_full=$source_full. "// synthesis attribute keep of $name is true;\n" if($s eq 'clk'); - $source_full=$source_full."\tinput $name;\n"; - } - #$top_ip->top_add_port('IO','clk','', 'input' ,'plug:clk[0]','clk_i'); - } - return ($sourc_short, $source_full); + my ($mpsoc,$top_ip)=@_; + my $sourc_short; + my $source_full=""; + my @sources=('clk','reset'); + foreach my $s (@sources){ + my $num = $mpsoc->object_get_attribute('SOURCE_SET',"${s}_number"); + $num=1 if (!defined $num); + for (my $n=0;$n<$num;$n++){ + my $name=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); + $name=$s if(!defined $name); + $top_ip->top_add_port('IO',$name,'', 'input' ,"plug:$s\[$n\]","${s}_i"); + $sourc_short= (defined $sourc_short)? $sourc_short.",\n\t$name" : "\t$name"; + #$source_full=$source_full. "// synthesis attribute keep of $name is true;\n" if($s eq 'clk'); + $source_full=$source_full."\tinput $name;\n"; + } + #$top_ip->top_add_port('IO','clk','', 'input' ,'plug:clk[0]','clk_i'); + } + return ($sourc_short, $source_full); } - sub get_clk_constrain_file{ - my ($self)=@_; - my $s='clk'; - my $num = $self->object_get_attribute('SOURCE_SET',"${s}_number"); - my $top_name=$self->object_get_attribute('mpsoc_name'); - $top_name=$self->object_get_attribute('soc_name') if(!defined $top_name); - my $xdc=""; - return if (!defined $num); - for (my $n=0;$n<$num;$n++){ - my $clk_name=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); - my $period=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_period"); - my $fall=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_fall"); - my $rise=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_rise"); - my $fal_ns= ($period * $fall)/100; - my $rise_ns= ($period * $rise)/100; - - $xdc=$xdc."create_clock -period $period -name internal_clk$n -waveform {$rise_ns $fal_ns} -add \[get_nets uut/the_${top_name}/${clk_name}\]\n"; - - } - return $xdc; - + my ($self)=@_; + my $s='clk'; + my $num = $self->object_get_attribute('SOURCE_SET',"${s}_number"); + my $top_name=$self->object_get_attribute('mpsoc_name'); + $top_name=$self->object_get_attribute('soc_name') if(!defined $top_name); + my $xdc=""; + return if (!defined $num); + for (my $n=0;$n<$num;$n++){ + my $clk_name=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); + my $period=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_period"); + my $fall=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_fall"); + my $rise=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_rise"); + my $fal_ns= ($period * $fall)/100; + my $rise_ns= ($period * $rise)/100; + $xdc=$xdc."create_clock -period $period -name internal_clk$n -waveform {$rise_ns $fal_ns} -add \[get_nets uut/the_${top_name}/${clk_name}\]\n"; + } + return $xdc; } - - sub add_jtag_ctrl { - my ($ref,$txview)=@_; - my %jtag_info=%{$ref}; - - my $jtag_v="\t//Allow software to remote reset/enable the cpu via jtag -\twire jtag_cpu_en, jtag_system_reset; + my ($ref,$txview)=@_; + my %jtag_info=%{$ref}; + my $jtag_v="\t//Allow software to remote reset/enable the cpu via jtag +\twire jtag_cpu_en, jtag_system_reset; "; - my @chains = (sort { $b <=> $a } keys %jtag_info); - my $altera=0; - my $xilinx=0; - my $glob_en; - foreach my $c (@chains){ - my $xilinx_jtag_ctrl_in; - my $xilinx_jtag_ctrl_out; - my $r = $jtag_info{$c}{'wire'}; - my $index = $jtag_info{$c}{'index'}; - - my @array = (defined $r)? @{$r} :(); - my $wires_def = join ("\n",@array); - $jtag_v=$jtag_v."\n//\tJtag chain $c Wire def\n$wires_def\n" if(@array); - $r= $jtag_info{$c}{'altera_num'}; - @array = (defined $r)? @{$r} :(); - my $altera_jtag_ctrl =(@array)? scalar @array : 0; - $r= $jtag_info{$c}{'xilinx_num'}; - @array = (defined $r)? @{$r} :(); - my $xilinx_jtag_ctrl =(@array)? scalar @array : 0; - $altera+=$altera_jtag_ctrl; - $xilinx+=$xilinx_jtag_ctrl; - if ($xilinx_jtag_ctrl>0){ - $r=$jtag_info{$c}{'input'}; - @array = (defined $r)? @{$r} :(); - $xilinx_jtag_ctrl_in = ($xilinx_jtag_ctrl!=1)? '{'.join(',',@array).'}' : $array[0]; - $r=$jtag_info{$c}{'output'}; - @array = (defined $r)? @{$r} :(); - $xilinx_jtag_ctrl_out= ($xilinx_jtag_ctrl!=1)? '{'.join(',',@array).'}' : $array[0]; - my $ctrl = (defined $glob_en)? " - .system_reset( ), - .cpu_en( ), - " : "//The global reset/enable signals are connected to the tap with the largest jtag chain number - .system_reset(jtag_system_reset), - .cpu_en(jtag_cpu_en), - "; - - - - - $glob_en=1; - $jtag_v=$jtag_v." - xilinx_jtag_wb #( - .JTAG_CHAIN($c), - .JWB_NUM($xilinx_jtag_ctrl) - ) - jwb_$c - ( - $ctrl - .reset(jtag_debug_reset_in), - .wb_to_jtag_all($xilinx_jtag_ctrl_out), - .jtag_to_wb_all($xilinx_jtag_ctrl_in) - ); -"; - - - } - - }#for - - if($altera>0 && $xilinx>0){ - my $r = $jtag_info{0}{'inst'}; - my @array = (defined $r)? @{$r} :(); - my $inst=join ("\n\t",@array); - add_colored_info($txview,"Found JTAG communication ports from different FPGA vendors:\n$inst.",'red'); - } - elsif($altera>0){ - $jtag_v=$jtag_v." - jtag_system_en #( - .FPGA_VENDOR(\"ALTERA\") - ) jtag_en ( - .cpu_en(jtag_cpu_en), - .system_reset(jtag_system_reset) - - ); - "; - } - - elsif($altera==0 && $xilinx==0){ - $jtag_v=$jtag_v." - //No jtag connection has found in the design - jtag_system_en #( - .FPGA_VENDOR(FPGA_VENDOR) - ) jtag_en ( - .cpu_en(jtag_cpu_en), - .system_reset(jtag_system_reset) - - ); -"; - - - } - -return $jtag_v; - + my @chains = (sort { $b <=> $a } keys %jtag_info); + my $altera=0; + my $xilinx=0; + my $glob_en; + foreach my $c (@chains){ + my $xilinx_jtag_ctrl_in; + my $xilinx_jtag_ctrl_out; + my $r = $jtag_info{$c}{'wire'}; + my $index = $jtag_info{$c}{'index'}; + my @array = (defined $r)? @{$r} :(); + my $wires_def = join ("\n",@array); + $jtag_v=$jtag_v."\n//\tJtag chain $c Wire def\n$wires_def\n" if(@array); + $r= $jtag_info{$c}{'altera_num'}; + @array = (defined $r)? @{$r} :(); + my $altera_jtag_ctrl =(@array)? scalar @array : 0; + $r= $jtag_info{$c}{'xilinx_num'}; + @array = (defined $r)? @{$r} :(); + my $xilinx_jtag_ctrl =(@array)? scalar @array : 0; + $altera+=$altera_jtag_ctrl; + $xilinx+=$xilinx_jtag_ctrl; + if ($xilinx_jtag_ctrl>0){ + $r=$jtag_info{$c}{'input'}; + @array = (defined $r)? @{$r} :(); + $xilinx_jtag_ctrl_in = ($xilinx_jtag_ctrl!=1)? '{'.join(',',@array).'}' : $array[0]; + $r=$jtag_info{$c}{'output'}; + @array = (defined $r)? @{$r} :(); + $xilinx_jtag_ctrl_out= ($xilinx_jtag_ctrl!=1)? '{'.join(',',@array).'}' : $array[0]; + my $ctrl = (defined $glob_en)? " + .system_reset( ), + .cpu_en( ), + " : "//The global reset/enable signals are connected to the tap with the largest jtag chain number + .system_reset(jtag_system_reset), + .cpu_en(jtag_cpu_en), + "; + $glob_en=1; + $jtag_v=$jtag_v." + xilinx_jtag_wb #( + .JTAG_CHAIN($c), + .JWB_NUM($xilinx_jtag_ctrl) + ) + jwb_$c + ( + $ctrl + .reset(jtag_debug_reset_in), + .wb_to_jtag_all($xilinx_jtag_ctrl_out), + .jtag_to_wb_all($xilinx_jtag_ctrl_in) + ); +"; + } + }#for + if($altera>0 && $xilinx>0){ + my $r = $jtag_info{0}{'inst'}; + my @array = (defined $r)? @{$r} :(); + my $inst=join ("\n\t",@array); + add_colored_info($txview,"Found JTAG communication ports from different FPGA vendors:\n$inst.",'red'); + } + elsif($altera>0){ + $jtag_v=$jtag_v." + jtag_system_en #( + .FPGA_VENDOR(\"ALTERA\") + ) jtag_en ( + .cpu_en(jtag_cpu_en), + .system_reset(jtag_system_reset) + ); + "; + } + elsif($altera==0 && $xilinx==0){ + $jtag_v=$jtag_v." + //No jtag connection has found in the design + jtag_system_en #( + .FPGA_VENDOR(FPGA_VENDOR) + ) jtag_en ( + .cpu_en(jtag_cpu_en), + .system_reset(jtag_system_reset) + ); +"; + } +return $jtag_v; } - - - sub get_functions{ - my $p=' -//functions - function integer log2; - input integer number; begin - log2=0; - while(2**log2mpsoc_get_tile_soc_name($tile); - if(defined $soc_name) { - my $param= gen_soc_param($mpsoc,$soc_name,$soc_num,$tile); - $socs_param=$socs_param.$param; - } - }#$tile - $socs_param="$socs_param \n"; - return $socs_param; + my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile); + if(defined $soc_name) { + my $param= gen_soc_param($mpsoc,$soc_name,$soc_num,$tile); + $socs_param=$socs_param.$param; + } + }#$tile + $socs_param="$socs_param \n"; + return $socs_param; } - sub gen_soc_param { - my ($mpsoc,$soc_name,$soc_num,$tile_num)=@_; - my $top=$mpsoc->mpsoc_get_soc($soc_name); - my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); - my %params; - #if ($setting eq 'Custom'){ - %params= $top->top_get_custom_soc_param($tile_num); - #}else{ - # %params=$top->top_get_default_soc_param(); - #} - my $params="\n\t //Parameter setting for $soc_name located in tile: $tile_num \n"; - $params{'CORE_ID'}=$tile_num; - foreach my $p (get_param_list_in_order(\%params)){ - $params{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$params{$p}); - - $params="$params\t localparam T${tile_num}_$p=$params{$p};\n"; - } - return $params; + my ($mpsoc,$soc_name,$soc_num,$tile_num)=@_; + my $top=$mpsoc->mpsoc_get_soc($soc_name); + my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); + my %params; + #if ($setting eq 'Custom'){ + %params= $top->top_get_custom_soc_param($tile_num); + #}else{ + # %params=$top->top_get_default_soc_param(); + #} + my $params="\n\t //Parameter setting for $soc_name located in tile: $tile_num \n"; + $params{'CORE_ID'}=$tile_num; + foreach my $p (get_param_list_in_order(\%params)){ + $params{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$params{$p}); + $params="$params\t localparam T${tile_num}_$p=$params{$p};\n"; + } + return $params; } - - sub gen_noc_param_v{ - my ($mpsoc,$sample,$noc_id)=@_; - $noc_id="" if(!defined $noc_id); - my $noc_param = "noc_param$noc_id"; - my $param_v="\n\n//NoC parameters\n"; - my $pass_param=""; - my @params=$mpsoc->object_get_attribute_order($noc_param); - my $custom_topology = $mpsoc->object_get_attribute($noc_param,'CUSTOM_TOPOLOGY_NAME'); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); - my %noc_info; - my $hashref= $mpsoc->object_get_attribute('noc_param_comments'); - my %comments = %{$hashref} if defined $hashref; - - if(defined $sample ){ - my $ref=$mpsoc->object_get_attribute($sample,"noc_info"); - %noc_info= %$ref; - ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_from_parameters($ref); - } - - foreach my $p (@params){ - - my $val= (defined $sample) ? $noc_info{$p} :$mpsoc->object_get_attribute($noc_param,$p); - next if($p eq "CUSTOM_TOPOLOGY_NAME"); - $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); - if($p eq 'MCAST_ENDP_LIST'){ - - $val="$NE".$val; - } - - $param_v= $param_v."\tlocalparam $p=$val;\n"; - my $comment=$comments{$p}; - if(defined $comment){ - $comment=~ s/\n/\n \/\//g; - $param_v.=" //$p : $comment\n\n"; - } - $pass_param=$pass_param."\t\t.$p($p),\n"; - #print "$p:$val\n"; - - } - my $class=$mpsoc->object_get_attribute($noc_param,"C"); - my $str; - if( $class > 1){ - for (my $i=0; $i<=$class-1; $i++){ - my $n="Cn_$i"; - my $val=$mpsoc->object_get_attribute('class_param',$n); - $param_v=$param_v."\tlocalparam $n=$val;\n"; - } - $str="CLASS_SETTING={"; - for (my $i=$class-1; $i>=0;$i--){ - $str=($i==0)? "${str}Cn_0};\n " : "${str}Cn_$i,"; - } - }else { - $str="CLASS_SETTING={V{1\'b1}};\n"; - } - $param_v=$param_v."\tlocalparam $str"; - $pass_param=$pass_param."\t\t.CLASS_SETTING(CLASS_SETTING),\n"; - my $v=$mpsoc->object_get_attribute($noc_param,"V")-1; - my $escape=$mpsoc->object_get_attribute($noc_param,"ESCAP_VC_MASK"); - if (! defined $escape){ - $param_v=$param_v."\tlocalparam [$v :0] ESCAP_VC_MASK=1;\n"; - $pass_param=$pass_param.".\t\tESCAP_VC_MASK(ESCAP_VC_MASK),\n"; - } - $param_v=$param_v." \tlocalparam CVw=(C==0)? V : C * V;\n"; - $pass_param=$pass_param."\t\t.CVw(CVw)\n"; - return ($param_v,$pass_param); - + my ($mpsoc,$sample,$noc_id)=@_; + $noc_id="" if(!defined $noc_id); + my $noc_param = "noc_param$noc_id"; + my $param_v="\n\n//NoC parameters\n"; + my $pass_param=""; + my @params=$mpsoc->object_get_attribute_order($noc_param); + my $custom_topology = $mpsoc->object_get_attribute($noc_param,'CUSTOM_TOPOLOGY_NAME'); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); + my %noc_info; + my $hashref= $mpsoc->object_get_attribute('noc_param_comments'); + my %comments = %{$hashref} if defined $hashref; + if(defined $sample ){ + my $ref=$mpsoc->object_get_attribute($sample,"noc_info"); + %noc_info= %$ref; + ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_from_parameters($ref); + } + foreach my $p (@params){ + my $val= (defined $sample) ? $noc_info{$p} :$mpsoc->object_get_attribute($noc_param,$p); + next if($p eq "CUSTOM_TOPOLOGY_NAME"); + $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); + if($p eq 'MCAST_ENDP_LIST'){ + $val="$NE".$val; + } + $param_v= $param_v."\tlocalparam $p=$val;\n"; + my $comment=$comments{$p}; + if(defined $comment){ + $comment=~ s/\n/\n \/\//g; + $param_v.=" //$p : $comment\n\n"; + } + $pass_param=$pass_param."\t\t.$p($p),\n"; + #print "$p:$val\n"; + } + my $class=$mpsoc->object_get_attribute($noc_param,"C"); + my $str; + if( $class > 1){ + for (my $i=0; $i<=$class-1; $i++){ + my $n="Cn_$i"; + my $val=$mpsoc->object_get_attribute('class_param',$n); + $param_v=$param_v."\tlocalparam $n=$val;\n"; + } + $str="CLASS_SETTING={"; + for (my $i=$class-1; $i>=0;$i--){ + $str=($i==0)? "${str}Cn_0};\n " : "${str}Cn_$i,"; + } + }else { + $str="CLASS_SETTING={V{1\'b1}};\n"; + } + $param_v=$param_v."\tlocalparam $str"; + $pass_param=$pass_param."\t\t.CLASS_SETTING(CLASS_SETTING),\n"; + my $v=$mpsoc->object_get_attribute($noc_param,"V")-1; + my $escape=$mpsoc->object_get_attribute($noc_param,"ESCAP_VC_MASK"); + if (! defined $escape){ + $param_v=$param_v."\tlocalparam [$v :0] ESCAP_VC_MASK=1;\n"; + $pass_param=$pass_param.".\t\tESCAP_VC_MASK(ESCAP_VC_MASK),\n"; + } + $param_v=$param_v." \tlocalparam CVw=(C==0)? V : C * V;\n"; + $pass_param=$pass_param."\t\t.CVw(CVw)\n"; + return ($param_v,$pass_param); } - sub gen_noc_param_h{ - my $mpsoc=shift; - my $param_h="\n\n//NoC parameters\n"; - - my $topology = $mpsoc->object_get_attribute('noc_param','TOPOLOGY'); - $topology =~ s/"//g; - $param_h.="\t#define IS_${topology}\n"; - - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); - - - - - my @params=$mpsoc->object_get_attribute_order('noc_param'); - my $custom_topology = $mpsoc->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); - foreach my $p (@params){ - my $val=$mpsoc->object_get_attribute('noc_param',$p); - next if($p eq "CUSTOM_TOPOLOGY_NAME"); - next if($p eq "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"); - $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); - if($p eq "MCAST_ENDP_LIST" || $p eq "ESCAP_VC_MASK"){ - $val="$NE".$val if($p eq 'MCAST_ENDP_LIST'); - $val =~ s/\'/\\\'/g; - $val="\"$val\""; - } - - $param_h=$param_h."\t#define $p\t$val\n"; - - #print "$p:$val\n"; - - } - my $class=$mpsoc->object_get_attribute('noc_param',"C"); - my $str; - if( $class > 1){ - for (my $i=0; $i<=$class-1; $i++){ - my $n="Cn_$i"; - my $val=$mpsoc->object_get_attribute('class_param',$n); - $param_h=$param_h."\t#define $n\t$val\n"; - } - $str="CLASS_SETTING {"; - for (my $i=$class-1; $i>=0;$i--){ - $str=($i==0)? "${str}Cn_0};\n " : "${str}Cn_$i,"; - } - }else { - $str="CLASS_SETTING={V{1\'b1}}\n"; - } - #add_text_to_string (\$param_h,"\t#define $str"); - - my $v=$mpsoc->object_get_attribute('noc_param',"V")-1; - my $escape=$mpsoc->object_get_attribute('noc_param',"ESCAP_VC_MASK"); - if (! defined $escape){ - #add_text_to_string (\$param_h,"\tlocalparam [$v :0] ESCAP_VC_MASK=1;\n"); - #add_text_to_string (\$pass_param,".ESCAP_VC_MASK(ESCAP_VC_MASK),\n"); - } - #add_text_to_string (\$param_h," \tlocalparam CVw=(C==0)? V : C * V;\n"); - #add_text_to_string (\$pass_param,".CVw(CVw)\n"); - - - #remove 'b and 'h - #$param_h =~ s/\d\'b/ /g; - #$param_h =~ s/\'h/ /g; - - return $param_h; + my $mpsoc=shift; + my $param_h="\n\n//NoC parameters\n"; + my $topology = $mpsoc->object_get_attribute('noc_param','TOPOLOGY'); + $topology =~ s/"//g; + $param_h.="\t#define IS_${topology}\n"; + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); + my @params=$mpsoc->object_get_attribute_order('noc_param'); + my $custom_topology = $mpsoc->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); + foreach my $p (@params){ + my $val=$mpsoc->object_get_attribute('noc_param',$p); + next if($p eq "CUSTOM_TOPOLOGY_NAME"); + next if($p eq "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"); + $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); + if($p eq "MCAST_ENDP_LIST" || $p eq "ESCAP_VC_MASK"){ + $val="$NE".$val if($p eq 'MCAST_ENDP_LIST'); + $val =~ s/\'/\\\'/g; + $val="\"$val\""; + } + $param_h=$param_h."\t#define $p\t$val\n"; + #print "$p:$val\n"; + } + my $class=$mpsoc->object_get_attribute('noc_param',"C"); + my $str; + if( $class > 1){ + for (my $i=0; $i<=$class-1; $i++){ + my $n="Cn_$i"; + my $val=$mpsoc->object_get_attribute('class_param',$n); + $param_h=$param_h."\t#define $n\t$val\n"; + } + $str="CLASS_SETTING {"; + for (my $i=$class-1; $i>=0;$i--){ + $str=($i==0)? "${str}Cn_0};\n " : "${str}Cn_$i,"; + } + }else { + $str="CLASS_SETTING={V{1\'b1}}\n"; + } + #add_text_to_string (\$param_h,"\t#define $str"); + my $v=$mpsoc->object_get_attribute('noc_param',"V")-1; + my $escape=$mpsoc->object_get_attribute('noc_param',"ESCAP_VC_MASK"); + if (! defined $escape){ + #add_text_to_string (\$param_h,"\tlocalparam [$v :0] ESCAP_VC_MASK=1;\n"); + #add_text_to_string (\$pass_param,".ESCAP_VC_MASK(ESCAP_VC_MASK),\n"); + } + #add_text_to_string (\$param_h," \tlocalparam CVw=(C==0)? V : C * V;\n"); + #add_text_to_string (\$pass_param,".CVw(CVw)\n"); + #remove 'b and 'h + #$param_h =~ s/\d\'b/ /g; + #$param_h =~ s/\'h/ /g; + return $param_h; } - - - - sub gen_noc_v{ - my ($mpsoc,$pass_param) = @_; - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); - - + my ($mpsoc,$pass_param) = @_; + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); my $noc_clk = $mpsoc->object_get_attribute('SOURCE_SET_CONNECT',"NoC_clk"); - my $noc_reset = $mpsoc->object_get_attribute('SOURCE_SET_CONNECT',"NoC_reset"); - $noc_clk = 'clk0' if(!defined $noc_clk ); - $noc_reset = 'reset0' if(!defined $noc_reset); - - my $noc_v=" - - //connection wire to NoC - smartflit_chanel_t ni_chan_in [NE-1 : 0]; - smartflit_chanel_t ni_chan_out [NE-1 : 0]; - - wire noc_clk_in,noc_reset_in; - + my $noc_reset = $mpsoc->object_get_attribute('SOURCE_SET_CONNECT',"NoC_reset"); + $noc_clk = 'clk0' if(!defined $noc_clk ); + $noc_reset = 'reset0' if(!defined $noc_reset); + my $noc_v=" + //connection wire to NoC + smartflit_chanel_t ni_chan_in [NE-1 : 0]; + smartflit_chanel_t ni_chan_out [NE-1 : 0]; + wire noc_clk_in,noc_reset_in; //NoC - noc_top # ( - .NOC_ID(NOC_ID) - ) the_noc ( - .reset(noc_reset_in), - .clk(noc_clk_in), - .chan_in_all(ni_chan_out), - .chan_out_all(ni_chan_in), - .router_event( ) - ); - - clk_source src ( - .clk_in($noc_clk), - .clk_out(noc_clk_in), - .reset_in($noc_reset), - .reset_out(noc_reset_in) - ); + noc_top # ( + .NOC_ID(NOC_ID) + ) the_noc ( + .reset(noc_reset_in), + .clk(noc_clk_in), + .chan_in_all(ni_chan_out), + .chan_out_all(ni_chan_in), + .router_event( ) + ); + clk_source src ( + .clk_in($noc_clk), + .clk_out(noc_clk_in), + .reset_in($noc_reset), + .reset_out(noc_reset_in) + ); "; - ; - return $noc_v; - + return $noc_v; } - - - sub gen_socs_v{ - my ($mpsoc,$top_ip,$sw_dir,$txview)=@_; - - #add clk reset signals - my ($sourc_short, $source_full)=add_sources_to_top_ip($mpsoc,$top_ip); - - - my $io_short=$sourc_short; - my $top_io_short="\tjtag_debug_reset_in"; - - -# my $jtag_def="// Allow software to remote reset/enable the cpu via jtag -#\twire jtag_cpu_en, jtag_system_reset; + my ($mpsoc,$top_ip,$sw_dir,$txview)=@_; + #add clk reset signals + my ($sourc_short, $source_full)=add_sources_to_top_ip($mpsoc,$top_ip); + my $io_short=$sourc_short; + my $top_io_short="\tjtag_debug_reset_in"; +# my $jtag_def="// Allow software to remote reset/enable the cpu via jtag +#\twire jtag_cpu_en, jtag_system_reset; #\twire processors_en_anded_jtag = processors_en & jtag_cpu_en; -# +# #"; - - my $io_full=$source_full; - my $top_io_full= "\tinput jtag_debug_reset_in;\n"; - my $top_io_pass="//"; - - my %jtag_info; - %jtag_info=append_to_hash (\%jtag_info,0,'wire',"wire processors_en_anded_jtag = processors_en & jtag_cpu_en;\n"); - #my $altera_jtag_ctrl=0; - #my $xilinx_jtag_ctrl=0; #if it becomes larger than 0 then add jtag to wb module - #my $jtag_insts=""; - #my $xilinx_jtag_ctrl_in=""; - #my $xilinx_jtag_ctrl_out=""; - - - my $socs_v=""; - my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); - - - my $processors_en=0; - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); - - if(defined $soc_name) { - my ($soc_v,$en,$io_short1,$io_full1,$top_io_short1,$top_io_full1,$top_io_pass1,$ref)= - gen_soc_v($mpsoc,$top_ip,$sw_dir,$soc_name,$tile_num,$soc_num,$txview,\%jtag_info); - %jtag_info=%{$ref}; - $socs_v=$socs_v.$soc_v; - $io_short = $io_short .$io_short1; - $io_full = $io_full .$io_full1; - $top_io_short= $top_io_short.$top_io_short1; - $top_io_full = $top_io_full. $top_io_full1; - $top_io_pass = $top_io_pass. $top_io_pass1; - # $jtag_def = $jtag_def .$jtag_def1; - # $jtag_insts=$jtag_insts.$jtag_insts1; - # $altera_jtag_ctrl+=$altera_jtag_ctrl1; - # $xilinx_jtag_ctrl+=$xilinx_jtag_ctrl1; - # $xilinx_jtag_ctrl_in =(length ($xilinx_jtag_ctrl_in )>2)? "$xilinx_jtag_ctrl_in,$xilinx_jtag_ctrl_in1" : $xilinx_jtag_ctrl_in.$xilinx_jtag_ctrl_in1; - # $xilinx_jtag_ctrl_out=(length ($xilinx_jtag_ctrl_out)>2)? "$xilinx_jtag_ctrl_out,$xilinx_jtag_ctrl_out1" :$xilinx_jtag_ctrl_out.$xilinx_jtag_ctrl_out1; - - $processors_en|=$en; - - }else{ - #this tile is not connected to any ip. the noc input ports will be connected to ground - my $soc_v="\n\n // Tile:$tile_num is not assigned to any ip\n"; - $soc_v="$soc_v - - assign ni_credit_out[$tile_num]={V{1'b0}}; - assign ni_flit_out[$tile_num]={Fw{1'b0}}; - assign ni_flit_out_wr[$tile_num]=1'b0; - "; - $socs_v=$socs_v.$soc_v; - - } - - } - + my $io_full=$source_full; + my $top_io_full= "\tinput jtag_debug_reset_in;\n"; + my $top_io_pass="//"; + my %jtag_info; + %jtag_info=append_to_hash (\%jtag_info,0,'wire',"wire processors_en_anded_jtag = processors_en & jtag_cpu_en;\n"); + #my $altera_jtag_ctrl=0; + #my $xilinx_jtag_ctrl=0; #if it becomes larger than 0 then add jtag to wb module + #my $jtag_insts=""; + #my $xilinx_jtag_ctrl_in=""; + #my $xilinx_jtag_ctrl_out=""; + my $socs_v=""; + my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); + my $processors_en=0; + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); + if(defined $soc_name) { + my ($soc_v,$en,$io_short1,$io_full1,$top_io_short1,$top_io_full1,$top_io_pass1,$ref)= + gen_soc_v($mpsoc,$top_ip,$sw_dir,$soc_name,$tile_num,$soc_num,$txview,\%jtag_info); + %jtag_info=%{$ref}; + $socs_v=$socs_v.$soc_v; + $io_short = $io_short .$io_short1; + $io_full = $io_full .$io_full1; + $top_io_short= $top_io_short.$top_io_short1; + $top_io_full = $top_io_full. $top_io_full1; + $top_io_pass = $top_io_pass. $top_io_pass1; + # $jtag_def = $jtag_def .$jtag_def1; + # $jtag_insts=$jtag_insts.$jtag_insts1; + # $altera_jtag_ctrl+=$altera_jtag_ctrl1; + # $xilinx_jtag_ctrl+=$xilinx_jtag_ctrl1; + # $xilinx_jtag_ctrl_in =(length ($xilinx_jtag_ctrl_in )>2)? "$xilinx_jtag_ctrl_in,$xilinx_jtag_ctrl_in1" : $xilinx_jtag_ctrl_in.$xilinx_jtag_ctrl_in1; + # $xilinx_jtag_ctrl_out=(length ($xilinx_jtag_ctrl_out)>2)? "$xilinx_jtag_ctrl_out,$xilinx_jtag_ctrl_out1" :$xilinx_jtag_ctrl_out.$xilinx_jtag_ctrl_out1; + $processors_en|=$en; + }else{ + #this tile is not connected to any ip. the noc input ports will be connected to ground + my $soc_v="\n\n // Tile:$tile_num is not assigned to any ip\n"; + $soc_v="$soc_v + assign ni_credit_out[$tile_num]={V{1'b0}}; + assign ni_flit_out[$tile_num]={Fw{1'b0}}; + assign ni_flit_out_wr[$tile_num]=1'b0; + "; + $socs_v=$socs_v.$soc_v; + } + } if($processors_en){ - $io_short=$io_short.",\n\tprocessors_en"; - $io_full=$io_full."\tinput processors_en;"; - $top_io_short=$top_io_short.",\n\tprocessors_en"; - $top_io_full=$top_io_full."\t input processors_en;"; - $top_io_pass=$top_io_pass.",\n\t\t.processors_en(processors_en_anded_jtag)"; - $top_ip->top_add_port('IO','processors_en','' ,'input','plug:enable[0]','enable_i'); - - } - - # $io_short=$io_short.",\n\tjtag_system_reset"; - # $io_full=$io_full."\n\tinput jtag_system_reset;"; - # $top_io_pass=$top_io_pass.",\n\t\t.jtag_system_reset(jtag_system_reset)"; - - - return ($socs_v,$io_short,$io_full,$top_io_short,$top_io_full,$top_io_pass,\%jtag_info); - + $io_short=$io_short.",\n\tprocessors_en"; + $io_full=$io_full."\tinput processors_en;"; + $top_io_short=$top_io_short.",\n\tprocessors_en"; + $top_io_full=$top_io_full."\t input processors_en;"; + $top_io_pass=$top_io_pass.",\n\t\t.processors_en(processors_en_anded_jtag)"; + $top_ip->top_add_port('IO','processors_en','' ,'input','plug:enable[0]','enable_i'); + } + # $io_short=$io_short.",\n\tjtag_system_reset"; + # $io_full=$io_full."\n\tinput jtag_system_reset;"; + # $top_io_pass=$top_io_pass.",\n\t\t.jtag_system_reset(jtag_system_reset)"; + return ($socs_v,$io_short,$io_full,$top_io_short,$top_io_full,$top_io_pass,\%jtag_info); } - - ############## -# gen_soc_v +# gen_soc_v ############## - - #$mpsoc,$top_ip,$sw_dir,$soc_name,$id,$soc_num,$txview sub gen_soc_v{ - my ($mpsoc,$top_ip,$sw_path,$soc_name,$tile_num,$soc_num,$txview,$href)=@_; - my %jtag_info = %{$href}; - - my $io_short=""; - my $io_full=""; - my $top_io_short=""; - my $top_io_full=""; - my $top_io_pass=""; - - - - my $processor_en=0; - - - - - - my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); - my $e_addr=endp_addr_encoder($mpsoc,$tile_num); - my $router_num = get_connected_router_id_to_endp($mpsoc,$tile_num); - my $r_addr=router_addr_encoder($mpsoc,$router_num); - - - - my $soc_v="\n\n // Tile:$tile_num ($e_addr)\n \t$soc_name #(\n"; - - # Global parameter - $soc_v=$soc_v."\t\t.CORE_ID($tile_num),\n\t\t.SW_LOC(\"$sw_path/tile$tile_num\")"; - - - # ni parameter - my $top=$mpsoc->mpsoc_get_soc($soc_name); - my @nis=get_NI_instance_list($top); - my @noc_param=$top->top_get_parameter_list($nis[0]); - my $inst_name=$top->top_get_def_of_instance($nis[0],'instance'); - - #other parameters - my %params=$top->top_get_default_soc_param(); - - - - foreach my $p (@noc_param){ - my $parm_next = $p; - $parm_next =~ s/${inst_name}_//; - my $param= ",\n\t\t.$p($parm_next)"; - $soc_v=$soc_v.$param; - } - foreach my $p (sort keys %params){ - my $parm_next= "T${tile_num}_$p"; - my $param= ",\n\t\t.$p($parm_next)"; - $soc_v=$soc_v.$param; - - } - - $soc_v=$soc_v."\n\t)the_${soc_name}_$soc_num(\n"; - - my @intfcs=$top->top_get_intfc_list(); - - my $i=0; - - my $dir = Cwd::getcwd(); - my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); - my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - my $soc_file="$target_dir/src_verilog/tiles/$soc_name.sv"; - - my $vdb =read_verilog_file($soc_file); - - my %soc_localparam = $vdb->get_modules_parameters($soc_name); - - - foreach my $intfc (@intfcs){ - - # ni intfc - if( $intfc eq 'socket:ni[0]'){ - my @ports=$top->top_get_intfc_ports_list($intfc); - - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - my $q= ($intfc_port eq "current_e_addr")? "$EAw\'d$e_addr" : - ($intfc_port eq "current_r_addr")? "$RAw\'d$r_addr" : - "ni_$intfc_port\[$tile_num\]"; - $soc_v=$soc_v.',' if ($i); - $soc_v=$soc_v."\n\t\t.$p($q)"; - $i=1; - - - } - } - # clk source - elsif( $intfc =~ /plug:clk\[/ ){ - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - $soc_v=$soc_v.',' if ($i); - my $src = $mpsoc->object_get_attribute('SOURCE_SET_CONNECT',"T${tile_num}_$p"); - $src = 'clk0' if(!defined $src); - $soc_v=$soc_v."\n\t\t.$p($src)"; - $i=1; - - } - } - #reset - elsif( $intfc =~ /plug:reset\[/){ - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - $soc_v=$soc_v.',' if ($i); - my $src = $mpsoc->object_get_attribute('SOURCE_SET_CONNECT',"T${tile_num}_$p"); - $src = 'reset0' if(!defined $src); - $soc_v=$soc_v."\n\t\t.$p(${src} )";#| jtag_system_reset)"; - $i=1; - - } - } - #enable - elsif( $intfc =~ /plug:enable\[/){ - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - $soc_v=$soc_v.',' if ($i); - $soc_v=$soc_v."\n\t\t.$p(processors_en)"; - $processor_en=1; - $i=1; - } - } - #RxD_sim - elsif( $intfc eq 'socket:RxD_sim[0]'){ - #This interface is for simulation only donot include it in top module - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - $soc_v=$soc_v.',' if ($i); - $soc_v=$soc_v."\n\t\t.$p( )"; - $i=1; - } - - } - #jtag_to_wb - elsif( $intfc =~ /socket:jtag_to_wb\[/){ #check JTAG connect parameter. if it is XILINX then connect it to jtag tap - my @ports=$top->top_get_intfc_ports_list($intfc); - - my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); - my %topparams; - #if ($setting eq 'Custom'){ - %topparams= $top->top_get_custom_soc_param($tile_num); - # }else{ - # %topparams=$top->top_get_default_soc_param(); - #} - - - #my $JTAG_CONNECT=$soc->soc_get_module_param_value ($id,'JTAG_CONNECT'); - - foreach my $p (@ports){ - my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - my $inst_name=$top->top_get_def_of_instance($id,'instance'); - my $JTAG_CONNECT= $topparams{"${inst_name}_JTAG_CONNECT"}; - my $chain=$topparams{"${inst_name}_JTAG_CHAIN"}; - my $index=$topparams{"${inst_name}_JTAG_INDEX"}; - #print Dumper (\%topparams); - #print "my $JTAG_CONNECT= \$topparams{${inst_name}_JTAG_CONNECT}\n"; - - #print "$inst,$range,$type,$intfc_name,$intfc_port-> $JTAG_CONNECT;"; - if($JTAG_CONNECT =~ /XILINX_JTAG_WB/){ - - my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); - my $port_def=(length ($new_range)>1 )? "\t$type\t [ $new_range ] $io_port;\n": "\t$type\t\t\t$io_port;\n"; - $top_ip->top_add_port("T${tile_num}" ,$io_port, $new_range ,$type,$intfc_name,$intfc_port); - - my $wire_def=(length ($new_range)>1 )? "\twire\t [ $new_range ] $io_port;": "\twire\t\t\t$io_port;"; - # my $new_range = add_instantc_name_to_parameters(\%params,"${soc_name}_$soc_num",$range); - - # $jtag_def=$jtag_def."$wire_def"; - %jtag_info=append_to_hash (\%jtag_info,$chain,'wire',"$wire_def"); - - - $soc_v=$soc_v.',' if ($i); - $soc_v=$soc_v."\n\t\t.$p($io_port)"; - $i=1; - if($type eq 'input'){ - %jtag_info=check_jtag_indexs(\%jtag_info,$chain,$index,$txview,$inst_name,$tile_num); - #$jtag_insts=$jtag_insts."$id XILINX JTAG,"; - %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id XILINX JTAG"); - #$xilinx_jtag_ctrl++; - %jtag_info=append_to_hash (\%jtag_info,$chain,'xilinx_num',1); - #$xilinx_jtag_ctrl_in=(length ($xilinx_jtag_ctrl_in)>2)? "$xilinx_jtag_ctrl_in,$io_port" : "$io_port"; - %jtag_info=append_to_hash (\%jtag_info,$chain,'input',$io_port); - }else { - #$xilinx_jtag_ctrl_out=(length($xilinx_jtag_ctrl_out)>2)? "$xilinx_jtag_ctrl_out,$io_port" : "$io_port"; - %jtag_info=append_to_hash (\%jtag_info,$chain,'output',$io_port); - } - $io_short=$io_short.",\n\t$io_port"; - $io_full=$io_full."$port_def"; - $top_io_pass=$top_io_pass.",\n\t\t.$io_port($io_port)"; -# - }else{#Dont not connect - $soc_v=$soc_v.',' if ($i); - $soc_v=$soc_v."\n\t\t.$p( )"; - $i=1; - } - - if($JTAG_CONNECT =~ /ALTERA_JTAG_WB/){ - if($type eq 'input'){ - #$jtag_insts=$jtag_insts."$id ALTERA JTAG,"; - #$altera_jtag_ctrl++; - %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id ALTERA JTAG"); - %jtag_info=append_to_hash (\%jtag_info,0,'altera_num',1); - %jtag_info=check_jtag_indexs(\%jtag_info,0,$index,$txview,$inst_name,$tile_num); - - } - } - - } - - } - - else { - #other interface - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); - - $io_short=$io_short.",\n\t$io_port"; - $top_io_short=$top_io_short.",\n\t$io_port"; - $top_io_pass=$top_io_pass.",\n\t\t.$io_port($io_port)"; - #io definition - #my $new_range = add_instantc_name_to_parameters(\%params,"${soc_name}_$soc_num",$range); - my $port_def=(length ($new_range)>1 )? "\t$type\t [ $new_range ] $io_port;\n": "\t$type\t\t\t$io_port;\n"; - $top_ip->top_add_port("T${tile_num}" ,$io_port, $new_range ,$type,$intfc_name,$intfc_port); - - $io_full=$io_full."$port_def"; - $top_io_full=$top_io_full."$port_def"; - $soc_v=$soc_v.',' if ($i); - $soc_v=$soc_v."\n\t\t.$p($io_port)"; - $i=1; - - } - } - } - - - - $soc_v=$soc_v."\n\t);\n"; - - - return ($soc_v,$processor_en,$io_short,$io_full,$top_io_short, $top_io_full,$top_io_pass,\%jtag_info); - + my ($mpsoc,$top_ip,$sw_path,$soc_name,$tile_num,$soc_num,$txview,$href)=@_; + my %jtag_info = %{$href}; + my $io_short=""; + my $io_full=""; + my $top_io_short=""; + my $top_io_full=""; + my $top_io_pass=""; + my $processor_en=0; + my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); + my $e_addr=endp_addr_encoder($mpsoc,$tile_num); + my $router_num = get_connected_router_id_to_endp($mpsoc,$tile_num); + my $r_addr=router_addr_encoder($mpsoc,$router_num); + my $soc_v="\n\n // Tile:$tile_num ($e_addr)\n \t$soc_name #(\n"; + # Global parameter + $soc_v=$soc_v."\t\t.CORE_ID($tile_num),\n\t\t.SW_LOC(\"$sw_path/tile$tile_num\")"; + # ni parameter + my $top=$mpsoc->mpsoc_get_soc($soc_name); + my @nis=get_NI_instance_list($top); + my @noc_param=$top->top_get_parameter_list($nis[0]); + my $inst_name=$top->top_get_def_of_instance($nis[0],'instance'); + #other parameters + my %params=$top->top_get_default_soc_param(); + foreach my $p (@noc_param){ + my $parm_next = $p; + $parm_next =~ s/${inst_name}_//; + my $param= ",\n\t\t.$p($parm_next)"; + $soc_v=$soc_v.$param; + } + foreach my $p (sort keys %params){ + my $parm_next= "T${tile_num}_$p"; + my $param= ",\n\t\t.$p($parm_next)"; + $soc_v=$soc_v.$param; + } + $soc_v=$soc_v."\n\t)the_${soc_name}_$soc_num(\n"; + my @intfcs=$top->top_get_intfc_list(); + my $i=0; + my $dir = Cwd::getcwd(); + my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); + my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + my $soc_file="$target_dir/src_verilog/tiles/$soc_name.sv"; + my $vdb =read_verilog_file($soc_file); + my %soc_localparam = $vdb->get_modules_parameters($soc_name); + foreach my $intfc (@intfcs){ + # ni intfc + if( $intfc eq 'socket:ni[0]'){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + my $q= ($intfc_port eq "current_e_addr")? "$EAw\'d$e_addr" : + ($intfc_port eq "current_r_addr")? "$RAw\'d$r_addr" : + "ni_$intfc_port\[$tile_num\]"; + $soc_v=$soc_v.',' if ($i); + $soc_v=$soc_v."\n\t\t.$p($q)"; + $i=1; + } + } + # clk source + elsif( $intfc =~ /plug:clk\[/ ){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + $soc_v=$soc_v.',' if ($i); + my $src = $mpsoc->object_get_attribute('SOURCE_SET_CONNECT',"T${tile_num}_$p"); + $src = 'clk0' if(!defined $src); + $soc_v=$soc_v."\n\t\t.$p($src)"; + $i=1; + } + } + #reset + elsif( $intfc =~ /plug:reset\[/){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + $soc_v=$soc_v.',' if ($i); + my $src = $mpsoc->object_get_attribute('SOURCE_SET_CONNECT',"T${tile_num}_$p"); + $src = 'reset0' if(!defined $src); + $soc_v=$soc_v."\n\t\t.$p(${src} )";#| jtag_system_reset)"; + $i=1; + } + } + #enable + elsif( $intfc =~ /plug:enable\[/){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + $soc_v=$soc_v.',' if ($i); + $soc_v=$soc_v."\n\t\t.$p(processors_en)"; + $processor_en=1; + $i=1; + } + } + #RxD_sim + elsif( $intfc eq 'socket:RxD_sim[0]'){ + #This interface is for simulation only donot include it in top module + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + $soc_v=$soc_v.',' if ($i); + $soc_v=$soc_v."\n\t\t.$p( )"; + $i=1; + } + } + #jtag_to_wb + elsif( $intfc =~ /socket:jtag_to_wb\[/){ #check JTAG connect parameter. if it is XILINX then connect it to jtag tap + my @ports=$top->top_get_intfc_ports_list($intfc); + my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); + my %topparams; + #if ($setting eq 'Custom'){ + %topparams= $top->top_get_custom_soc_param($tile_num); + # }else{ + # %topparams=$top->top_get_default_soc_param(); + #} + #my $JTAG_CONNECT=$soc->soc_get_module_param_value ($id,'JTAG_CONNECT'); + foreach my $p (@ports){ + my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + my $inst_name=$top->top_get_def_of_instance($id,'instance'); + my $JTAG_CONNECT= $topparams{"${inst_name}_JTAG_CONNECT"}; + my $chain=$topparams{"${inst_name}_JTAG_CHAIN"}; + my $index=$topparams{"${inst_name}_JTAG_INDEX"}; + #print Dumper (\%topparams); + #print "my $JTAG_CONNECT= \$topparams{${inst_name}_JTAG_CONNECT}\n"; + #print "$inst,$range,$type,$intfc_name,$intfc_port-> $JTAG_CONNECT;"; + if($JTAG_CONNECT =~ /XILINX_JTAG_WB/){ + my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); + my $port_def=(length ($new_range)>1 )? "\t$type\t [ $new_range ] $io_port;\n": "\t$type\t\t\t$io_port;\n"; + $top_ip->top_add_port("T${tile_num}" ,$io_port, $new_range ,$type,$intfc_name,$intfc_port); + my $wire_def=(length ($new_range)>1 )? "\twire\t [ $new_range ] $io_port;": "\twire\t\t\t$io_port;"; + # my $new_range = add_instantc_name_to_parameters(\%params,"${soc_name}_$soc_num",$range); + # $jtag_def=$jtag_def."$wire_def"; + %jtag_info=append_to_hash (\%jtag_info,$chain,'wire',"$wire_def"); + $soc_v=$soc_v.',' if ($i); + $soc_v=$soc_v."\n\t\t.$p($io_port)"; + $i=1; + if($type eq 'input'){ + %jtag_info=check_jtag_indexs(\%jtag_info,$chain,$index,$txview,$inst_name,$tile_num); + #$jtag_insts=$jtag_insts."$id XILINX JTAG,"; + %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id XILINX JTAG"); + #$xilinx_jtag_ctrl++; + %jtag_info=append_to_hash (\%jtag_info,$chain,'xilinx_num',1); + #$xilinx_jtag_ctrl_in=(length ($xilinx_jtag_ctrl_in)>2)? "$xilinx_jtag_ctrl_in,$io_port" : "$io_port"; + %jtag_info=append_to_hash (\%jtag_info,$chain,'input',$io_port); + }else { + #$xilinx_jtag_ctrl_out=(length($xilinx_jtag_ctrl_out)>2)? "$xilinx_jtag_ctrl_out,$io_port" : "$io_port"; + %jtag_info=append_to_hash (\%jtag_info,$chain,'output',$io_port); + } + $io_short=$io_short.",\n\t$io_port"; + $io_full=$io_full."$port_def"; + $top_io_pass=$top_io_pass.",\n\t\t.$io_port($io_port)"; +# + }else{#Dont not connect + $soc_v=$soc_v.',' if ($i); + $soc_v=$soc_v."\n\t\t.$p( )"; + $i=1; + } + if($JTAG_CONNECT =~ /ALTERA_JTAG_WB/){ + if($type eq 'input'){ + #$jtag_insts=$jtag_insts."$id ALTERA JTAG,"; + #$altera_jtag_ctrl++; + %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id ALTERA JTAG"); + %jtag_info=append_to_hash (\%jtag_info,0,'altera_num',1); + %jtag_info=check_jtag_indexs(\%jtag_info,0,$index,$txview,$inst_name,$tile_num); + } + } + } + } + else { + #other interface + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); + $io_short=$io_short.",\n\t$io_port"; + $top_io_short=$top_io_short.",\n\t$io_port"; + $top_io_pass=$top_io_pass.",\n\t\t.$io_port($io_port)"; + #io definition + #my $new_range = add_instantc_name_to_parameters(\%params,"${soc_name}_$soc_num",$range); + my $port_def=(length ($new_range)>1 )? "\t$type\t [ $new_range ] $io_port;\n": "\t$type\t\t\t$io_port;\n"; + $top_ip->top_add_port("T${tile_num}" ,$io_port, $new_range ,$type,$intfc_name,$intfc_port); + $io_full=$io_full."$port_def"; + $top_io_full=$top_io_full."$port_def"; + $soc_v=$soc_v.',' if ($i); + $soc_v=$soc_v."\n\t\t.$p($io_port)"; + $i=1; + } + } + } + $soc_v=$soc_v."\n\t);\n"; + return ($soc_v,$processor_en,$io_short,$io_full,$top_io_short, $top_io_full,$top_io_pass,\%jtag_info); } - sub check_jtag_indexs{ - my ($ref,$chain,$index,$txview,$inst_name,$core_id)=@_; - my %jtag_info = %{$ref} if (defined $ref); - - chomp $index; - # replace coreid parameter - ($index=$index)=~ s/CORE_ID/$core_id/g; - $index = eval $index; - my $inst1 =$jtag_info{$chain}{'index'}{$index}; - my $id1 = $jtag_info{$chain}{'core_id'}{$index}; - if (defined $inst1){ - add_colored_info($txview,"Error: The JTAG INDEX number $index in JTAG Chain $chain is not unique. The same index number is used in tile($id1):$inst1 & tile($core_id):$inst_name IPs. It should be used in only one module.\n",'red'); - } - $jtag_info{$chain}{'index'}{$index}=$inst_name; - $jtag_info{$chain}{'core_id'}{$index}=$core_id; - #print "\$jtag_info{$chain}{'index'}{$index}=$inst_name\n"; - return %jtag_info; + my ($ref,$chain,$index,$txview,$inst_name,$core_id)=@_; + my %jtag_info = %{$ref} if (defined $ref); + chomp $index; + # replace coreid parameter + ($index=$index)=~ s/CORE_ID/$core_id/g; + $index = eval $index; + my $inst1 =$jtag_info{$chain}{'index'}{$index}; + my $id1 = $jtag_info{$chain}{'core_id'}{$index}; + if (defined $inst1){ + add_colored_info($txview,"Error: The JTAG INDEX number $index in JTAG Chain $chain is not unique. The same index number is used in tile($id1):$inst1 & tile($core_id):$inst_name IPs. It should be used in only one module.\n",'red'); + } + $jtag_info{$chain}{'index'}{$index}=$inst_name; + $jtag_info{$chain}{'core_id'}{$index}=$core_id; + #print "\$jtag_info{$chain}{'index'}{$index}=$inst_name\n"; + return %jtag_info; } - - sub get_top_clk_setting{ - my $mpsoc=shift; + my $mpsoc=shift; #get mpsoc with clock setting interface - my $dir = Cwd::getcwd(); - my $soc =get_source_set_top($mpsoc); - + my $dir = Cwd::getcwd(); + my $soc =get_source_set_top($mpsoc); my @instances=$soc->soc_get_all_instances(); my $top_ip=ip_gen->top_gen_new(); my $body_v; - my $param_pass_v=""; + my $param_pass_v=""; my $io_sim_v; - my $io_top_sim_v; - my $core_id= 0 ; - my $param_as_in_v=""; - my $local_param_v_all=""; - my $inst_v_all=""; + my $io_top_sim_v; + my $core_id= 0 ; + my $param_as_in_v=""; + my $local_param_v_all=""; + my $inst_v_all=""; my $param_v_all=""; my $wire_def_v_all=""; - my $plugs_assign_v_all=""; - my $sockets_assign_v_all=""; - my $io_full_v_all=""; - my $io_top_full_v_all=""; - my $io_sim_v_all; - my $system_v_all=""; - - my $wires=soc->new_wires(); - my $intfc=interface->interface_new(); - my $clk_assigned_port; + my $plugs_assign_v_all=""; + my $sockets_assign_v_all=""; + my $io_full_v_all=""; + my $io_top_full_v_all=""; + my $io_sim_v_all; + my $system_v_all=""; + my $wires=soc->new_wires(); + my $intfc=interface->interface_new(); + my $clk_assigned_port; foreach my $id (@instances){ - my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, - $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires); - - #my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$system_v,$assigned_ports)=gen_module_inst($id,$soc,\$io_sim_v,\$io_top_sim_v,\$param_as_in_v,$top_ip,$intfc,$wires,\$param_pass_v,\$system_v); - my $inst = $soc->soc_get_instance_name($id); - if ($id ne 'TOP'){ - add_text_to_string(\$body_v,"/*******************\n*\n*\t$inst\n*\n*\n*********************/\n"); - add_text_to_string(\$system_v_all,"$system_v\n") if(defined($system_v)); - add_text_to_string(\$local_param_v_all,"$local_param_v\n") if(defined($local_param_v)); - add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); - add_text_to_string(\$inst_v_all,$inst_v) if(defined($inst_v)); - add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); - add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); - add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); - add_text_to_string(\$io_top_full_v_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); - $io_sim_v_all = (defined $io_sim_v_all )? "$io_sim_v_all,\n$io_sim_v" : $io_sim_v if(defined($io_sim_v)); - }else{ - add_text_to_string(\$system_v_all,"$system_v\n") if(defined($system_v)); - add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); - add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); - add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); - add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); - $io_sim_v_all = (defined $io_sim_v_all )? "$io_sim_v_all,\n$io_sim_v" : $io_sim_v if(defined($io_sim_v)); - add_text_to_string(\$io_top_full_v_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); - $clk_assigned_port= (defined $clk_assigned_port)? "$clk_assigned_port,\n$assigned_ports" : $assigned_ports if(defined $assigned_ports); - } - - } - - - - - - + my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, + $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires); + #my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$system_v,$assigned_ports)=gen_module_inst($id,$soc,\$io_sim_v,\$io_top_sim_v,\$param_as_in_v,$top_ip,$intfc,$wires,\$param_pass_v,\$system_v); + my $inst = $soc->soc_get_instance_name($id); + if ($id ne 'TOP'){ + add_text_to_string(\$body_v,"/*******************\n*\n*\t$inst\n*\n*\n*********************/\n"); + add_text_to_string(\$system_v_all,"$system_v\n") if(defined($system_v)); + add_text_to_string(\$local_param_v_all,"$local_param_v\n") if(defined($local_param_v)); + add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); + add_text_to_string(\$inst_v_all,$inst_v) if(defined($inst_v)); + add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); + add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); + add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); + add_text_to_string(\$io_top_full_v_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); + $io_sim_v_all = (defined $io_sim_v_all )? "$io_sim_v_all,\n$io_sim_v" : $io_sim_v if(defined($io_sim_v)); + }else{ + add_text_to_string(\$system_v_all,"$system_v\n") if(defined($system_v)); + add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); + add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); + add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); + add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); + $io_sim_v_all = (defined $io_sim_v_all )? "$io_sim_v_all,\n$io_sim_v" : $io_sim_v if(defined($io_sim_v)); + add_text_to_string(\$io_top_full_v_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); + $clk_assigned_port= (defined $clk_assigned_port)? "$clk_assigned_port,\n$assigned_ports" : $assigned_ports if(defined $assigned_ports); + } + } my $unused_wiers_v=assign_unconnected_wires($wires,$intfc); $unused_wiers_v= "" if(!defined $unused_wiers_v); - - my $soc_v = " - $system_v_all - $local_param_v_all - $wire_def_v_all - $unused_wiers_v - $inst_v_all - $plugs_assign_v_all - $sockets_assign_v_all - -"; - my $clk_io_full= $io_full_v_all; - my $clk_io_sim=$io_sim_v_all; - return ($soc_v,$clk_io_sim,$clk_io_full,$clk_assigned_port); - + my $soc_v = " + $system_v_all + $local_param_v_all + $wire_def_v_all + $unused_wiers_v + $inst_v_all + $plugs_assign_v_all + $sockets_assign_v_all + "; + my $clk_io_full= $io_full_v_all; + my $clk_io_sim=$io_sim_v_all; + return ($soc_v,$clk_io_sim,$clk_io_full,$clk_assigned_port); } sub get_top_port_io_info{ - my ($top,$port,$tile_num,$params_ref,$local_param_ref)=@_; - my %params =%{$params_ref} if(defined $params_ref); - my %localparams=%{$local_param_ref} if(defined $local_param_ref); - my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($port); - my $io_port="T${tile_num}_${port}"; + my ($top,$port,$tile_num,$params_ref,$local_param_ref)=@_; + my %params =%{$params_ref} if(defined $params_ref); + my %localparams=%{$local_param_ref} if(defined $local_param_ref); + my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($port); + my $io_port="T${tile_num}_${port}"; #resolve range parameter - if (defined $range ){ - my @a= split (/\b/,$range); - foreach my $l (@a){ - #if defined in parameter list ignore it - next if(defined $params{$l}); - ($range=$range)=~ s/\b$l\b/$localparams{$l}/g if(defined $localparams{$l}); - } - } - my $new_range = add_instantc_name_to_parameters(\%params,"T${tile_num}",$range); - return ($io_port,$type,$new_range,$intfc_name,$intfc_port); + if (defined $range ){ + my @a= split (/\b/,$range); + foreach my $l (@a){ + #if defined in parameter list ignore it + next if(defined $params{$l}); + ($range=$range)=~ s/\b$l\b/$localparams{$l}/g if(defined $localparams{$l}); + } + } + my $new_range = add_instantc_name_to_parameters(\%params,"T${tile_num}",$range); + return ($io_port,$type,$new_range,$intfc_name,$intfc_port); } - - - - - - - - 1 diff --git a/mpsoc/perl_gui/lib/perl/network_maker.pl b/mpsoc/perl_gui/lib/perl/network_maker.pl index c2b83cb..ffaf2c4 100644 --- a/mpsoc/perl_gui/lib/perl/network_maker.pl +++ b/mpsoc/perl_gui/lib/perl/network_maker.pl @@ -2,2688 +2,2037 @@ use strict; use warnings; use constant::boolean; - use Cwd 'abs_path'; use base 'Class::Accessor::Fast'; -require "widget.pl"; +require "widget.pl"; require "diagram.pl"; require "topology_verilog_gen.pl"; - use String::Scanf; # imports sscanf() - use FindBin; use lib $FindBin::Bin; use tsort; - use File::Basename; use Cwd 'abs_path'; __PACKAGE__->mk_accessors(qw{ - window - sourceview + window + sourceview }); my $NAME = 'Network_maker'; exit network_maker_main() unless caller; - sub network_maker_main { - my $app = __PACKAGE__->new(); - - my @parameters = ( - {param_name=> "V ", value=>2}, - {param_name=> "B ", value=>4}, - {param_name=> "C ", value=>2}, + my $app = __PACKAGE__->new(); + my @parameters = ( + {param_name=> "V ", value=>2}, + {param_name=> "B ", value=>4}, + {param_name=> "C ", value=>2}, {param_name=> "Fpay ", value=>32}, - {param_name=> "MUX_TYPE", value=>'"ONE_HOT"'}, + {param_name=> "MUX_TYPE", value=>'"ONE_HOT"'}, {param_name=> "VC_REALLOCATION_TYPE ", value=>'"NONATOMIC"'}, {param_name=> "COMBINATION_TYPE", value=>'"COMB_NONSPEC"'}, - {param_name=> "FIRST_ARBITER_EXT_P_EN ", value=>1}, + {param_name=> "FIRST_ARBITER_EXT_P_EN ", value=>1}, {param_name=> "CONGESTION_INDEX ", value=>7}, {param_name=> "DEBUG_EN", value=>0}, {param_name=> "AVC_ATOMIC_EN", value=>0}, {param_name=> "ADD_PIPREG_AFTER_CROSSBAR", value=>0}, {param_name=> "CVw", value=>"(C==0)? V : C * V"}, - {param_name=> "CLASS_SETTING ", value=>"{CVw{1\'b1}}"}, + {param_name=> "CLASS_SETTING ", value=>"{CVw{1\'b1}}"}, {param_name=> "SSA_EN", value=>'"NO"'}, - {param_name=> "SWA_ARBITER_TYPE ", value=>'"RRA"'}, - {param_name=> "WEIGHTw ", value=>7}, + {param_name=> "SWA_ARBITER_TYPE ", value=>'"RRA"'}, + {param_name=> "WEIGHTw ", value=>7}, {param_name=> "MIN_PCK_SIZE", value=>2}, {param_name=> "BYTE_EN", value=>0} -); - -my @ports =( - {name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw", pname=> "flit_in", pconnect=>"flit_out", endp=>"yes"}, - {name=> "flit_in_wr_all", type=>"input", width=>"P", connect=>"flit_out_wr_all", pwidth=>1, pname=> "flit_in_wr", pconnect=>"flit_out_wr",endp=>"yes"}, - {name=> "congestion_in_all", type=>"input", width=>"CONG_ALw", connect=>"congestion_out_all", pwidth=>"CONGw", pname=> "congestion_in", pconnect=>"congestion_out",endp=>"no"}, - {name=> "credit_out_all", type=>"output", width=>"PV", connect=>"credit_in_all", pwidth=>"V" ,pname=> "credit_out", pconnect=>"credit_in",endp=>"yes"} -); - - - $app->object_add_attribute ('Verilog','Router_param',\@parameters); - $app->object_add_attribute ('Verilog','Router_ports',\@ports); - - - - - my $table=$app->build_network_maker_gui(); - return $table; + ); + my @ports =( + {name=> "flit_in_all", type=>"input", width=>"PFw", connect=>"flit_out_all", pwidth=>"Fw", pname=> "flit_in", pconnect=>"flit_out", endp=>"yes"}, + {name=> "flit_in_wr_all", type=>"input", width=>"P", connect=>"flit_out_wr_all", pwidth=>1, pname=> "flit_in_wr", pconnect=>"flit_out_wr",endp=>"yes"}, + {name=> "congestion_in_all", type=>"input", width=>"CONG_ALw", connect=>"congestion_out_all", pwidth=>"CONGw", pname=> "congestion_in", pconnect=>"congestion_out",endp=>"no"}, + {name=> "credit_out_all", type=>"output", width=>"PV", connect=>"credit_in_all", pwidth=>"V" ,pname=> "credit_out", pconnect=>"credit_in",endp=>"yes"} + ); + $app->object_add_attribute ('Verilog','Router_param',\@parameters); + $app->object_add_attribute ('Verilog','Router_ports',\@ports); + my $table=$app->build_network_maker_gui(); + return $table; } - sub custom_topology_diagram { - my $self= shift; - - - - my $table=def_table(20,20,FALSE); - my $scrolled_win = add_widget_to_scrolled_win(); - - - my ($col,$row)=(0,0); - - - - - my $plus = def_image_button('icons/plus.png',undef,TRUE); - my $minues = def_image_button('icons/minus.png',undef,TRUE); - my $save = def_image_button('icons/save.png',undef,TRUE); - my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); - set_tip($dot_file, "Show dot file."); - - my $scale=$self->object_get_attribute("tile_diagram","scale"); - $scale= 1 if (!defined $scale); - - my $state=$self->object_get_attribute("tile_diagram","auto_draw"); - if (!defined $state){ - $state='ON' ; - $self->object_add_attribute("tile_diagram","auto_draw",$state); - } - my $auto= ($state eq 'ON')? def_colored_button('ON',17): def_colored_button('OFF',4); - - - my $gtype=$self->object_get_attribute("tile_diagram","gtype"); - if (!defined $gtype){ - $gtype='comp' ; - $self->object_add_attribute("tile_diagram","gtype",$gtype); - } - my $graph_type= ($gtype eq 'comp')? def_colored_button('comp',17): def_colored_button('simple',4); - - - - - - - $table->attach (gen_label_in_center ("Auto Draw") , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach ($auto , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach ($graph_type , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach ($plus , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach ($minues, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach ($save, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach ($dot_file, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - - $table->attach_defaults ($scrolled_win, 1, 20, 0, 20); #,'fill','shrink',2,2); - - ($col,$row)=(1,0); - while ($row<20){ - my $tmp=gen_label_in_left(''); - $table->attach_defaults ($tmp, $col, $col+1,$row,$row+1);$row++; - } - - $plus -> signal_connect("clicked" => sub{ - $scale*=1.1 if ($scale <10); - $self->object_add_attribute("topology_diagram","scale", $scale ); - show_custom_topology_diagram ($self,$scrolled_win,"topology_diagram"); - }); - $minues -> signal_connect("clicked" => sub{ - $scale*=.9 if ($scale >0.1); ; - $self->object_add_attribute("topology_diagram","scale", $scale ); - show_custom_topology_diagram ($self,$scrolled_win,"topology_diagram"); - }); - $save-> signal_connect("clicked" => sub{ - save_inline_diagram_as ($self); - }); - - $dot_file-> signal_connect("clicked" => sub{ - my $dotfile = generate_custom_topology_dot_file($self); - show_text_in_scrolled_win($self,$scrolled_win, $dotfile); - }); - - - $auto -> signal_connect("clicked" => sub{ - my $state=$self->object_get_attribute("tile_diagram","auto_draw"); - - - my $new = ($state eq "ON")? "OFF" : "ON"; - $self->object_add_attribute("tile_diagram","auto_draw",$new); - set_gui_status($self,"ref",1); - }); - - $graph_type-> signal_connect("clicked" => sub{ - my $state=$self->object_get_attribute("tile_diagram","gtype"); - - - my $new = ($state eq "simple")? "comp" : "simple"; - $self->object_add_attribute("tile_diagram","gtype",$new); - set_gui_status($self,"ref",1); - }); - - if ($state eq 'ON'){ - show_custom_topology_diagram ($self,$scrolled_win,"topology_diagram"); - } - - return add_widget_to_scrolled_win ($table); - + my $self= shift; + my $table=def_table(20,20,FALSE); + my $scrolled_win = add_widget_to_scrolled_win(); + my ($col,$row)=(0,0); + my $plus = def_image_button('icons/plus.png',undef,TRUE); + my $minues = def_image_button('icons/minus.png',undef,TRUE); + my $save = def_image_button('icons/save.png',undef,TRUE); + my $dot_file = def_image_button('icons/add-notes.png',undef,TRUE); + set_tip($dot_file, "Show dot file."); + my $scale=$self->object_get_attribute("tile_diagram","scale"); + $scale= 1 if (!defined $scale); + my $state=$self->object_get_attribute("tile_diagram","auto_draw"); + if (!defined $state){ + $state='ON' ; + $self->object_add_attribute("tile_diagram","auto_draw",$state); + } + my $auto= ($state eq 'ON')? def_colored_button('ON',17): def_colored_button('OFF',4); + my $gtype=$self->object_get_attribute("tile_diagram","gtype"); + if (!defined $gtype){ + $gtype='comp' ; + $self->object_add_attribute("tile_diagram","gtype",$gtype); + } + my $graph_type= ($gtype eq 'comp')? def_colored_button('comp',17): def_colored_button('simple',4); + $table->attach (gen_label_in_center ("Auto Draw") , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach ($auto , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach ($graph_type , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach ($plus , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach ($minues, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach ($save, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach ($dot_file, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach_defaults ($scrolled_win, 1, 20, 0, 20); #,'fill','shrink',2,2); + ($col,$row)=(1,0); + while ($row<20){ + my $tmp=gen_label_in_left(''); + $table->attach_defaults ($tmp, $col, $col+1,$row,$row+1);$row++; + } + $plus -> signal_connect("clicked" => sub{ + $scale*=1.1 if ($scale <10); + $self->object_add_attribute("topology_diagram","scale", $scale ); + show_custom_topology_diagram ($self,$scrolled_win,"topology_diagram"); + }); + $minues -> signal_connect("clicked" => sub{ + $scale*=.9 if ($scale >0.1); ; + $self->object_add_attribute("topology_diagram","scale", $scale ); + show_custom_topology_diagram ($self,$scrolled_win,"topology_diagram"); + }); + $save-> signal_connect("clicked" => sub{ + save_inline_diagram_as ($self); + }); + $dot_file-> signal_connect("clicked" => sub{ + my $dotfile = generate_custom_topology_dot_file($self); + show_text_in_scrolled_win($self,$scrolled_win, $dotfile); + }); + $auto -> signal_connect("clicked" => sub{ + my $state=$self->object_get_attribute("tile_diagram","auto_draw"); + my $new = ($state eq "ON")? "OFF" : "ON"; + $self->object_add_attribute("tile_diagram","auto_draw",$new); + set_gui_status($self,"ref",1); + }); + $graph_type-> signal_connect("clicked" => sub{ + my $state=$self->object_get_attribute("tile_diagram","gtype"); + my $new = ($state eq "simple")? "comp" : "simple"; + $self->object_add_attribute("tile_diagram","gtype",$new); + set_gui_status($self,"ref",1); + }); + if ($state eq 'ON'){ + show_custom_topology_diagram ($self,$scrolled_win,"topology_diagram"); + } + return add_widget_to_scrolled_win ($table); } - - - - sub gen_right_paned { - my ($self,$info) =@_; - my $page_num=$self->object_get_attribute ("process_notebook","currentpage"); - - return route_info_window($self,$info) if($page_num==3); - return custom_topology_diagram ($self,$info); - + my ($self,$info) =@_; + my $page_num=$self->object_get_attribute ("process_notebook","currentpage"); + return route_info_window($self,$info) if($page_num==3); + return custom_topology_diagram ($self,$info); } - - - sub endp_node_dot_comp { - my ($T,$instance)=@_; - - - return - " - $T\[ - label = \"$instance\" + my ($T,$instance)=@_; + return + " + $T\[ + label = \"$instance\" shape=house margin=0 - color=orange - style=filled - fillcolor=orange + color=orange + style=filled + fillcolor=orange ]; -"; +"; } sub router_node_dot_comp{ - my ($Pnum,$R,$instance)=@_; - $Pnum=1 if(!defined $Pnum); - my $label = - ($Pnum==2)? " \{1|$instance|0\}": - ($Pnum==3)? "\{ |2| \} | \{1|$instance|0\} ": - ($Pnum==4)? "\{ |3| \} | \{2|$instance|0\} | \{ 1\}": - ($Pnum==5)? "\{ |3| \} | \{2|$instance|4\} | \{ |1|0\}": - ($Pnum==6)? "\{3|4| \} | \{2|$instance|5\} | \{ |1|0\}": - ($Pnum==7)? "\{4|5| \} | \{3|$instance|6\} | \{2 |1|0\}": - ($Pnum==8)? "\{4|5|6\} | \{3|$instance|7\} | \{2 |1|0\}": - ($Pnum==9)? "\{5|6|7\} | \{4|$instance|8\} | \{3 |2|1|0\}": - ($Pnum==10)? "\{5|6|7|8\} | \{4|$instance|9\} | \{3 |2|1|0\}": - ($Pnum==11)? "\{6|7|8|9\}| \{5| | |10\} | \{4|$instance| \} | \{3 |2|1|0\}": - ($Pnum==12)? "\{6|7|8|9\}| \{5| | |10\} | \{4|$instance|11\} | \{3 |2|1|0\}": - "\{ |2| \} | \{3|$instance|1\} | \{ |4|0\}"; - - - return - "$R\[ - label = \"$label\" + my ($Pnum,$R,$instance)=@_; + $Pnum=1 if(!defined $Pnum); + my $label = + ($Pnum==2)? " \{1|$instance|0\}": + ($Pnum==3)? "\{ |2| \} | \{1|$instance|0\} ": + ($Pnum==4)? "\{ |3| \} | \{2|$instance|0\} | \{ 1\}": + ($Pnum==5)? "\{ |3| \} | \{2|$instance|4\} | \{ |1|0\}": + ($Pnum==6)? "\{3|4| \} | \{2|$instance|5\} | \{ |1|0\}": + ($Pnum==7)? "\{4|5| \} | \{3|$instance|6\} | \{2 |1|0\}": + ($Pnum==8)? "\{4|5|6\} | \{3|$instance|7\} | \{2 |1|0\}": + ($Pnum==9)? "\{5|6|7\} | \{4|$instance|8\} | \{3 |2|1|0\}": + ($Pnum==10)? "\{5|6|7|8\} | \{4|$instance|9\} | \{3 |2|1|0\}": + ($Pnum==11)? "\{6|7|8|9\}| \{5| | |10\} | \{4|$instance| \} | \{3 |2|1|0\}": + ($Pnum==12)? "\{6|7|8|9\}| \{5| | |10\} | \{4|$instance|11\} | \{3 |2|1|0\}": + "\{ |2| \} | \{3|$instance|1\} | \{ |4|0\}"; + return + "$R\[ + label = \"$label\" shape=record - color=blue - style=filled - fillcolor=blue + color=blue + style=filled + fillcolor=blue ]; "; - } sub router_node_dot_sim{ - my ($Pnum,$R,$instance)=@_; - $Pnum=1 if(!defined $Pnum); - my $label = "$instance"; - - - return - "$R\[ - label = \"$label\" + my ($Pnum,$R,$instance)=@_; + $Pnum=1 if(!defined $Pnum); + my $label = "$instance"; + return + "$R\[ + label = \"$label\" shape=circle - color=blue - style=filled - fillcolor=blue + color=blue + style=filled + fillcolor=blue ]; "; - } - sub endp_node_dot_sim { - my ($T,$instance)=@_; - - - return - " - $T\[ - label = \"$instance\" + my ($T,$instance)=@_; + return + " + $T\[ + label = \"$instance\" shape=circle margin=0 - color=orange - style=filled - fillcolor=orange + color=orange + style=filled + fillcolor=orange ]; -"; +"; } - - - - - - - - - - - sub generate_custom_topology_dot_file{ - my $self=shift; - - my $gtype=$self->object_get_attribute("tile_diagram","gtype"); - $gtype = "simple" if (!defined $gtype); - - my $dotfile= + my $self=shift; + my $gtype=$self->object_get_attribute("tile_diagram","gtype"); + $gtype = "simple" if (!defined $gtype); + my $dotfile= "digraph G { - graph [layout = twopi, rankdir = RL , splines = true, overlap = false]; - node[shape=record]; - "; - #Add endpoints - my @nodes=get_list_of_all_endpoints($self); - my $i=0; - foreach my $p (@nodes){ - my $instance= $self->object_get_attribute("$p","NAME"); - $instance = "T$i" if(!defined $instance); - $dotfile.= ($gtype eq 'simple')? endp_node_dot_sim($p,$instance) : endp_node_dot_comp($p,$instance); - $i++; - } - - - - #add routers - @nodes=get_list_of_all_routers($self); - $i=0; - foreach my $p (@nodes){ - my $instance= $self->object_get_attribute("$p","NAME"); - $instance = "R$i" if(!defined $instance); - my $pnum=$self->object_get_attribute("$p",'PNUM'); - $dotfile.=($gtype eq 'simple')? router_node_dot_sim($pnum,$p,$instance): router_node_dot_comp($pnum,$p,$instance); - $i++; - } - - - #add connections - my @all_nodes=get_list_of_all_nodes($self); - my @draw; - foreach my $p (@all_nodes){ - my $pnum=$self->object_get_attribute("$p",'PNUM'); - # my $inst=$self->object_get_attribute("$p",'NAME'); - my $type = $self->object_get_attribute("$p",'TYPE'); - $pnum = 0 if(!defined $pnum); - for (my $i=0;$i<$pnum; $i++){ - my $src_port = "Port[${i}]"; - my $connect = $self->{$p}{'PCONNECT'}{$src_port}; - - if (defined $connect) { - my $pos = get_scolar_pos($connect,@draw); - if ( !defined $pos ){ - - - my ($node,$pnode)=split(/\s*,\s*/,$connect); - # check if $node exist - if ( defined get_scolar_pos($node, @all_nodes)){ - - my ($cp)= sscanf("Port[%u]","$pnode"); - # my $cinst=$self->object_get_attribute("$node",'NAME'); - my $ctype = $self->object_get_attribute("$node",'TYPE'); - - - - my ($t2, $t1); - - if ($gtype eq 'simple'){ - $t2 = "\"$p\""; - $t1 = "\"$node\""; - } else { - $t2 = ($type eq "ENDP" )? "\"$p\"" : "\"$p\" : \"p$i\""; - $t1 = ($ctype eq "ENDP" )? "\"$node\"" : "\"$node\" : \"p$cp\""; - - } - my $t= "$t1 -> $t2 [ dir=none];\n"; - $dotfile=$dotfile."$t"; - } - push(@draw,$connect); - push(@draw,"$p,$src_port"); - #print "@draw\n"; - } - - - }} - } - $dotfile=$dotfile."\n}\n"; - #print $dotfile; - return $dotfile; + graph [layout = twopi, rankdir = RL , splines = true, overlap = false]; + node[shape=record]; + "; + #Add endpoints + my @nodes=get_list_of_all_endpoints($self); + my $i=0; + foreach my $p (@nodes){ + my $instance= $self->object_get_attribute("$p","NAME"); + $instance = "T$i" if(!defined $instance); + $dotfile.= ($gtype eq 'simple')? endp_node_dot_sim($p,$instance) : endp_node_dot_comp($p,$instance); + $i++; + } + #add routers + @nodes=get_list_of_all_routers($self); + $i=0; + foreach my $p (@nodes){ + my $instance= $self->object_get_attribute("$p","NAME"); + $instance = "R$i" if(!defined $instance); + my $pnum=$self->object_get_attribute("$p",'PNUM'); + $dotfile.=($gtype eq 'simple')? router_node_dot_sim($pnum,$p,$instance): router_node_dot_comp($pnum,$p,$instance); + $i++; + } + #add connections + my @all_nodes=get_list_of_all_nodes($self); + my @draw; + foreach my $p (@all_nodes){ + my $pnum=$self->object_get_attribute("$p",'PNUM'); + # my $inst=$self->object_get_attribute("$p",'NAME'); + my $type = $self->object_get_attribute("$p",'TYPE'); + $pnum = 0 if(!defined $pnum); + for (my $i=0;$i<$pnum; $i++){ + my $src_port = "Port[${i}]"; + my $connect = $self->{$p}{'PCONNECT'}{$src_port}; + if (defined $connect) { + my $pos = get_scolar_pos($connect,@draw); + if ( !defined $pos ){ + my ($node,$pnode)=split(/\s*,\s*/,$connect); + # check if $node exist + if ( defined get_scolar_pos($node, @all_nodes)){ + my ($cp)= sscanf("Port[%u]","$pnode"); + # my $cinst=$self->object_get_attribute("$node",'NAME'); + my $ctype = $self->object_get_attribute("$node",'TYPE'); + my ($t2, $t1); + if ($gtype eq 'simple'){ + $t2 = "\"$p\""; + $t1 = "\"$node\""; + } else { + $t2 = ($type eq "ENDP" )? "\"$p\"" : "\"$p\" : \"p$i\""; + $t1 = ($ctype eq "ENDP" )? "\"$node\"" : "\"$node\" : \"p$cp\""; + } + my $t= "$t1 -> $t2 [ dir=none];\n"; + $dotfile=$dotfile."$t"; + } + push(@draw,$connect); + push(@draw,"$p,$src_port"); + #print "@draw\n"; + } + } + } + } + $dotfile=$dotfile."\n}\n"; + #print $dotfile; + return $dotfile; } sub get_connection_port_num_between_two_nodes{ - my ($self,$n1,$n2)=@_; - my $PNUM=$self->object_get_attribute($n1,"PNUM"); - - for (my $p1=0; $p1<$PNUM; $p1++){ - my $connect=$self->{$n1}{"PCONNECT"}{"Port[$p1]"}; - next if(!defined $connect); - my ($node,$pnode)=split(/\s*,\s*/,$connect); - my ($p2)= sscanf("Port[%u]","$pnode"); - return ($p1,$p2) if($node eq $n2 ); - } - return undef; + my ($self,$n1,$n2)=@_; + my $PNUM=$self->object_get_attribute($n1,"PNUM"); + for (my $p1=0; $p1<$PNUM; $p1++){ + my $connect=$self->{$n1}{"PCONNECT"}{"Port[$p1]"}; + next if(!defined $connect); + my ($node,$pnode)=split(/\s*,\s*/,$connect); + my ($p2)= sscanf("Port[%u]","$pnode"); + return ($p1,$p2) if($node eq $n2 ); + } + return undef; } - sub show_custom_topology_diagram { - my ($self,$scrolled_win, $name)=@_; - - my $state=$self->object_get_attribute("tile_diagram","auto_draw"); - if( $state eq "ON") { - my $dotfile = generate_custom_topology_dot_file($self); - generate_and_show_graph_using_graphviz($self,$scrolled_win,$dotfile,$name); - } - else { - my @list = $scrolled_win->get_children(); - foreach my $l (@list){ - $scrolled_win->remove($l); - } - } - - return; + my ($self,$scrolled_win, $name)=@_; + my $state=$self->object_get_attribute("tile_diagram","auto_draw"); + if( $state eq "ON") { + my $dotfile = generate_custom_topology_dot_file($self); + generate_and_show_graph_using_graphviz($self,$scrolled_win,$dotfile,$name); + } + else { + my @list = $scrolled_win->get_children(); + foreach my $l (@list){ + $scrolled_win->remove($l); + } + } + return; } - - - - sub take_node_num_page{ - my ($self)=@_; - my $table= def_table(2,10,FALSE); - my $row=0; - my $col=4; - $table->attach (def_label('Network Element'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=2; - $table->attach (def_label('Number'),$col,$col+1,$row,$row+1,'fill','shrink',2,2); - $row++;$col=0; - - $table->attach (def_icon('icons/e.png'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - ($row,$col)=add_param_widget ($self,"# Endpoints","NUM", 0,'Spin-button','0,1024,1',undef, $table,$row,$col,1,'ENDP',10,'redraw');$col=0; - for ( my $i=2;$i<=12; $i++){ - $table->attach (def_icon('icons/r.png'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - ($row,$col)=add_param_widget ($self,"# $i-Port Routers","NUM", 0,'Spin-button','0,1024,1',undef, $table,$row,$col,1,"ROUTER${i}",10,'redraw');$col=0; - } - return $table; + my ($self)=@_; + my $table= def_table(2,10,FALSE); + my $row=0; + my $col=4; + $table->attach (def_label('Network Element'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=2; + $table->attach (def_label('Number'),$col,$col+1,$row,$row+1,'fill','shrink',2,2); + $row++;$col=0; + $table->attach (def_icon('icons/e.png'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; + ($row,$col)=add_param_widget ($self,"# Endpoints","NUM", 0,'Spin-button','0,1024,1',undef, $table,$row,$col,1,'ENDP',10,'redraw');$col=0; + for ( my $i=2;$i<=12; $i++){ + $table->attach (def_icon('icons/r.png'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; + ($row,$col)=add_param_widget ($self,"# $i-Port Routers","NUM", 0,'Spin-button','0,1024,1',undef, $table,$row,$col,1,"ROUTER${i}",10,'redraw');$col=0; + } + return $table; } - - sub take_instance_page{ - my ($self)=@_; - my $table= def_table(2,10,FALSE); - - initial_node_info($self); - - my $row=0; - my $col=0; - - - $table->attach (def_label(' Network Element '),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=2; - $table->attach (def_label(' Instance name '),$col,$col+1,$row,$row+1,'fill','shrink',2,2); - $row++;$col=0; - - - my $EN= $self->object_get_attribute('ENDP','NUM'); - $EN = 0 if(!defined $EN); - for (my $i=0;$i<$EN; $i++){ - - my $d=get_default_instance_name($self,"ENDP_$i"); - ($row,$col)=add_param_widget ($self,"Endpoint $i","NAME",$d ,'Entry',undef,"router instance name", $table,$row,$col,1,"ENDP_$i",10,'redraw');$col=0; - - } - - #routers - my $Rnum=0; - for ( my $i=2;$i<=12; $i++){ - my $n= $self->object_get_attribute("ROUTER${i}","NUM"); - $n=0 if(!defined $n); - for ( my $j=0;$j<$n; $j++){ - my $d=get_default_instance_name($self,"ROUTER${i}_$j"); - ($row,$col)=add_param_widget ($self,"Router $Rnum","NAME", "$d",'Entry',undef,"router instance name", $table,$row,$col,1,"ROUTER${i}_$j",10,'redraw');$col=0; - - $Rnum++; - } - } - return $table; - + my ($self)=@_; + my $table= def_table(2,10,FALSE); + initial_node_info($self); + my $row=0; + my $col=0; + $table->attach (def_label(' Network Element '),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=2; + $table->attach (def_label(' Instance name '),$col,$col+1,$row,$row+1,'fill','shrink',2,2); + $row++;$col=0; + my $EN= $self->object_get_attribute('ENDP','NUM'); + $EN = 0 if(!defined $EN); + for (my $i=0;$i<$EN; $i++){ + my $d=get_default_instance_name($self,"ENDP_$i"); + ($row,$col)=add_param_widget ($self,"Endpoint $i","NAME",$d ,'Entry',undef,"router instance name", $table,$row,$col,1,"ENDP_$i",10,'redraw');$col=0; + } + #routers + my $Rnum=0; + for ( my $i=2;$i<=12; $i++){ + my $n= $self->object_get_attribute("ROUTER${i}","NUM"); + $n=0 if(!defined $n); + for ( my $j=0;$j<$n; $j++){ + my $d=get_default_instance_name($self,"ROUTER${i}_$j"); + ($row,$col)=add_param_widget ($self,"Router $Rnum","NAME", "$d",'Entry',undef,"router instance name", $table,$row,$col,1,"ROUTER${i}_$j",10,'redraw');$col=0; + $Rnum++; + } + } + return $table; } sub initial_node_info { - my ($self)=@_; - - my $EN= $self->object_get_attribute('ENDP','NUM'); - $EN = 0 if(!defined $EN); - for (my $i=0;$i<$EN; $i++){ - $self->object_add_attribute("ENDP_$i",'PNUM',1); - $self->object_add_attribute("ENDP_$i",'TYPE',"ENDP"); - my $inst=$self->object_get_attribute("ENDP_$i",'NAME'); - if(!defined $inst){ - $inst=get_default_instance_name ($self,"ENDP_$i"); - $self->object_add_attribute("ENDP_$i",'NAME',$inst); - } - } - - #routers - my $Rnum=0; - for ( my $i=2;$i<=12; $i++){ - my $n= $self->object_get_attribute("ROUTER${i}","NUM"); - $n=0 if(!defined $n); - for ( my $j=0;$j<$n; $j++){ - $self->object_add_attribute("ROUTER${i}_$j",'PNUM',${i}); - $self->object_add_attribute("ROUTER${i}_$j",'RNUM',$Rnum); - $self->object_add_attribute("ROUTER${i}_$j",'TYPE',"ROUTER"); - my $inst=$self->object_get_attribute("ROUTER${i}_$j",'NAME'); - if(!defined $inst){ - $inst=get_default_instance_name ($self,"ROUTER${i}_$j"); - $self->object_add_attribute("ROUTER${i}_$j",'NAME',$inst); - } - $Rnum++; - } - } - + my ($self)=@_; + my $EN= $self->object_get_attribute('ENDP','NUM'); + $EN = 0 if(!defined $EN); + for (my $i=0;$i<$EN; $i++){ + $self->object_add_attribute("ENDP_$i",'PNUM',1); + $self->object_add_attribute("ENDP_$i",'TYPE',"ENDP"); + my $inst=$self->object_get_attribute("ENDP_$i",'NAME'); + if(!defined $inst){ + $inst=get_default_instance_name ($self,"ENDP_$i"); + $self->object_add_attribute("ENDP_$i",'NAME',$inst); + } + } + #routers + my $Rnum=0; + for ( my $i=2;$i<=12; $i++){ + my $n= $self->object_get_attribute("ROUTER${i}","NUM"); + $n=0 if(!defined $n); + for ( my $j=0;$j<$n; $j++){ + $self->object_add_attribute("ROUTER${i}_$j",'PNUM',${i}); + $self->object_add_attribute("ROUTER${i}_$j",'RNUM',$Rnum); + $self->object_add_attribute("ROUTER${i}_$j",'TYPE',"ROUTER"); + my $inst=$self->object_get_attribute("ROUTER${i}_$j",'NAME'); + if(!defined $inst){ + $inst=get_default_instance_name ($self,"ROUTER${i}_$j"); + $self->object_add_attribute("ROUTER${i}_$j",'NAME',$inst); + } + $Rnum++; + } + } } - - - sub get_default_instance_name { - my ($self,$name)=@_; - my $type = $self->object_get_attribute($name,'TYPE'); - my @nodes =($type eq 'ENDP')? get_list_of_all_endpoints($self):get_list_of_all_routers($self); - - my @R=("--"); - foreach my $p (@nodes){ - my $n= $self->object_get_attribute("$p","NAME"); - push( @R, $n) if(defined $n); - } - - my $i=0; - my $inst = ($type eq 'ENDP')? "T$i": "R$i"; - my $pos= get_scolar_pos($inst,@R); - while (defined $pos){ - $i++; - $inst = ($type eq 'ENDP')? "T$i": "R$i"; - $pos= get_scolar_pos($inst,@R); - } - - - return $inst; -} - - - + my ($self,$name)=@_; + my $type = $self->object_get_attribute($name,'TYPE'); + my @nodes =($type eq 'ENDP')? get_list_of_all_endpoints($self):get_list_of_all_routers($self); + my @R=("--"); + foreach my $p (@nodes){ + my $n= $self->object_get_attribute("$p","NAME"); + push( @R, $n) if(defined $n); + } + my $i=0; + my $inst = ($type eq 'ENDP')? "T$i": "R$i"; + my $pos= get_scolar_pos($inst,@R); + while (defined $pos){ + $i++; + $inst = ($type eq 'ENDP')? "T$i": "R$i"; + $pos= get_scolar_pos($inst,@R); + } + return $inst; +} sub get_list_of_all_routers { - my ($self)=@_; - my @R; - for ( my $i=2;$i<=12; $i++){ - my $n= $self->object_get_attribute("ROUTER${i}","NUM"); - $n=0 if(!defined $n); - for ( my $j=0;$j<$n; $j++){ - push( @R, "ROUTER${i}_$j"); - } - } - return @R; + my ($self)=@_; + my @R; + for ( my $i=2;$i<=12; $i++){ + my $n= $self->object_get_attribute("ROUTER${i}","NUM"); + $n=0 if(!defined $n); + for ( my $j=0;$j<$n; $j++){ + push( @R, "ROUTER${i}_$j"); + } + } + return @R; } sub get_list_of_all_endpoints { - my ($self)=@_; - my @E; - my $EN= $self->object_get_attribute('ENDP','NUM'); - $EN = 0 if(!defined $EN); - for (my $i=0;$i<$EN; $i++){ - push( @E, "ENDP_$i"); - } - return @E; + my ($self)=@_; + my @E; + my $EN= $self->object_get_attribute('ENDP','NUM'); + $EN = 0 if(!defined $EN); + for (my $i=0;$i<$EN; $i++){ + push( @E, "ENDP_$i"); + } + return @E; } sub get_list_of_all_nodes { - my ($self)=@_; - my @R=get_list_of_all_routers($self); + my ($self)=@_; + my @R=get_list_of_all_routers($self); my @E=get_list_of_all_endpoints($self); my @all_nodes= (@E,@R); - return @all_nodes; -} + return @all_nodes; +} sub remove_connected_port{ - my ($self,$node,$port,$info)=@_; - my @all_nodes=get_list_of_all_nodes($self); - foreach my $p (@all_nodes){ - my $pnum=$self->object_get_attribute("$p",'PNUM'); - my $inst=$self->object_get_attribute("$p",'NAME'); - - $pnum = 0 if(!defined $pnum); - for (my $i=0;$i<$pnum; $i++){ - my $src_port = "Port[${i}]"; - if(defined $self->{$p}{'PCONNECT'}{$src_port}){ if ($self->{$p}{'PCONNECT'}{$src_port} eq "$node,$port"){ - delete $self->{$p}{'PCONNECT'}{$src_port}; - my $con_inst=$self->object_get_attribute("$node",'NAME'); - add_info($info,"** $inst $src_port is disconnected from $con_inst $port \n") if (defined $info); - - }} - } - } -} - + my ($self,$node,$port,$info)=@_; + my @all_nodes=get_list_of_all_nodes($self); + foreach my $p (@all_nodes){ + my $pnum=$self->object_get_attribute("$p",'PNUM'); + my $inst=$self->object_get_attribute("$p",'NAME'); + $pnum = 0 if(!defined $pnum); + for (my $i=0;$i<$pnum; $i++){ + my $src_port = "Port[${i}]"; + if(defined $self->{$p}{'PCONNECT'}{$src_port}){ if ($self->{$p}{'PCONNECT'}{$src_port} eq "$node,$port"){ + delete $self->{$p}{'PCONNECT'}{$src_port}; + my $con_inst=$self->object_get_attribute("$node",'NAME'); + add_info($info,"** $inst $src_port is disconnected from $con_inst $port \n") if (defined $info); + }} + } + } +} sub get_instance_to_node_name { - my $self=shift; - my @all_nodes=get_list_of_all_nodes($self); + my $self=shift; + my @all_nodes=get_list_of_all_nodes($self); my %par; foreach my $p (@all_nodes){ - my $inst=$self->object_get_attribute("$p",'NAME'); - $par{$inst}= $p; + my $inst=$self->object_get_attribute("$p",'NAME'); + $par{$inst}= $p; } - return %par; + return %par; } - - ############## -# create_tree +# create_tree ############## sub create_tree_view { - my ($self,$source,$src_port,$info)=@_; - my $window = def_popwin_size(30,85,"Select Connection Element and Port",'percent'); - - - my ($model,$tree_view,$column) =create_tree_model_network_maker(); - - my @all_nodes=get_list_of_all_nodes($self); - - unshift(@all_nodes,"-"); - my %par; - - foreach my $p (@all_nodes){ - my @childs; - my $pnum=$self->object_get_attribute("$p",'PNUM'); - my $inst=$self->object_get_attribute("$p",'NAME'); - - $pnum = 0 if(!defined $pnum); - $inst = "-" if(!defined $inst); - - $par{$inst}= $p; - for (my $i=0;$i<$pnum; $i++){ - #donot add the source port itself to connection list - if(($source ne $p)|| ($src_port ne "Port[${i}]")){ - push(@childs, "Port[${i}]"); - } - } - my $iter = $model->append (undef); - $model->set ($iter, 0, $inst, 1, $inst || '', 2, 0 || '', 3, FALSE); - foreach my $v ( @childs){ - my $child_iter = $model->append ($iter); - $model->set ($child_iter, 0, $v, 1, $inst|| '', 2, $v || '', 3, FALSE); - } - } - - - $tree_view->append_column ($column); - - - - $tree_view->signal_connect (row_activated => sub{ - - my ($tree_view, $path, $column) = @_; - my $model = $tree_view->get_model; - my $iter = $model->get_iter ($path); - my $parent = $model->get ($iter, 1); - my $child = $model->get ($iter, 2); - - if ($child){ - my $node=$par{$parent}; - connect_nodes ($self,$node,$child,$source,$src_port,$info); - - - - - set_gui_status($self,'ref',1); - $window->destroy; - - #add parent child - } - elsif($parent ){ - - my $node=$par{$parent}; - if ($node eq "-"){ - remove_connected_port($self,$source,$src_port); - delete $self->{$source}{'PCONNECT'}{$src_port}; - } - - - - set_gui_status($self,'ref',1); - $window->destroy; - - - } - - - #add parent child - - }); - - #$tree_view->expand_all; - - my $scrolled_window = add_widget_to_scrolled_win($tree_view); - - my $hbox = def_hbox (FALSE, 0); - $hbox->pack_start ( $scrolled_window, TRUE, TRUE, 0); - $window ->add($hbox); - $window->show_all; + my ($self,$source,$src_port,$info)=@_; + my $window = def_popwin_size(30,85,"Select Connection Element and Port",'percent'); + my ($model,$tree_view,$column) =create_tree_model_network_maker(); + my @all_nodes=get_list_of_all_nodes($self); + unshift(@all_nodes,"-"); + my %par; + foreach my $p (@all_nodes){ + my @childs; + my $pnum=$self->object_get_attribute("$p",'PNUM'); + my $inst=$self->object_get_attribute("$p",'NAME'); + $pnum = 0 if(!defined $pnum); + $inst = "-" if(!defined $inst); + $par{$inst}= $p; + for (my $i=0;$i<$pnum; $i++){ + #donot add the source port itself to connection list + if(($source ne $p)|| ($src_port ne "Port[${i}]")){ + push(@childs, "Port[${i}]"); + } + } + my $iter = $model->append (undef); + $model->set ($iter, 0, $inst, 1, $inst || '', 2, 0 || '', 3, FALSE); + foreach my $v ( @childs){ + my $child_iter = $model->append ($iter); + $model->set ($child_iter, 0, $v, 1, $inst|| '', 2, $v || '', 3, FALSE); + } + } + $tree_view->append_column ($column); + $tree_view->signal_connect (row_activated => sub{ + my ($tree_view, $path, $column) = @_; + my $model = $tree_view->get_model; + my $iter = $model->get_iter ($path); + my $parent = $model->get ($iter, 1); + my $child = $model->get ($iter, 2); + if ($child){ + my $node=$par{$parent}; + connect_nodes ($self,$node,$child,$source,$src_port,$info); + set_gui_status($self,'ref',1); + $window->destroy; + #add parent child + } + elsif($parent ){ + my $node=$par{$parent}; + if ($node eq "-"){ + remove_connected_port($self,$source,$src_port); + delete $self->{$source}{'PCONNECT'}{$src_port}; + } + set_gui_status($self,'ref',1); + $window->destroy; + } + #add parent child + }); + #$tree_view->expand_all; + my $scrolled_window = add_widget_to_scrolled_win($tree_view); + my $hbox = def_hbox (FALSE, 0); + $hbox->pack_start ( $scrolled_window, TRUE, TRUE, 0); + $window ->add($hbox); + $window->show_all; } sub connect_nodes { - my ($self,$node1,$src_port1,$node2,$src_port2,$info)=@_; - - - - #add_colored_info($info,"$node1,$src_port1,$node2,$src_port2;\n","red") if (defined $info); - - #check if the selected port has been connected to another port before and remove the connection - remove_connected_port($self,$node1,$src_port1,$info); - remove_connected_port($self,$node2,$src_port2,$info); - - $self->{$node1}{'PCONNECT'}{$src_port1}="$node2,$src_port2"; - $self->{$node2}{'PCONNECT'}{$src_port2}="$node1,$src_port1"; - + my ($self,$node1,$src_port1,$node2,$src_port2,$info)=@_; + #add_colored_info($info,"$node1,$src_port1,$node2,$src_port2;\n","red") if (defined $info); + #check if the selected port has been connected to another port before and remove the connection + remove_connected_port($self,$node1,$src_port1,$info); + remove_connected_port($self,$node2,$src_port2,$info); + $self->{$node1}{'PCONNECT'}{$src_port1}="$node2,$src_port2"; + $self->{$node2}{'PCONNECT'}{$src_port2}="$node1,$src_port1"; } sub remove_all_connection { - my ($self)=@_; - my @all_nodes=get_list_of_all_nodes($self); - foreach my $node (@all_nodes ){ - $self->{$node}{'PCONNECT'}=undef; - } - set_gui_status($self,"ref",1); + my ($self)=@_; + my @all_nodes=get_list_of_all_nodes($self); + foreach my $node (@all_nodes ){ + $self->{$node}{'PCONNECT'}=undef; + } + set_gui_status($self,"ref",1); } sub list_node_all_port{ - my ($self,$node)=@_; - my @l; - my $pnum = $self->object_get_attribute($node,'PNUM'); - for (my $i=0;$i<$pnum; $i++){ - push(@l,"Port[${i}]"); - } - return @l; + my ($self,$node)=@_; + my @l; + my $pnum = $self->object_get_attribute($node,'PNUM'); + for (my $i=0;$i<$pnum; $i++){ + push(@l,"Port[${i}]"); + } + return @l; } - - sub list_node_connected_port { - my ($self,$node)=@_; - my $r = $self->{$node}{'PCONNECT'}; - my %c =(defined $r)? %{$r} : undef; - return sort keys %c; + my ($self,$node)=@_; + my $r = $self->{$node}{'PCONNECT'}; + my %c =(defined $r)? %{$r} : undef; + return sort keys %c; } sub list_node_unconnected_port { - my ($self,$node)=@_; - my @p = list_node_all_port($self,$node); - my @cp = list_node_connected_port ($self,$node); - #@p - @cp; + my ($self,$node)=@_; + my @p = list_node_all_port($self,$node); + my @cp = list_node_connected_port ($self,$node); + #@p - @cp; my @np =get_diff_array(\@p,\@cp); - return @np; + return @np; } - sub connection_page{ - my ($self,$info)=@_; - my $table= def_table(2,10,FALSE); - my $row=0; - my $col=0; - - initial_node_info($self); - - - - my $eq = def_table(1,8,TRUE); - - my $label = gen_label_help("Eg: R[i]P[0]->T[i]P[0];i[0,10,1]","Equation:"); - my $entry = gen_entry(); - my $open= def_image_button("icons/enter.png",undef,TRUE); - $eq->attach ($label,0,2, $row, $row+1,'fill','fill',2,2); - $eq->attach_defaults ($entry,2, 9, $row, $row+1); - $eq->attach ($open,9, 10, $row, $row+1,'fill','shrink',2,2); - $table->attach ($eq,0, 20, $row, $row+1,'expand','fill',2,2);$row++; - - $open->signal_connect("clicked" => sub { - evaluate_eqation($self,$entry->get_text(),$info); - - }); - - $row++; - - - - add_Hsep_to_table($table,0, 20, $row);$row++; - my $savr=$row;$row++; - - my $maxp=1; - - my @all_nodes=get_list_of_all_nodes($self); - - foreach my $p (@all_nodes ){ - my $inst=$self->object_get_attribute("$p",'NAME'); - my $pnum=$self->object_get_attribute("$p",'PNUM'); - $maxp= $pnum if($pnum > $maxp ); - - - - my $label =gen_label_in_left("$inst:"); - attach_widget_to_table ($table,$row,undef,undef,$label,$col); $col+=4; - - for (my $i=0;$i<$pnum; $i++){ - my $pname= "Port[${i}]"; - my $connect = $self->{$p}{'PCONNECT'}{$pname}; - my $button = def_button(" -> "); - if (defined $connect) { - my ($node,$pnode)=split(/\s*,\s*/,$connect); - my $e=$self->object_get_attribute("$node",'NAME'); - $button = def_button("$e->$pnode") if(defined $e); - } - $button->signal_connect("clicked" => sub { - create_tree_view($self,$p,$pname,$info); - - }); - attach_widget_to_table ($table,$row,undef,undef,$button,$col); $col+=4; - } - $col=0; - - #($row,$col)=add_param_widget ($self,"$instance","CNNT", undef,"Combo-box",$list,"router instance name", $table,$row,$col,1,"ENDP_$i",1,'ref','horizontal'); - # my $connect_r= $self->object_get_attribute("ENDP_$i","CNNT"); - # if( defined $connect_r){ - # print "cponnection is $R{$connect_r}\n"; - # my $conr= $R{$connect_r}; - # my $p=0; - # ($row,$col)=add_param_widget ($self,"P$p","P_$p", undef,"Combo-box",$list,undef, $table,$row,$col,1,"ENDP_$i",1,'ref','horizontal'); - - - - # } - $row++;$col=0; - - } - - #routers + my ($self,$info)=@_; + my $table= def_table(2,10,FALSE); + my $row=0; + my $col=0; + initial_node_info($self); + my $eq = def_table(1,8,TRUE); + my $label = gen_label_help("Eg: R[i]P[0]->T[i]P[0];i[0,10,1]","Equation:"); + my $entry = gen_entry(); + my $open= def_image_button("icons/enter.png",undef,TRUE); + $eq->attach ($label,0,2, $row, $row+1,'fill','fill',2,2); + $eq->attach_defaults ($entry,2, 9, $row, $row+1); + $eq->attach ($open,9, 10, $row, $row+1,'fill','shrink',2,2); + $table->attach ($eq,0, 20, $row, $row+1,'expand','fill',2,2);$row++; + $open->signal_connect("clicked" => sub { + evaluate_eqation($self,$entry->get_text(),$info); + }); + $row++; + add_Hsep_to_table($table,0, 20, $row);$row++; + my $savr=$row;$row++; + my $maxp=1; + my @all_nodes=get_list_of_all_nodes($self); + foreach my $p (@all_nodes ){ + my $inst=$self->object_get_attribute("$p",'NAME'); + my $pnum=$self->object_get_attribute("$p",'PNUM'); + $maxp= $pnum if($pnum > $maxp ); + my $label =gen_label_in_left("$inst:"); + attach_widget_to_table ($table,$row,undef,undef,$label,$col); $col+=4; + for (my $i=0;$i<$pnum; $i++){ + my $pname= "Port[${i}]"; + my $connect = $self->{$p}{'PCONNECT'}{$pname}; + my $button = def_button(" -> "); + if (defined $connect) { + my ($node,$pnode)=split(/\s*,\s*/,$connect); + my $e=$self->object_get_attribute("$node",'NAME'); + $button = def_button("$e->$pnode") if(defined $e); + } + $button->signal_connect("clicked" => sub { + create_tree_view($self,$p,$pname,$info); + }); + attach_widget_to_table ($table,$row,undef,undef,$button,$col); $col+=4; + } + $col=0; + #($row,$col)=add_param_widget ($self,"$instance","CNNT", undef,"Combo-box",$list,"router instance name", $table,$row,$col,1,"ENDP_$i",1,'ref','horizontal'); + # my $connect_r= $self->object_get_attribute("ENDP_$i","CNNT"); + # if( defined $connect_r){ + # print "cponnection is $R{$connect_r}\n"; + # my $conr= $R{$connect_r}; + # my $p=0; + # ($row,$col)=add_param_widget ($self,"P$p","P_$p", undef,"Combo-box",$list,undef, $table,$row,$col,1,"ENDP_$i",1,'ref','horizontal'); + # } + $row++;$col=0; + } + #routers for ( my $i=2;$i<=12; $i++){ - my $n= $self->object_get_attribute("ROUTER${i}","NUM"); - $n=0 if(!defined $n); - for ( my $j=0;$j<$n; $j++){ - my $pnum= $self->object_get_attribute("ROUTER${i}_$j",'PNUM'); - for ( my $p=0;$p<$pnum; $p++){ - # ($row,$col)=add_param_widget ($self,"P$p","P_$p", undef,"Combo-box",$list,undef, $table,$row,$col,1,"ROUTER${i}_$j",1,'ref','horizontal'); - - } - $row++;$col=0; - - } - } - - - - - #add lables - $row=$savr;$col=0; - $table->attach (def_label(' Network Element '),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=4; - for (my $i=0;$i<$maxp; $i++){ - $table->attach (def_label(" P$i "),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=4; - - } - return $table; - + my $n= $self->object_get_attribute("ROUTER${i}","NUM"); + $n=0 if(!defined $n); + for ( my $j=0;$j<$n; $j++){ + my $pnum= $self->object_get_attribute("ROUTER${i}_$j",'PNUM'); + for ( my $p=0;$p<$pnum; $p++){ + # ($row,$col)=add_param_widget ($self,"P$p","P_$p", undef,"Combo-box",$list,undef, $table,$row,$col,1,"ROUTER${i}_$j",1,'ref','horizontal'); + } + $row++;$col=0; + } + } + #add lables + $row=$savr;$col=0; + $table->attach (def_label(' Network Element '),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=4; + for (my $i=0;$i<$maxp; $i++){ + $table->attach (def_label(" P$i "),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=4; + } + return $table; } - sub evaluate_eqation{ - my ($self,$exp,$info)=@_; - - my @str=split /;/, $exp; - my $eq_exp; - - my $f=0; - my %vname; - my %vars; - - my %nodes_name=get_instance_to_node_name($self); - - foreach my $p (@str) { - - if($f==0){ - $eq_exp= $p; - - } - else{ - my ($v, $start, $end, $step) = sscanf("%s[%d,%d,%d]", $p); - print "($v, $start, $end, $step)\n"; - my @a; - for (my $i=$start; $i<$end;$i++){ - push (@a,$i); - } - $vars{$f}=\@a; - $vname{$f}=$v; - - } - $f++; - - } - - - my %vars2; - my $v1=$vname{1}; - foreach my $i (@{$vars{1}}){ - $vars2{$v1}=$i; - my $v2=$vname{2}; - if (defined $v2) { - foreach my $j (@{$vars{2}}){ - $vars2{$v2}=$j; - my $v3=$vname{3}; - if (defined $v3) { - foreach my $k (@{$vars{3}}){ - $vars2{$v3}=$k; - eval_exp($self,$eq_exp,\%vars2,\%nodes_name,$info); - } - - } - else {eval_exp($self,$eq_exp,\%vars2,\%nodes_name,$info)}; - - - } - } - else {eval_exp($self,$eq_exp,\%vars2,\%nodes_name,$info)}; - - } - -set_gui_status($self,'ref',1); + my ($self,$exp,$info)=@_; + my @str=split /;/, $exp; + my $eq_exp; + my $f=0; + my %vname; + my %vars; + my %nodes_name=get_instance_to_node_name($self); + foreach my $p (@str) { + if($f==0){ + $eq_exp= $p; + } + else{ + my ($v, $start, $end, $step) = sscanf("%s[%d,%d,%d]", $p); + print "($v, $start, $end, $step)\n"; + my @a; + for (my $i=$start; $i<$end;$i++){ + push (@a,$i); + } + $vars{$f}=\@a; + $vname{$f}=$v; + } + $f++; + } + my %vars2; + my $v1=$vname{1}; + foreach my $i (@{$vars{1}}){ + $vars2{$v1}=$i; + my $v2=$vname{2}; + if (defined $v2) { + foreach my $j (@{$vars{2}}){ + $vars2{$v2}=$j; + my $v3=$vname{3}; + if (defined $v3) { + foreach my $k (@{$vars{3}}){ + $vars2{$v3}=$k; + eval_exp($self,$eq_exp,\%vars2,\%nodes_name,$info); + } + } + else {eval_exp($self,$eq_exp,\%vars2,\%nodes_name,$info)}; + } + } + else {eval_exp($self,$eq_exp,\%vars2,\%nodes_name,$info)}; + } + set_gui_status($self,'ref',1); } - - - sub eval_exp { - my ($self,$exp,$ref,$ref2,$info)=@_; - my %vars = %{$ref}; - my %nodes_name =%{$ref2}; + my ($self,$exp,$ref,$ref2,$info)=@_; + my %vars = %{$ref}; + my %nodes_name =%{$ref2}; foreach my $p (sort keys %vars){ - - chomp $exp; - ($exp=$exp)=~ s/\b$p\b/$vars{$p}/g; - - + chomp $exp; + ($exp=$exp)=~ s/\b$p\b/$vars{$p}/g; } - my ($s1, $n1, $p1,$s2, $n2, $p2 ) = sscanf("%s[%s]P[%s]->%s[%s]P[%s]", $exp); + $n1 = eval $n1; + $p1 = eval $p1; + $n2 = eval $n2; + $p2 = eval $p2; + my $string= "$s1 [$n1] P [$p1] -> $s2 [$n2] P [$p2]\n"; + my $node1=$nodes_name{$s1.$n1}; + my $node2=$nodes_name{$s2.$n2}; + if(!defined $node1 ){ + add_colored_info($info,"No instance is named as \"$s1$n1\";\n","red") if (defined $info); + return; + } + if( !defined $node2 ){ + add_colored_info($info,"No instance is named as \"$s2$n2\";\n","red") if (defined $info); + return; + } + connect_nodes ($self,$node1,"Port[$p1]",$node2,"Port[$p2]",$info); + add_info($info,"$string") if (defined $info); +} - -$n1 = eval $n1; -$p1 = eval $p1; - -$n2 = eval $n2; -$p2 = eval $p2; - - -my $string= "$s1 [$n1] P [$p1] -> $s2 [$n2] P [$p2]\n"; - -my $node1=$nodes_name{$s1.$n1}; -my $node2=$nodes_name{$s2.$n2}; - -if(!defined $node1 ){ - add_colored_info($info,"No instance is named as \"$s1$n1\";\n","red") if (defined $info); - return; - } - if( !defined $node2 ){ - add_colored_info($info,"No instance is named as \"$s2$n2\";\n","red") if (defined $info); - return; - } - - - connect_nodes ($self,$node1,"Port[$p1]",$node2,"Port[$p2]",$info); - - -add_info($info,"$string") if (defined $info); - - -} - ########### # connection_page_auto -########## - +########## sub connection_page_auto{ - my ($self,$info)=@_; - my $table= def_table(2,10,FALSE); - my $row=0; - my $col=0; - - initial_node_info($self); - - my $help1 = "Define the minimum number of endpoints that can be connected to a single router. Routers in the topology will have either at least a minum endpoint number or they will have no endpoints at all."; - my $help2 = "Define the manimum number of endpoints that can be connected to a single router."; - my $help3 = undef; - - - - my @widgets = ( - { label=>"Minimum Endp per Router", param_name=>'MIN_ENDP_PER_ROUTER', type=>"Spin-button", default_val=>1, content=>"1,1024,1", info=>$help1, param_parent=>'connection_auto', ref_delay=> undef}, - { label=>"Maximum Endp per Router", param_name=>'MAX_ENDP_PER_ROUTER', type=>"Spin-button", default_val=>1, content=>"1,1024,1", info=>$help2, param_parent=>'connection_auto', ref_delay=> undef}, - { label=>"Endp per Router distribution", param_name=>'ENDP_PER_ROUTER_DIST', type=>"Combo-box", default_val=>"uniform", content=>"uniform,random", info=>$help3, param_parent=>'connection_auto', ref_delay=> undef}, - { label=>"Topology Dimention", param_name=>'DIMENTION', type=>"Combo-box", default_val=>"2D", content=>"2D,3D", info=>undef, param_parent=>'connection_auto', ref_delay=> undef}, - - ); - - - - foreach my $d (@widgets) { - my $w; - ($row,$col,$w)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical"); - - }#foreach - - - - - my $auto = def_image_button('icons/gen.png','Auto Connect'); - $table->attach ($auto,1, 2, $row, $row+1,'fill','fill',2,2); - $auto-> signal_connect("clicked" => sub{ - auto_connect($self,$info); - }); - - my $clean = def_image_button('icons/clear.png','Remove All Connection'); - $table->attach ($clean,0,1 , $row, $row+1,'fill','fill',2,2); - $clean-> signal_connect("clicked" => sub{ - remove_all_connection($self); - }); - - - - return $table; + my ($self,$info)=@_; + my $table= def_table(2,10,FALSE); + my $row=0; + my $col=0; + initial_node_info($self); + my $help1 = "Define the minimum number of endpoints that can be connected to a single router. Routers in the topology will have either at least a minum endpoint number or they will have no endpoints at all."; + my $help2 = "Define the manimum number of endpoints that can be connected to a single router."; + my $help3 = undef; + my @widgets = ( + { label=>"Minimum Endp per Router", param_name=>'MIN_ENDP_PER_ROUTER', type=>"Spin-button", default_val=>1, content=>"1,1024,1", info=>$help1, param_parent=>'connection_auto', ref_delay=> undef}, + { label=>"Maximum Endp per Router", param_name=>'MAX_ENDP_PER_ROUTER', type=>"Spin-button", default_val=>1, content=>"1,1024,1", info=>$help2, param_parent=>'connection_auto', ref_delay=> undef}, + { label=>"Endp per Router distribution", param_name=>'ENDP_PER_ROUTER_DIST', type=>"Combo-box", default_val=>"uniform", content=>"uniform,random", info=>$help3, param_parent=>'connection_auto', ref_delay=> undef}, + { label=>"Topology Dimention", param_name=>'DIMENTION', type=>"Combo-box", default_val=>"2D", content=>"2D,3D", info=>undef, param_parent=>'connection_auto', ref_delay=> undef}, + ); + foreach my $d (@widgets) { + my $w; + ($row,$col,$w)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical"); + }#foreach + my $auto = def_image_button('icons/gen.png','Auto Connect'); + $table->attach ($auto,1, 2, $row, $row+1,'fill','fill',2,2); + $auto-> signal_connect("clicked" => sub{ + auto_connect($self,$info); + }); + my $clean = def_image_button('icons/clear.png','Remove All Connection'); + $table->attach ($clean,0,1 , $row, $row+1,'fill','fill',2,2); + $clean-> signal_connect("clicked" => sub{ + remove_all_connection($self); + }); + return $table; } sub get_new_val_based_on_dist { - my ($total_router,$total_endp, $router_Pnum,$min_endp,$max_endp,$dist_endp)=@_; - - if($dist_endp eq "uniform"){ - my $a = int($total_endp/$total_router); - return $a if($a >= $min_endp && $a <$router_Pnum ); - return $min_endp if($a < $min_endp ); - return $router_Pnum -1 if($a >= $router_Pnum ) ; - } - #random distribution - my $a = int(rand($max_endp - $min_endp +1)) + $min_endp; - return $a if($a >= $min_endp && $a <$router_Pnum ); - return $min_endp if($a < $min_endp ); - return $router_Pnum -1 if($a >= $router_Pnum) ; + my ($total_router,$total_endp, $router_Pnum,$min_endp,$max_endp,$dist_endp)=@_; + if($dist_endp eq "uniform"){ + my $a = int($total_endp/$total_router); + return $a if($a >= $min_endp && $a <$router_Pnum ); + return $min_endp if($a < $min_endp ); + return $router_Pnum -1 if($a >= $router_Pnum ) ; + } + #random distribution + my $a = int(rand($max_endp - $min_endp +1)) + $min_endp; + return $a if($a >= $min_endp && $a <$router_Pnum ); + return $min_endp if($a < $min_endp ); + return $router_Pnum -1 if($a >= $router_Pnum) ; } - sub assign_endp_num_based_on_dist { - my ($self,$routers_ref,$total_endp, $min_endp,$max_endp,$dist_endp,$info)=@_; - my @routers = @{$routers_ref}; - my %assigned; - my $total_router = scalar @routers; - my $valid=1; - while ($total_endp > 0 && $valid ==1){ - $valid =0; - foreach my $r (reverse @routers) { - my $router_Pnum=$self->object_get_attribute("$r",'PNUM'); - my $val = $assigned{$r}; - if (!defined $val) { - $val=0; - $assigned{$r}=0; - } - if ($min_endp >=$router_Pnum || $total_endp ==0 ){ - - } else{ - my $new =get_new_val_based_on_dist ($total_router,$total_endp, $router_Pnum,$min_endp,$max_endp,$dist_endp); - $new =$val + $total_endp if(($new - $val) > $total_endp); - if ($new<$min_endp){ - - } - elsif ($new > $val){ - $assigned{$r} = $new; - $total_endp-=($new - $val); - $valid = 1; - } elsif ($val < $router_Pnum-2 && $val +1 <=$max_endp ){ - $assigned{$r} = $val +1; - $total_endp-=1; - $valid = 1; - } - }#else - }#for - - }#while - - if ($total_endp > 0) { - add_colored_info($info, "Error: Unable to assign all endpoits to routers using requested configuration. Total of $total_endp endpoints left unconnected\n",'red'); - return (\%assigned,0); - } - - return (\%assigned,1); - + my ($self,$routers_ref,$total_endp, $min_endp,$max_endp,$dist_endp,$info)=@_; + my @routers = @{$routers_ref}; + my %assigned; + my $total_router = scalar @routers; + my $valid=1; + while ($total_endp > 0 && $valid ==1){ + $valid =0; + foreach my $r (reverse @routers) { + my $router_Pnum=$self->object_get_attribute("$r",'PNUM'); + my $val = $assigned{$r}; + if (!defined $val) { + $val=0; + $assigned{$r}=0; + } + if ($min_endp >=$router_Pnum || $total_endp ==0 ){ + } else{ + my $new =get_new_val_based_on_dist ($total_router,$total_endp, $router_Pnum,$min_endp,$max_endp,$dist_endp); + $new =$val + $total_endp if(($new - $val) > $total_endp); + if ($new<$min_endp){ + } + elsif ($new > $val){ + $assigned{$r} = $new; + $total_endp-=($new - $val); + $valid = 1; + } elsif ($val < $router_Pnum-2 && $val +1 <=$max_endp ){ + $assigned{$r} = $val +1; + $total_endp-=1; + $valid = 1; + } + }#else + }#for + }#while + if ($total_endp > 0) { + add_colored_info($info, "Error: Unable to assign all endpoits to routers using requested configuration. Total of $total_endp endpoints left unconnected\n",'red'); + return (\%assigned,0); + } + return (\%assigned,1); } - #list the manhatan distance of all nodes in dimention ($xd,$yd,$zd) to the node located in ($xm,$ym,$zm) sub list_manhatan_distance { - my ($xd,$yd,$zd,$xm,$ym,$zm)=@_; - my %manhatan; - for( my $x=0; $x<$xd;$x++){ - for( my $y=0; $y<$yd;$y++){ - for( my $z=0; $z<$zd;$z++){ - $manhatan{"$x,$y,$z"} = abs($x-$xm) + abs($y-$ym) + abs($z-$zm); - } - } - } - return %manhatan; + my ($xd,$yd,$zd,$xm,$ym,$zm)=@_; + my %manhatan; + for( my $x=0; $x<$xd;$x++){ + for( my $y=0; $y<$yd;$y++){ + for( my $z=0; $z<$zd;$z++){ + $manhatan{"$x,$y,$z"} = abs($x-$xm) + abs($y-$ym) + abs($z-$zm); + } + } + } + return %manhatan; } - - sub auto_connect { - my ($self,$info)=@_; - show_colored_info($info, "Start auto connecting Nodes\n",'blue'); - add_info($info, "Step 1: Connect endpoints to the routers:\n"); - - - my $min_endp = $self->object_get_attribute('connection_auto','MIN_ENDP_PER_ROUTER'); - my $max_endp = $self->object_get_attribute('connection_auto','MAX_ENDP_PER_ROUTER'); - my $dist_endp = $self->object_get_attribute('connection_auto','ENDP_PER_ROUTER_DIST'); - my $dimention = $self->object_get_attribute('connection_auto','DIMENTION'); - - - #check min and max is correct - if($min_endp > $max_endp ){ - add_colored_info($info, "Error: Invalid Min & Max range for endpoint router numbr per router. MAX_ENDP_PER_ROUTER shuld >= MIN_ENDP_PER_ROUTER\n",'red'); - } - - initial_node_info($self); - - my @all_endpoints=get_list_of_all_endpoints($self); - my @routers=get_list_of_all_routers($self); - - #connect endpoints - my ($ref,$result) = assign_endp_num_based_on_dist ($self,\@routers,scalar @all_endpoints, $min_endp,$max_endp,$dist_endp,$info); - my %assign = %{$ref}; - my %router_free_port; - foreach my $r (reverse @routers) { - $router_free_port{$r}=$self->object_get_attribute("$r",'PNUM'); - my $num = $assign{$r}; - for (my $p=0; $p<$num;$p++){ - my $e = pop (@all_endpoints); - connect_nodes ($self,$r,"Port[$p]",$e,"Port[0]",$info); - my $rinst=$self->object_get_attribute("$r",'NAME'); - my $einst=$self->object_get_attribute("$e",'NAME'); - add_info($info,"\t connect $rinst-Port[$p] -> $einst-Port[0]\n",$info); - $router_free_port{$r}=$router_free_port{$r}-1; - } - } - - #get dimention - my $routers_num =scalar @routers; - my ($xd,$yd,$zd)=(1,1,1); - ($xd,$yd)= network_dim_cal ($routers_num) if ($dimention eq '2D'); - ($xd,$yd,$zd)=network_3dim_cal ($routers_num) if ($dimention eq '3D'); - add_info($info, "Step 2: Map $routers_num routers in (x=$xd , y=$yd , z=$zd) dimention. Routers with higher number of free ports located in center:\n"); - - #obtain routers location - #center loc - my $xmid =int($xd/2); - my $ymid =int($yd/2); - my $zmid =int($zd/2); - - #sort location based on manhatan distanc from the center - my %manhatan = list_manhatan_distance ($xd,$yd,$zd,$xmid,$ymid,$zmid); - my @sort_locs = (sort { $manhatan{$a} <=> $manhatan{$b} } keys %manhatan); - - #sort routers based on avilable ports - my @sort_routers = (sort { $router_free_port{$b} <=> $router_free_port{$a} } keys %router_free_port); - - #assign sorted routers to sorted locations - my %locations; - foreach my $r (@sort_routers){ - my $loc = shift @sort_locs; - my $inst=$self->object_get_attribute("$r",'NAME'); - add_info($info, "\t $inst with $router_free_port{$r} free port placed in $loc location\n"); - $self->object_add_attribute("$r",'LOC_ASIC',$loc); - $locations{$loc}=$r; - } - - #start from the center and connect each router to the N nearest router - add_info($info,"Step3 : start from the center and connect each router to the N nearest router\n",$info); - foreach my $r (@sort_routers){ - - my $avb_P_num =$router_free_port{$r}; - my @up = list_node_unconnected_port($self,$r); - my @cp = list_node_connected_port ($self,$r); - my $loc = $self->object_get_attribute("$r",'LOC_ASIC'); - my ($xc,$yc,$zc)=split(',',$loc); - my %manhatan = list_manhatan_distance ($xd,$yd,$zd,$xc,$yc,$zc); - my @sort_locs = (sort { $manhatan{$a} <=> $manhatan{$b} } keys %manhatan); - - while (scalar @up && scalar @sort_locs){ - #select one unconnected port from current router - my $p = shift @up; - my $cr; - my $cp; - while (scalar @sort_locs && !defined $cp){ - #select the nearest router to current one - my $cl =shift @sort_locs; - $cr=$locations{$cl}; - next if(!defined $cr); - next if ($cr eq $r); #thes two routers are identical - #check if they are not connected - my $line =get_connection_port_num_between_two_nodes($self,$r,$cr); - next if (defined $line); #these two routers are already connected - my @up_cr = list_node_unconnected_port($self,$cr); - next if (scalar @up_cr == 0); # the target router has no free port - $cp=$up_cr[0]; - } - last if(!defined $cp); - my $rinst=$self->object_get_attribute("$r",'NAME'); - my $einst=$self->object_get_attribute("$cr",'NAME'); - add_info($info,"\t connect $rinst-$p -> $einst-$cp\n",$info); - connect_nodes ($self,$r,"$p",$cr,"$cp",$info); - } - - } - - - - - - - set_gui_status($self,"ref",1); - - - - - + my ($self,$info)=@_; + show_colored_info($info, "Start auto connecting Nodes\n",'blue'); + add_info($info, "Step 1: Connect endpoints to the routers:\n"); + my $min_endp = $self->object_get_attribute('connection_auto','MIN_ENDP_PER_ROUTER'); + my $max_endp = $self->object_get_attribute('connection_auto','MAX_ENDP_PER_ROUTER'); + my $dist_endp = $self->object_get_attribute('connection_auto','ENDP_PER_ROUTER_DIST'); + my $dimention = $self->object_get_attribute('connection_auto','DIMENTION'); + #check min and max is correct + if($min_endp > $max_endp ){ + add_colored_info($info, "Error: Invalid Min & Max range for endpoint router numbr per router. MAX_ENDP_PER_ROUTER shuld >= MIN_ENDP_PER_ROUTER\n",'red'); + } + initial_node_info($self); + my @all_endpoints=get_list_of_all_endpoints($self); + my @routers=get_list_of_all_routers($self); + #connect endpoints + my ($ref,$result) = assign_endp_num_based_on_dist ($self,\@routers,scalar @all_endpoints, $min_endp,$max_endp,$dist_endp,$info); + my %assign = %{$ref}; + my %router_free_port; + foreach my $r (reverse @routers) { + $router_free_port{$r}=$self->object_get_attribute("$r",'PNUM'); + my $num = $assign{$r}; + for (my $p=0; $p<$num;$p++){ + my $e = pop (@all_endpoints); + connect_nodes ($self,$r,"Port[$p]",$e,"Port[0]",$info); + my $rinst=$self->object_get_attribute("$r",'NAME'); + my $einst=$self->object_get_attribute("$e",'NAME'); + add_info($info,"\t connect $rinst-Port[$p] -> $einst-Port[0]\n",$info); + $router_free_port{$r}=$router_free_port{$r}-1; + } + } + #get dimention + my $routers_num =scalar @routers; + my ($xd,$yd,$zd)=(1,1,1); + ($xd,$yd)= network_dim_cal ($routers_num) if ($dimention eq '2D'); + ($xd,$yd,$zd)=network_3dim_cal ($routers_num) if ($dimention eq '3D'); + add_info($info, "Step 2: Map $routers_num routers in (x=$xd , y=$yd , z=$zd) dimention. Routers with higher number of free ports located in center:\n"); + #obtain routers location + #center loc + my $xmid =int($xd/2); + my $ymid =int($yd/2); + my $zmid =int($zd/2); + #sort location based on manhatan distanc from the center + my %manhatan = list_manhatan_distance ($xd,$yd,$zd,$xmid,$ymid,$zmid); + my @sort_locs = (sort { $manhatan{$a} <=> $manhatan{$b} } keys %manhatan); + #sort routers based on avilable ports + my @sort_routers = (sort { $router_free_port{$b} <=> $router_free_port{$a} } keys %router_free_port); + #assign sorted routers to sorted locations + my %locations; + foreach my $r (@sort_routers){ + my $loc = shift @sort_locs; + my $inst=$self->object_get_attribute("$r",'NAME'); + add_info($info, "\t $inst with $router_free_port{$r} free port placed in $loc location\n"); + $self->object_add_attribute("$r",'LOC_ASIC',$loc); + $locations{$loc}=$r; + } + #start from the center and connect each router to the N nearest router + add_info($info,"Step3 : start from the center and connect each router to the N nearest router\n",$info); + foreach my $r (@sort_routers){ + my $avb_P_num =$router_free_port{$r}; + my @up = list_node_unconnected_port($self,$r); + my @cp = list_node_connected_port ($self,$r); + my $loc = $self->object_get_attribute("$r",'LOC_ASIC'); + my ($xc,$yc,$zc)=split(',',$loc); + my %manhatan = list_manhatan_distance ($xd,$yd,$zd,$xc,$yc,$zc); + my @sort_locs = (sort { $manhatan{$a} <=> $manhatan{$b} } keys %manhatan); + while (scalar @up && scalar @sort_locs){ + #select one unconnected port from current router + my $p = shift @up; + my $cr; + my $cp; + while (scalar @sort_locs && !defined $cp){ + #select the nearest router to current one + my $cl =shift @sort_locs; + $cr=$locations{$cl}; + next if(!defined $cr); + next if ($cr eq $r); #thes two routers are identical + #check if they are not connected + my $line =get_connection_port_num_between_two_nodes($self,$r,$cr); + next if (defined $line); #these two routers are already connected + my @up_cr = list_node_unconnected_port($self,$cr); + next if (scalar @up_cr == 0); # the target router has no free port + $cp=$up_cr[0]; + } + last if(!defined $cp); + my $rinst=$self->object_get_attribute("$r",'NAME'); + my $einst=$self->object_get_attribute("$cr",'NAME'); + add_info($info,"\t connect $rinst-$p -> $einst-$cp\n",$info); + connect_nodes ($self,$r,"$p",$cr,"$cp",$info); + } + } + set_gui_status($self,"ref",1); } sub routing_page_auto{ - my ($self,$info)=@_; - my $table= def_table(2,10,FALSE); - my $row=0; - my $col=0; - - - $self->object_add_attribute('routing','type','turn_model'); - - - - my $auto = def_image_button('icons/gen.png','AutoGenerate'); - #$table->attach ($auto,0, 1, $row, $row+1,'fill','fill',2,2); - my $clear = def_image_button('icons/clear.png','Clear'); - #$table->attach ($clear,2,3 , $row, $row+1,'fill','fill',2,2);$row++; - - my $box= def_pack_hbox( FALSE, 0 , $auto,$clear); - $table->attach ($box,0,5 , $row, $row+1,'fill','fill',2,2);$row++; - - $auto-> signal_connect("clicked" => sub{ - auto_route($self,$info); - }); - - $clear-> signal_connect("clicked" => sub{ - clean_route($self,$info); - }); - - my $manual = get_route_manual ($self,$info); - - my $mtable= def_table(2,2,FALSE); - - $mtable->attach_defaults ($table , 0, 1, 0,1); - $mtable->attach_defaults ($manual , 0, 1, 1,2); - - return $mtable; + my ($self,$info)=@_; + my $table= def_table(2,10,FALSE); + my $row=0; + my $col=0; + $self->object_add_attribute('routing','type','turn_model'); + my $auto = def_image_button('icons/gen.png','AutoGenerate'); + #$table->attach ($auto,0, 1, $row, $row+1,'fill','fill',2,2); + my $clear = def_image_button('icons/clear.png','Clear'); + #$table->attach ($clear,2,3 , $row, $row+1,'fill','fill',2,2);$row++; + my $box= def_pack_hbox( FALSE, 0 , $auto,$clear); + $table->attach ($box,0,5 , $row, $row+1,'fill','fill',2,2);$row++; + $auto-> signal_connect("clicked" => sub{ + auto_route($self,$info); + }); + $clear-> signal_connect("clicked" => sub{ + clean_route($self,$info); + }); + my $manual = get_route_manual ($self,$info); + my $mtable= def_table(2,2,FALSE); + $mtable->attach_defaults ($table , 0, 1, 0,1); + $mtable->attach_defaults ($manual , 0, 1, 1,2); + return $mtable; } sub update_acycle_model { - my ($self,$alg_name,$info)=@_; - my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; - my $model_file = "$tmp_dir/$alg_name.alg"; - my ($pp,$r,$err) = regen_object($model_file); - if ($r){ - add_colored_info($info,"**Error: cannot open $model_file file: $err\n",'red'); - $self->object_add_attribute('routing_auto','acyclic_turns_model',undef); - return; - } else { - add_info($info,"Use $alg_name algorithm for obtaing acyclic paths\n"); - } - - my @acyclic_turns = @{$pp}; - $self->object_add_attribute('routing_auto','acyclic_turns_model',\@acyclic_turns); - -} - + my ($self,$alg_name,$info)=@_; + my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; + my $model_file = "$tmp_dir/$alg_name.alg"; + my ($pp,$r,$err) = regen_object($model_file); + if ($r){ + add_colored_info($info,"**Error: cannot open $model_file file: $err\n",'red'); + $self->object_add_attribute('routing_auto','acyclic_turns_model',undef); + return; + } else { + add_info($info,"Use $alg_name algorithm for obtaing acyclic paths\n"); + } + my @acyclic_turns = @{$pp}; + $self->object_add_attribute('routing_auto','acyclic_turns_model',\@acyclic_turns); +} sub routing_page_manual{ - my ($self,$info)=@_; - my $table= def_table(2,10,FALSE); - my $row=0; - my $col=0; - - $self->object_add_attribute('routing','type','minimal'); - - initial_node_info($self); - my $help1 = "Define the offset path value that is the maximum difference between the lentght of all paths which are extracted for any specefic source-destination endpoints pair. Define this valuse as zero for Minimal-path (MIN) routing algorithms."; - my $help2 = "Define the maximum number of routers (path length) paths which should be extracted for any specefic source-destination endpoints pair."; - my $help3 = "Define how to extract paths between two endpoints: all-paths: extract all paths between two specific endpoints that match the offset size and maximum size parameters. Cycle-free: only paths which do not generate a cyclic dependency in routing graph are extracted."; - - - my @widgets = ( - { label=>"Route path offset size ", param_name=>'OFFSET', type=>"Spin-button", default_val=>1, content=>"0,1024,1", info=>$help1, param_parent=>'routing_auto', ref_delay=>"1",ref_state=> undef}, - { label=>"Route path maximum size", param_name=>'MAX_LENGTH', type=>"Spin-button", default_val=>1000, content=>"1,1024,1", info=>$help2, param_parent=>'routing_auto', ref_delay=>"1",ref_state=> undef}, - { label=>"Route paths select", param_name=>'PATH_SELECT', type=>"Combo-box", default_val=>"Cycle-free paths", content=>"all-paths,Cycle-free paths", info=>$help3, param_parent=>'routing_auto', ref_delay=>"1",ref_state=> undef }, - - ); - - - foreach my $d (@widgets) { - my $w; - ($row,$col,$w)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},$d->{ref_state},"vertical"); - - }#foreach - my $offset = $self->object_get_attribute('routing_auto','OFFSET'); - my $max_len = $self->object_get_attribute('routing_auto','MAX_LENGTH'); - - my $auto = def_image_button('icons/gen.png','AutoGenerate'); - - my $path_select= $self->object_get_attribute("routing_auto",'PATH_SELECT'); - if($path_select eq "Cycle-free paths") { - my %algorithms; - my $ref =$self->object_get_attribute('routing_auto','acyclic_algorithms'); - %algorithms = %{$ref} if defined $ref; - my @algs = sort { $algorithms{$a} <=> $algorithms{$b} } keys(%algorithms); - my ($content,$default); - foreach my $alg (@algs){ - $content.="$alg -- $algorithms{$alg},"; - $default= "$alg -- $algorithms{$alg};"; - - } - if (!defined $content){ - $content='-'; - $default='-'; - - } - - my $alg; - ($row,$col,$alg)=add_param_widget ($self,"cycle-remove algorithm:" , "CYCLE_FREE_ALG",$default , "Combo-box", $content, undef, $table,$row,$col,1,'routing_auto', undef,undef,"vertical"); - - $alg->signal_connect("changed" => sub{ - my $comb_text = $alg->get_active_text(); - my ($alg_name,$line) = split (/\s+--\s+/,$comb_text); - update_acycle_model ($self,$alg_name,$info); - #print "bbbb:@acyclic_turns\n"; - }); - - $auto-> signal_connect("clicked" => sub{ - auto_route($self,$info); - }); - - - } - - - - - my $clear = def_image_button('icons/clear.png','Clear'); - my $gen_cycle_free = def_image_button('icons/turn.png','Generate Cycle-free Paths'); - - if($path_select eq 'Cycle-free paths') { - $table->attach ($gen_cycle_free,0,2 , $row, $row+1,'fill','fill',2,2);$row++; - $table->attach ($auto,2, 3, $row, $row+1,'fill','fill',2,2); - - } - $table->attach ($clear,0,2 , $row, $row+1,'fill','fill',2,2);$row++; - - - $clear-> signal_connect("clicked" => sub{ - clean_route($self,$info); - }); - - $gen_cycle_free -> signal_connect("clicked" => sub{ - gen_aciclic_turn_graph($self,$info); - my %algorithms; - my $ref =$self->object_get_attribute('routing_auto','acyclic_algorithms'); - %algorithms = %{$ref} if defined $ref; - my @algs = sort { $algorithms{$a} <=> $algorithms{$b} } keys(%algorithms); - update_acycle_model ($self,$algs[0],$info); - set_gui_status($self,'ref',1); - }); - - my $manual = get_route_manual ($self,$info); - - my $mtable= def_table(2,2,FALSE); - - $mtable->attach_defaults ($table , 0, 1, 0,1); - $mtable->attach_defaults ($manual , 0, 1, 1,2); - - return $mtable; + my ($self,$info)=@_; + my $table= def_table(2,10,FALSE); + my $row=0; + my $col=0; + $self->object_add_attribute('routing','type','minimal'); + initial_node_info($self); + my $help1 = "Define the offset path value that is the maximum difference between the lentght of all paths which are extracted for any specefic source-destination endpoints pair. Define this valuse as zero for Minimal-path (MIN) routing algorithms."; + my $help2 = "Define the maximum number of routers (path length) paths which should be extracted for any specefic source-destination endpoints pair."; + my $help3 = "Define how to extract paths between two endpoints: all-paths: extract all paths between two specific endpoints that match the offset size and maximum size parameters. Cycle-free: only paths which do not generate a cyclic dependency in routing graph are extracted."; + my @widgets = ( + { label=>"Route path offset size ", param_name=>'OFFSET', type=>"Spin-button", default_val=>1, content=>"0,1024,1", info=>$help1, param_parent=>'routing_auto', ref_delay=>"1",ref_state=> undef}, + { label=>"Route path maximum size", param_name=>'MAX_LENGTH', type=>"Spin-button", default_val=>1000, content=>"1,1024,1", info=>$help2, param_parent=>'routing_auto', ref_delay=>"1",ref_state=> undef}, + { label=>"Route paths select", param_name=>'PATH_SELECT', type=>"Combo-box", default_val=>"Cycle-free paths", content=>"all-paths,Cycle-free paths", info=>$help3, param_parent=>'routing_auto', ref_delay=>"1",ref_state=> undef }, + ); + foreach my $d (@widgets) { + my $w; + ($row,$col,$w)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},$d->{ref_state},"vertical"); + }#foreach + my $offset = $self->object_get_attribute('routing_auto','OFFSET'); + my $max_len = $self->object_get_attribute('routing_auto','MAX_LENGTH'); + my $auto = def_image_button('icons/gen.png','AutoGenerate'); + my $path_select= $self->object_get_attribute("routing_auto",'PATH_SELECT'); + if($path_select eq "Cycle-free paths") { + my %algorithms; + my $ref =$self->object_get_attribute('routing_auto','acyclic_algorithms'); + %algorithms = %{$ref} if defined $ref; + my @algs = sort { $algorithms{$a} <=> $algorithms{$b} } keys(%algorithms); + my ($content,$default); + foreach my $alg (@algs){ + $content.="$alg -- $algorithms{$alg},"; + $default= "$alg -- $algorithms{$alg};"; + } + if (!defined $content){ + $content='-'; + $default='-'; + } + my $alg; + ($row,$col,$alg)=add_param_widget ($self,"cycle-remove algorithm:" , "CYCLE_FREE_ALG",$default , "Combo-box", $content, undef, $table,$row,$col,1,'routing_auto', undef,undef,"vertical"); + $alg->signal_connect("changed" => sub{ + my $comb_text = $alg->get_active_text(); + my ($alg_name,$line) = split (/\s+--\s+/,$comb_text); + update_acycle_model ($self,$alg_name,$info); + #print "bbbb:@acyclic_turns\n"; + }); + $auto-> signal_connect("clicked" => sub{ + auto_route($self,$info); + }); + } + my $clear = def_image_button('icons/clear.png','Clear'); + my $gen_cycle_free = def_image_button('icons/turn.png','Generate Cycle-free Paths'); + if($path_select eq 'Cycle-free paths') { + $table->attach ($gen_cycle_free,0,2 , $row, $row+1,'fill','fill',2,2);$row++; + $table->attach ($auto,2, 3, $row, $row+1,'fill','fill',2,2); + } + $table->attach ($clear,0,2 , $row, $row+1,'fill','fill',2,2);$row++; + $clear-> signal_connect("clicked" => sub{ + clean_route($self,$info); + }); + $gen_cycle_free -> signal_connect("clicked" => sub{ + gen_aciclic_turn_graph($self,$info); + my %algorithms; + my $ref =$self->object_get_attribute('routing_auto','acyclic_algorithms'); + %algorithms = %{$ref} if defined $ref; + my @algs = sort { $algorithms{$a} <=> $algorithms{$b} } keys(%algorithms); + update_acycle_model ($self,$algs[0],$info); + set_gui_status($self,'ref',1); + }); + my $manual = get_route_manual ($self,$info); + my $mtable= def_table(2,2,FALSE); + $mtable->attach_defaults ($table , 0, 1, 0,1); + $mtable->attach_defaults ($manual , 0, 1, 1,2); + return $mtable; } - - - sub get_route_manual { - my ($self,$info)=@_; - - my $row=0; - my $col=0; - - my $table= def_table(2,10,FALSE); - - add_Hsep_to_table ($table,0, 200, $row);$row++; - - my $refresh = def_image_button('icons/refresh.png','Refresh'); - $table->attach ($refresh,0,5 , $row, $row+1,'fill','fill',2,2);$row++; - - - $table->attach (gen_colored_label('Not selected',17),5,10,$row,$row+1,'fill','shrink',2,2); - $table->attach (gen_colored_label('Selected',0),10,15,$row,$row+1,'fill','shrink',2,2); - $table->attach (gen_colored_label('Not Existed',11),15,20,$row,$row+1,'fill','shrink',2,2); - $row++; - - $table->attach (def_label(' source -> destination '),10,15,$row,$row+1,'fill','shrink',2,2); - $row++; - - - my @all_endpoints=get_list_of_all_endpoints($self); - - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - my $src_inst=$self->object_get_attribute("$src",'NAME'); - my $dst_inst=$self->object_get_attribute("$dst",'NAME'); - my $select = $self->object_get_attribute('Route',"${src}::$dst"); - - #my ($paths_to_dst,$ports_to_dst); #= get_all_paths_between_two_endps($self,$src, $dst); - #my $color =(scalar @{$paths_to_dst}==0)? 11 : (defined $select)? 0 : 17; - #my $button = ($src_inst ne $dst_inst )? def_colored_button("${src_inst}->$dst_inst",$color): gen_label_in_center(' - '); - - my $color = (defined $select)? 0 :17; - my $button = ($src_inst ne $dst_inst )? def_colored_button("${src_inst}->$dst_inst",$color): gen_label_in_center(' - '); - - - attach_widget_to_table ($table,$row,undef,undef,$button,$col); $col+=4; - - - - $button->signal_connect("clicked" => sub { - $self->object_add_attribute("SELECT_PATH","src",$src); - $self->object_add_attribute("SELECT_PATH","dst",$dst); - set_gui_status($self,"redraw",1); - - }) if($src_inst ne $dst_inst ); - - - }$row++;$col=0; - } - - - $refresh->signal_connect("clicked" => sub{ - refresh_route_manual($self,$info); - }); - - return $table; + my ($self,$info)=@_; + my $row=0; + my $col=0; + my $table= def_table(2,10,FALSE); + add_Hsep_to_table ($table,0, 200, $row);$row++; + my $refresh = def_image_button('icons/refresh.png','Refresh'); + $table->attach ($refresh,0,5 , $row, $row+1,'fill','fill',2,2);$row++; + $table->attach (gen_colored_label('Not selected',17),5,10,$row,$row+1,'fill','shrink',2,2); + $table->attach (gen_colored_label('Selected',0),10,15,$row,$row+1,'fill','shrink',2,2); + $table->attach (gen_colored_label('Not Existed',11),15,20,$row,$row+1,'fill','shrink',2,2); + $row++; + $table->attach (def_label(' source -> destination '),10,15,$row,$row+1,'fill','shrink',2,2); + $row++; + my @all_endpoints=get_list_of_all_endpoints($self); + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + my $src_inst=$self->object_get_attribute("$src",'NAME'); + my $dst_inst=$self->object_get_attribute("$dst",'NAME'); + my $select = $self->object_get_attribute('Route',"${src}::$dst"); + #my ($paths_to_dst,$ports_to_dst); #= get_all_paths_between_two_endps($self,$src, $dst); + #my $color =(scalar @{$paths_to_dst}==0)? 11 : (defined $select)? 0 : 17; + #my $button = ($src_inst ne $dst_inst )? def_colored_button("${src_inst}->$dst_inst",$color): gen_label_in_center(' - '); + my $color = (defined $select)? 0 :17; + my $button = ($src_inst ne $dst_inst )? def_colored_button("${src_inst}->$dst_inst",$color): gen_label_in_center(' - '); + attach_widget_to_table ($table,$row,undef,undef,$button,$col); $col+=4; + $button->signal_connect("clicked" => sub { + $self->object_add_attribute("SELECT_PATH","src",$src); + $self->object_add_attribute("SELECT_PATH","dst",$dst); + set_gui_status($self,"redraw",1); + }) if($src_inst ne $dst_inst ); + }$row++;$col=0; + } + $refresh->signal_connect("clicked" => sub{ + refresh_route_manual($self,$info); + }); + return $table; } - sub refresh_route_manual { - my ($self,$info)=@_; - my @all_endpoints=get_list_of_all_endpoints($self); - - my $path_select= $self->object_get_attribute("routing_auto",'PATH_SELECT'); - my @acyclic_turns; - - - if ($path_select ne "all-paths"){ - my $ref = $self->object_get_attribute('routing_auto','acyclic_turns_model'); - if(defined $ref) { - @acyclic_turns = @{$ref}; - }else{ - add_colored_info($info,"Info:No acyclic route model is selected\n",'green'); - - } - } - - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - my $src_inst=$self->object_get_attribute("$src",'NAME'); - my $dst_inst=$self->object_get_attribute("$dst",'NAME'); - my $select = $self->object_get_attribute('Route',"${src}::$dst"); - - my ($ref1,$ref2)= ($path_select eq "all-paths")? get_all_paths_between_two_endps($self,$src, $dst) : get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,\@acyclic_turns) ; - my @paths = @{$ref1}; - if (defined $select){ - #check if select exist in @paths - my $match=0; - - foreach my $p (@paths ){ - my @a1 = @{$p}; - my @a2 = @{$select}; - my $st1=join('->',@a1); - my $st2=join('->',@a2); - if($st1 eq $st2){ - $match=1; - } - }#foreach - #remove it from the selected path - if ($match ==0){ - my $selp; - foreach my $q ( @{$select}){ - my $inst=$self->object_get_attribute("$q",'NAME'); - $selp= (defined $selp)? $selp."->$inst" : $inst; - } - - add_info ($info,"$selp does not exist in path list anymore and it has been removed\n"); - $self->object_add_attribute('Route',"${src}::$dst",undef); - }#if - }#if - }#foreach - }#foreach - - - set_gui_status($self,"ref",1); - -} - + my ($self,$info)=@_; + my @all_endpoints=get_list_of_all_endpoints($self); + my $path_select= $self->object_get_attribute("routing_auto",'PATH_SELECT'); + my @acyclic_turns; + if ($path_select ne "all-paths"){ + my $ref = $self->object_get_attribute('routing_auto','acyclic_turns_model'); + if(defined $ref) { + @acyclic_turns = @{$ref}; + }else{ + add_colored_info($info,"Info:No acyclic route model is selected\n",'green'); + } + } + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + my $src_inst=$self->object_get_attribute("$src",'NAME'); + my $dst_inst=$self->object_get_attribute("$dst",'NAME'); + my $select = $self->object_get_attribute('Route',"${src}::$dst"); + my ($ref1,$ref2)= ($path_select eq "all-paths")? get_all_paths_between_two_endps($self,$src, $dst) : get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,\@acyclic_turns) ; + my @paths = @{$ref1}; + if (defined $select){ + #check if select exist in @paths + my $match=0; + foreach my $p (@paths ){ + my @a1 = @{$p}; + my @a2 = @{$select}; + my $st1=join('->',@a1); + my $st2=join('->',@a2); + if($st1 eq $st2){ + $match=1; + } + }#foreach + #remove it from the selected path + if ($match ==0){ + my $selp; + foreach my $q ( @{$select}){ + my $inst=$self->object_get_attribute("$q",'NAME'); + $selp= (defined $selp)? $selp."->$inst" : $inst; + } + add_info ($info,"$selp does not exist in path list anymore and it has been removed\n"); + $self->object_add_attribute('Route',"${src}::$dst",undef); + }#if + }#if + }#foreach + }#foreach + set_gui_status($self,"ref",1); +} sub route_info_window{ - my ($self,$info)= @_; - my $w1 = show_paths_between_two_endps($self,$info); - my $w2 = routing_summary($self,$info); - my $h1=gen_hpaned($w1,.30,$w2); - return $h1; + my ($self,$info)= @_; + my $w1 = show_paths_between_two_endps($self,$info); + my $w2 = routing_summary($self,$info); + my $h1=gen_hpaned($w1,.30,$w2); + return $h1; } - - sub add_route_edge_to_graph{ - my ($gref,$anodes_ref)=@_; - my %graph=%{$gref}; - my @a_nodes= @{$anodes_ref}; - - my $old_r; - foreach my $r (@a_nodes){ - - if(defined $old_r){ - push(@{$graph{$old_r}},$r); - } - $old_r=$r; - } - - return %graph; + my ($gref,$anodes_ref)=@_; + my %graph=%{$gref}; + my @a_nodes= @{$anodes_ref}; + my $old_r; + foreach my $r (@a_nodes){ + if(defined $old_r){ + push(@{$graph{$old_r}},$r); + } + $old_r=$r; + } + return %graph; } sub get_adjacent_node_in_a_path{ - my $ref=shift; - my @result; - my @path=@{$ref}; - my $old_r; - foreach my $r (@path){ - push (@result,"${old_r}::$r") if(defined $old_r); - $old_r=$r; - } - return @result; - + my $ref=shift; + my @result; + my @path=@{$ref}; + my $old_r; + foreach my $r (@path){ + push (@result,"${old_r}::$r") if(defined $old_r); + $old_r=$r; + } + return @result; } sub get_adjacent_router_in_a_path{ - - my $ref=shift; - my @result; - my @path=@{$ref}; - shift @path; #remove source node from the path - pop @path; #remove the destination node from the path - - - my $old_r; - foreach my $r (@path){ - push (@result,"${old_r}::$r") if(defined $old_r); - $old_r=$r; - } - return @result; - + my $ref=shift; + my @result; + my @path=@{$ref}; + shift @path; #remove source node from the path + pop @path; #remove the destination node from the path + my $old_r; + foreach my $r (@path){ + push (@result,"${old_r}::$r") if(defined $old_r); + $old_r=$r; + } + return @result; } - sub get_route_info{ - my ($self)=@_; - my %R_num; - my %L_num; - my @all_endpoints=get_list_of_all_endpoints($self); - foreach my $r (@all_endpoints ){ - #$R_num{$r} =0; - } - my @nodes=get_list_of_all_routers($self); - foreach my $p (@nodes){ - $R_num{$p} =0; - } - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - my $path = $self->object_get_attribute('Route',"${src}::$dst"); - if (defined $path){ - #router counting - my @p=@{$path}; - shift @p; #remove source node from the path - pop @p; #remove the destination node from the path - foreach my $r (@p){ - $R_num{$r} ++; - } - #path counting - @p= get_adjacent_router_in_a_path($path); - foreach my $r (@p){ - $L_num{$r} ++; - - } - - - } - } - } - - my @Rkeys = sort { $R_num{$a} <=> $R_num{$b} } keys(%R_num); - my @Lkeys = sort { $L_num{$a} <=> $L_num{$b} } keys(%L_num); - my $sample="sample0"; - foreach my $r (@nodes ){ - my $inst=$self->object_get_attribute("$r",'NAME'); - update_result ($self,$sample,"router_all_paths_result",'-',$inst,$R_num{$r}); - } - - my $max_r = (defined $Rkeys[-1]) ? $R_num{$Rkeys[-1]} : 0; - my $min_r = (defined $Rkeys[ 0]) ? $R_num{$Rkeys[ 0]} : 0; - my $max_l = (defined $Lkeys[-1]) ? $L_num{$Lkeys[-1]} : 0; - my $min_l = (defined $Lkeys[ 0]) ? $L_num{$Lkeys[ 0]} : 0; - my @l = sort values (%L_num); - my $std_l=stdev(\@l); - - $self->object_add_attribute ($sample,"link_all_paths_result",undef); - - my $nn=0; - my $min_l_name="-"; - my $max_l_name="-"; - my $siz = $#Lkeys; - foreach my $r (@Lkeys ){ - my ($n1,$n2)=split(/::/,$r); - my $inst1=$self->object_get_attribute("$n1",'NAME'); - my $inst2=$self->object_get_attribute("$n2",'NAME'); - my $inst = "$inst1-$inst2"; - update_result ($self,$sample,"link_all_paths_result",'-',$inst,$L_num{$r}); - $min_l_name= $inst if($nn==0); - $max_l_name= $inst if($nn==$siz-1); - $nn++; - } - - - - my $max_r_name= (defined $Rkeys[-1])? $self->object_get_attribute("$Rkeys[-1]",'NAME') : "-"; - my $min_r_name= (defined $Rkeys[0]) ? $self->object_get_attribute("$Rkeys[0]",'NAME') : "-"; - - $max_r_name= "-" if (!defined $max_r_name); - $min_r_name= "-" if (!defined $min_r_name); - - - return ($max_r,$min_r,$max_l,$min_l,$std_l,$max_r_name,$min_r_name,$max_l_name,$min_l_name); -} - + my ($self)=@_; + my %R_num; + my %L_num; + my @all_endpoints=get_list_of_all_endpoints($self); + foreach my $r (@all_endpoints ){ + #$R_num{$r} =0; + } + my @nodes=get_list_of_all_routers($self); + foreach my $p (@nodes){ + $R_num{$p} =0; + } + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + my $path = $self->object_get_attribute('Route',"${src}::$dst"); + if (defined $path){ + #router counting + my @p=@{$path}; + shift @p; #remove source node from the path + pop @p; #remove the destination node from the path + foreach my $r (@p){ + $R_num{$r} ++; + } + #path counting + @p= get_adjacent_router_in_a_path($path); + foreach my $r (@p){ + $L_num{$r} ++; + } + } + } + } + my @Rkeys = sort { $R_num{$a} <=> $R_num{$b} } keys(%R_num); + my @Lkeys = sort { $L_num{$a} <=> $L_num{$b} } keys(%L_num); + my $sample="sample0"; + foreach my $r (@nodes ){ + my $inst=$self->object_get_attribute("$r",'NAME'); + update_result ($self,$sample,"router_all_paths_result",'-',$inst,$R_num{$r}); + } + my $max_r = (defined $Rkeys[-1]) ? $R_num{$Rkeys[-1]} : 0; + my $min_r = (defined $Rkeys[ 0]) ? $R_num{$Rkeys[ 0]} : 0; + my $max_l = (defined $Lkeys[-1]) ? $L_num{$Lkeys[-1]} : 0; + my $min_l = (defined $Lkeys[ 0]) ? $L_num{$Lkeys[ 0]} : 0; + my @l = sort values (%L_num); + my $std_l=stdev(\@l); + $self->object_add_attribute ($sample,"link_all_paths_result",undef); + my $nn=0; + my $min_l_name="-"; + my $max_l_name="-"; + my $siz = $#Lkeys; + foreach my $r (@Lkeys ){ + my ($n1,$n2)=split(/::/,$r); + my $inst1=$self->object_get_attribute("$n1",'NAME'); + my $inst2=$self->object_get_attribute("$n2",'NAME'); + my $inst = "$inst1-$inst2"; + update_result ($self,$sample,"link_all_paths_result",'-',$inst,$L_num{$r}); + $min_l_name= $inst if($nn==0); + $max_l_name= $inst if($nn==$siz-1); + $nn++; + } + my $max_r_name= (defined $Rkeys[-1])? $self->object_get_attribute("$Rkeys[-1]",'NAME') : "-"; + my $min_r_name= (defined $Rkeys[0]) ? $self->object_get_attribute("$Rkeys[0]",'NAME') : "-"; + $max_r_name= "-" if (!defined $max_r_name); + $min_r_name= "-" if (!defined $min_r_name); + return ($max_r,$min_r,$max_l,$min_l,$std_l,$max_r_name,$min_r_name,$max_l_name,$min_l_name); +} sub routing_summary{ - my ($self,$info)= @_; - - my $sc_win = gen_scr_win_with_adjst($self,'map_info'); - #my $table= def_table(10,10,FALSE); - - - my $row=0; - my $col=0; - my ($max_r,$min_r,$max_l,$min_l,$std_l,$max_r_name,$min_r_name,$max_l_name,$min_l_name)=get_route_info($self); - - - my @data = ( - {0 => "The Maximum number that a router is used in routing", 1 =>"$max_r", 2 =>"$max_r_name"}, # The maximum number that a router is located in all paths between all source-destination pair in this routing algorithm. - {0 => "The Minimum number that a router is used in routing", 1 =>"$min_r", 2 =>"$min_r_name" }, - {0 => "The Maximum number that a link is used in routing ", 1 =>"$max_l", 2 =>"$max_l_name"}, # The maximum number that a node-2-node link is located in all paths between all source-destination pair in this routing algorithm. - {0 => "The Minimum number that a link is used in routing", 1=>"$min_l", 2 =>"$min_l_name" }, - {0 => "Link usage standard deviation ", 1 =>"$std_l" } - ); - - - - my @clmn_type = ('Glib::String', # => G_TYPE_STRING - 'Glib::String', - 'Glib::String'); # you get the idea - - my @clmns = ("Routing Summary", " ", " "); - - my $list= gen_list_store (\@data,\@clmn_type,\@clmns); - - - add_widget_to_scrolled_win($list,$sc_win); - - my $charts = gen_routing_charts($self,$info); - - my $v1=gen_vpaned($sc_win,.25,$charts); - - $sc_win->show_all; - - return $v1; - + my ($self,$info)= @_; + my $sc_win = gen_scr_win_with_adjst($self,'map_info'); + #my $table= def_table(10,10,FALSE); + my $row=0; + my $col=0; + my ($max_r,$min_r,$max_l,$min_l,$std_l,$max_r_name,$min_r_name,$max_l_name,$min_l_name)=get_route_info($self); + my @data = ( + {0 => "The Maximum number that a router is used in routing", 1 =>"$max_r", 2 =>"$max_r_name"}, # The maximum number that a router is located in all paths between all source-destination pair in this routing algorithm. + {0 => "The Minimum number that a router is used in routing", 1 =>"$min_r", 2 =>"$min_r_name" }, + {0 => "The Maximum number that a link is used in routing ", 1 =>"$max_l", 2 =>"$max_l_name"}, # The maximum number that a node-2-node link is located in all paths between all source-destination pair in this routing algorithm. + {0 => "The Minimum number that a link is used in routing", 1=>"$min_l", 2 =>"$min_l_name" }, + {0 => "Link usage standard deviation ", 1 =>"$std_l" } + ); + my @clmn_type = ( + 'Glib::String', # => G_TYPE_STRING + 'Glib::String', + 'Glib::String' + ); # you get the idea + my @clmns = ("Routing Summary", " ", " "); + my $list= gen_list_store (\@data,\@clmn_type,\@clmns); + add_widget_to_scrolled_win($list,$sc_win); + my $charts = gen_routing_charts($self,$info); + my $v1=gen_vpaned($sc_win,.25,$charts); + $sc_win->show_all; + return $v1; } - sub gen_routing_charts{ - - my ($self,$info)=@_; - - my @pages =( - {page_name=>" # Routers in all Paths", page_num=>0}, - {page_name=>" # Links in all Paths ", page_num=>1} -); - - - -my @charts = ( - { type=>"3D_bar", page_num=>0, graph_name=> "# Router in all Paths", result_name => "router_all_paths_result", X_Title=> 'Router Name', Y_Title=>'The total number that a router is used in the routing', Z_Title=>undef}, - { type=>"3D_bar", page_num=>1, graph_name=> "# Links in all paths", result_name => "link_all_paths_result", X_Title=> 'Connection Link', Y_Title=>'The total number that a link is used in the routing', Z_Title=>undef}, - #{ type=>"2D_line", page_num=>0, graph_name=> "SD latency", result_name => "sd_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Latency Standard Deviation (clock)', Z_Title=>undef}, - #{ type=>"3D_bar", page_num=>1, graph_name=> "Received", result_name => "packet_rsvd_result", X_Title=>'Core ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, - #{ type=>"3D_bar", page_num=>1, graph_name=> "Sent", result_name => "packet_sent_result", X_Title=>'Core ID' , Y_Title=>'Sent Packets Per Router', Z_Title=>undef}, - - ); - - - my $chart =gen_multiple_charts ($self,\@pages,\@charts,.3); + my ($self,$info)=@_; + my @pages =( + {page_name=>" # Routers in all Paths", page_num=>0}, + {page_name=>" # Links in all Paths ", page_num=>1} + ); + my @charts = ( + { type=>"3D_bar", page_num=>0, graph_name=> "# Router in all Paths", result_name => "router_all_paths_result", X_Title=> 'Router Name', Y_Title=>'The total number that a router is used in the routing', Z_Title=>undef}, + { type=>"3D_bar", page_num=>1, graph_name=> "# Links in all paths", result_name => "link_all_paths_result", X_Title=> 'Connection Link', Y_Title=>'The total number that a link is used in the routing', Z_Title=>undef}, + #{ type=>"2D_line", page_num=>0, graph_name=> "SD latency", result_name => "sd_latency_result", X_Title=> 'Desired Avg. Injected Load Per Router (flits/clock (%))', Y_Title=>'Latency Standard Deviation (clock)', Z_Title=>undef}, + #{ type=>"3D_bar", page_num=>1, graph_name=> "Received", result_name => "packet_rsvd_result", X_Title=>'Core ID' , Y_Title=>'Received Packets Per Router', Z_Title=>undef}, + #{ type=>"3D_bar", page_num=>1, graph_name=> "Sent", result_name => "packet_sent_result", X_Title=>'Core ID' , Y_Title=>'Sent Packets Per Router', Z_Title=>undef}, + ); + my $chart =gen_multiple_charts ($self,\@pages,\@charts,.3); return $chart; - } - - - sub show_paths_between_two_endps{ - my ($self,$info)= @_; - my $table=def_table(20,20,FALSE); - - my $row-=0; - my $col=0; - - my $src = $self->object_get_attribute("SELECT_PATH","src"); - my $dst = $self->object_get_attribute("SELECT_PATH","dst"); - - my @acyclic_turns; - my $path_select= $self->object_get_attribute("routing_auto",'PATH_SELECT'); - if ($path_select ne "all-paths"){ - my $ref = $self->object_get_attribute('routing_auto','acyclic_turns_model'); - if(defined $ref) { - @acyclic_turns = @{$ref}; - }else{ - add_colored_info($info,"Info:No acyclic route model is selected\n",'green'); - - } - } - - - - - - if(defined $src && defined $dst ){ - my $s= $self->object_get_attribute("$src","NAME"); - my $d= $self->object_get_attribute("$dst","NAME"); - $table->attach (def_label("Select path between $s to $d" ),$col,$col+10,$row,$row+1,'fill','shrink',2,2); - add_info($info,"get list of all paths between $s to $d \n") if (defined $info); - $row=1; - my ($ref1,$ref2)= ($path_select eq "all-paths") ? get_all_paths_between_two_endps($self,$src, $dst): - get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,\@acyclic_turns); - - - my @paths = @{$ref1}; - my @ports= @{$ref2}; - my $n=0; - my $select = $self->object_get_attribute('Route',"${src}::$dst"); - foreach my $p (@paths){ - my $scal; - my $selp; - my $path_num=$n; - my $path=$p; - foreach my $q ( @{$p}){ - my $inst=$self->object_get_attribute("$q",'NAME'); - $scal= (defined $scal)? $scal."->$inst" : $inst; - } - - foreach my $q ( @{$select}){ - my $inst=$self->object_get_attribute("$q",'NAME'); - $selp= (defined $selp)? $selp."->$inst" : $inst; - } - - - my $check= gen_checkbutton(); - #print "if($select eq $path)"; - if(defined $select && defined $scal && defined $selp) {if($selp eq $scal) {$check->set_active(TRUE);}} - else {$check->set_active(FALSE);} - - $check-> signal_connect("toggled" => sub{ - if($check->get_active()) { - - $self->object_add_attribute('Route',"${src}::$dst",$path); - } - else { - - $self->object_add_attribute('Route',"${src}::$dst",undef); - } - set_gui_status($self,"ref",1); - }); - - - my $label =gen_label_in_left("$scal"); - $table->attach ($check , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col++; - $table->attach ($label , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++;$col=0; - - $n++; - } - - - } - - return add_widget_to_scrolled_win($table); - + my ($self,$info)= @_; + my $table=def_table(20,20,FALSE); + my $row-=0; + my $col=0; + my $src = $self->object_get_attribute("SELECT_PATH","src"); + my $dst = $self->object_get_attribute("SELECT_PATH","dst"); + my @acyclic_turns; + my $path_select= $self->object_get_attribute("routing_auto",'PATH_SELECT'); + if ($path_select ne "all-paths"){ + my $ref = $self->object_get_attribute('routing_auto','acyclic_turns_model'); + if(defined $ref) { + @acyclic_turns = @{$ref}; + }else{ + add_colored_info($info,"Info:No acyclic route model is selected\n",'green'); + } + } + if(defined $src && defined $dst ){ + my $s= $self->object_get_attribute("$src","NAME"); + my $d= $self->object_get_attribute("$dst","NAME"); + $table->attach (def_label("Select path between $s to $d" ),$col,$col+10,$row,$row+1,'fill','shrink',2,2); + add_info($info,"get list of all paths between $s to $d \n") if (defined $info); + $row=1; + my ($ref1,$ref2)= ($path_select eq "all-paths") ? get_all_paths_between_two_endps($self,$src, $dst): + get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,\@acyclic_turns); + my @paths = @{$ref1}; + my @ports= @{$ref2}; + my $n=0; + my $select = $self->object_get_attribute('Route',"${src}::$dst"); + foreach my $p (@paths){ + my $scal; + my $selp; + my $path_num=$n; + my $path=$p; + foreach my $q ( @{$p}){ + my $inst=$self->object_get_attribute("$q",'NAME'); + $scal= (defined $scal)? $scal."->$inst" : $inst; + } + foreach my $q ( @{$select}){ + my $inst=$self->object_get_attribute("$q",'NAME'); + $selp= (defined $selp)? $selp."->$inst" : $inst; + } + my $check= gen_checkbutton(); + #print "if($select eq $path)"; + if(defined $select && defined $scal && defined $selp) {if($selp eq $scal) {$check->set_active(TRUE);}} + else {$check->set_active(FALSE);} + $check-> signal_connect("toggled" => sub{ + if($check->get_active()) { + $self->object_add_attribute('Route',"${src}::$dst",$path); + } + else { + $self->object_add_attribute('Route',"${src}::$dst",undef); + } + set_gui_status($self,"ref",1); + }); + my $label =gen_label_in_left("$scal"); + $table->attach ($check , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col++; + $table->attach ($label , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++;$col=0; + $n++; + } + } + return add_widget_to_scrolled_win($table); } - - - ########## -# save +# save ########## sub save_network { - my ($self)=@_; - # read topology name - my $name=$self->object_get_attribute('save_as'); - #print $name; - my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; - if ($s == 0){ - message_dialog("Please set the topology name!"); - return 0; - } - # Write object file - my $fname = "$name.NWM"; - open(FILE, ">lib/netwmaker/$fname") || die "Can not open: $!"; - print FILE perl_file_header("$fname"); - print FILE Data::Dumper->Dump([\%$self],["nwmaker"]); - close(FILE) || die "Error closing file: $!"; - message_dialog("Current network maker state is saved as lib/netwmaker/$fname!"); - return 1; + my ($self)=@_; + # read topology name + my $name=$self->object_get_attribute('save_as'); + #print $name; + my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; + if ($s == 0){ + message_dialog("Please set the topology name!"); + return 0; + } + # Write object file + my $fname = "$name.NWM"; + open(FILE, ">lib/netwmaker/$fname") || die "Can not open: $!"; + print FILE perl_file_header("$fname"); + print FILE Data::Dumper->Dump([\%$self],["nwmaker"]); + close(FILE) || die "Error closing file: $!"; + message_dialog("Current network maker state is saved as lib/netwmaker/$fname!"); + return 1; } sub get_all_endp_ids{ - my $self=shift; - my %e= $self->object_get_attribute("E"); - my @list = sort keys %e; - return @list; - + my $self=shift; + my %e= $self->object_get_attribute("E"); + my @list = sort keys %e; + return @list; } - - - ############# # load ############# - sub load_net_maker{ my ($self,$info)=@_; my $file; - my $dialog = gen_file_dialog (undef, 'NWM'); - - + my $dialog = gen_file_dialog (undef, 'NWM'); my $dir = Cwd::getcwd(); $dialog->set_current_folder ("$dir/lib/netwmaker") ; - if ( "ok" eq $dialog->run ) { $file = $dialog->get_filename; my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); if($suffix eq '.NWM'){ my ($pp,$r,$err) = regen_object($file ); - if ($r){ + if ($r){ add_info($info,"**Error: cannot open $file file: $err\n"); - $dialog->destroy; + $dialog->destroy; return; - } - - + } clone_obj($self,$pp); - - - } - } - $dialog->destroy; - set_gui_status($self,"ref",1) + } + } + $dialog->destroy; + set_gui_status($self,"ref",1) } - - - - - - sub get_all_paths_between_two_endps{ - my ($self,$src, $dst)=@_; - my @proceed_nodes; - my @head_nodes; - - my $offset = $self->object_get_attribute('routing_auto','OFFSET'); - my $max_len = $self->object_get_attribute('routing_auto','MAX_LENGTH'); - - push (@head_nodes,$src); - push (@proceed_nodes,$src); - - my @paths; - my @ports; - my @paths_to_dst; - my @ports_to_dst; - - my @first_path=($src); - my @first_port=(0); - $paths[0]=\@first_path; - $ports[0]=\@first_port; - - # select one path - my $n=0; - my $min_dist=1000000; - do{ - my @current_path= @{$paths[$n]}; - my @current_port= @{$ports[$n]}; - # get head node - my $head_node = $current_path[-1]; - if(defined $head_node){ - # get connected nodes for all ports - #print "hn=$head_node\n"; - my $pnum = $self->object_get_attribute($head_node,'PNUM'); - - for (my $i=0;$i<$pnum; $i++){ - my @new_path=@current_path; - my @new_ports=@current_port; - my $src_port = "Port[${i}]"; - my $connect = $self->{$head_node}{'PCONNECT'}{$src_port}; - if(defined $connect){ - my ($node,$pnode)=split(/\s*,\s*/,$connect); - #add connected nodes to head_nodes if they are not in path before - if(!defined get_scolar_pos($node,@new_path)){ - my $size=scalar @new_path; - #if ($min_dist > $size){ - if( ($min_dist+$offset) > $size && $max_len>=$size){ - - - push (@new_path,$node); - push (@new_ports,$pnode); - push (@paths,\@new_path); - push (@ports,\@new_ports); - if($node eq $dst){ - push(@paths_to_dst,\@new_path); - push(@ports_to_dst,\@new_ports); - $min_dist=$size+1 if ($min_dist > $size); - } - } - } #if - } - }#for - } - $n++; - }while( defined $paths[$n]); - - #print "\@paths_to_dst". Dumper(@paths_to_dst). "\n \@ports_to_dst". Dumper(@ports_to_dst) . "\n" ; - - return (\@paths_to_dst,\@ports_to_dst); - + my ($self,$src, $dst)=@_; + my @proceed_nodes; + my @head_nodes; + my $offset = $self->object_get_attribute('routing_auto','OFFSET'); + my $max_len = $self->object_get_attribute('routing_auto','MAX_LENGTH'); + push (@head_nodes,$src); + push (@proceed_nodes,$src); + my @paths; + my @ports; + my @paths_to_dst; + my @ports_to_dst; + my @first_path=($src); + my @first_port=(0); + $paths[0]=\@first_path; + $ports[0]=\@first_port; + # select one path + my $n=0; + my $min_dist=1000000; + do{ + my @current_path= @{$paths[$n]}; + my @current_port= @{$ports[$n]}; + # get head node + my $head_node = $current_path[-1]; + if(defined $head_node){ + # get connected nodes for all ports + #print "hn=$head_node\n"; + my $pnum = $self->object_get_attribute($head_node,'PNUM'); + for (my $i=0;$i<$pnum; $i++){ + my @new_path=@current_path; + my @new_ports=@current_port; + my $src_port = "Port[${i}]"; + my $connect = $self->{$head_node}{'PCONNECT'}{$src_port}; + if(defined $connect){ + my ($node,$pnode)=split(/\s*,\s*/,$connect); + #add connected nodes to head_nodes if they are not in path before + if(!defined get_scolar_pos($node,@new_path)){ + my $size=scalar @new_path; + #if ($min_dist > $size){ + if( ($min_dist+$offset) > $size && $max_len>=$size){ + push (@new_path,$node); + push (@new_ports,$pnode); + push (@paths,\@new_path); + push (@ports,\@new_ports); + if($node eq $dst){ + push(@paths_to_dst,\@new_path); + push(@ports_to_dst,\@new_ports); + $min_dist=$size+1 if ($min_dist > $size); + } + } + } #if + } + }#for + } + $n++; + }while( defined $paths[$n]); + #print "\@paths_to_dst". Dumper(@paths_to_dst). "\n \@ports_to_dst". Dumper(@ports_to_dst) . "\n" ; + return (\@paths_to_dst,\@ports_to_dst); } sub get_path_from_turns { - my ($self,$ref)=@_; - my @new_turn = @{$ref} if(defined $ref); - my @path_nodes; - my @path_ports; - my $st2; - foreach my $code (@new_turn){ - my $pn2 = $code & 0xF; - $code >>=4; - my $rn2 = $code & 0xFFF; - $code >>=12; - my $pn1 =$code & 0xF; - $code >>=4; - my $rn1=$code; - my $st1 = ($pn1==1)? "ENDP_${rn1}" : "ROUTER${pn1}_${rn1}"; - $st2 = ($pn2==1)? "ENDP_${rn2}" : "ROUTER${pn2}_${rn2}"; - push(@path_nodes,$st1); - } - push(@path_nodes,$st2); - - @path_ports=(0); - for (my $i=0; $i>=4; + my $rn2 = $code & 0xFFF; + $code >>=12; + my $pn1 =$code & 0xF; + $code >>=4; + my $rn1=$code; + my $st1 = ($pn1==1)? "ENDP_${rn1}" : "ROUTER${pn1}_${rn1}"; + $st2 = ($pn2==1)? "ENDP_${rn2}" : "ROUTER${pn2}_${rn2}"; + push(@path_nodes,$st1); + } + push(@path_nodes,$st2); + @path_ports=(0); + for (my $i=0; $iobject_get_attribute('routing_auto','OFFSET'); - my $max_len = $self->object_get_attribute('routing_auto','MAX_LENGTH'); - - my @paths_to_dst; - my @ports_to_dst; - - my %graph; - - foreach my $str (@accyclic_turn){ - my ($s1,$s2) = split /\s/, $str; - push(@{$graph{$s1}},$s2); - } - - my $start_turns; - my $ended_turns; - my $src_port = "Port[0]"; - my $connect = $self->{$src}{'PCONNECT'}{$src_port}; - if(defined $connect){ - my ($node,$pnode)=split(/\s*,\s*/,$connect); - $start_turns = get_turn_code("${src}::${node}"); - } - - $connect = $self->{$dst}{'PCONNECT'}{$src_port}; - if(defined $connect){ - my ($node,$pnode)=split(/\s*,\s*/,$connect); - $ended_turns = get_turn_code("${node}::${dst}"); - } - - push (@head_turns,$start_turns); + my ($self,$src, $dst,$ref)=@_; + my @proceed_turns; + my @head_turns; + my @accyclic_turn= @{$ref}; + my $offset = $self->object_get_attribute('routing_auto','OFFSET'); + my $max_len = $self->object_get_attribute('routing_auto','MAX_LENGTH'); + my @paths_to_dst; + my @ports_to_dst; + my %graph; + foreach my $str (@accyclic_turn){ + my ($s1,$s2) = split /\s/, $str; + push(@{$graph{$s1}},$s2); + } + my $start_turns; + my $ended_turns; + my $src_port = "Port[0]"; + my $connect = $self->{$src}{'PCONNECT'}{$src_port}; + if(defined $connect){ + my ($node,$pnode)=split(/\s*,\s*/,$connect); + $start_turns = get_turn_code("${src}::${node}"); + } + $connect = $self->{$dst}{'PCONNECT'}{$src_port}; + if(defined $connect){ + my ($node,$pnode)=split(/\s*,\s*/,$connect); + $ended_turns = get_turn_code("${node}::${dst}"); + } + push (@head_turns,$start_turns); push (@proceed_turns,$start_turns); - - - - - - my @turns; - my @ports; - my @turns_to_dst; - my @first_turn=($start_turns); - - $turns[0]=\@first_turn; - - - # select one path - my $n=0; - my $min_dist=1000000; - do{ - my @current_turn= @{$turns[$n]}; - # get head node - my $head_turn = $current_turn[-1]; - if(defined $head_turn){ - #get all turns - my @all_fwd_turns = @{$graph{$head_turn}} if (defined $graph{$head_turn}); - - foreach my $fwd_turn (@all_fwd_turns){ - my @new_turn=@current_turn; - #add new turn to head_turns if they are not in turns before - if(!defined get_scolar_pos($fwd_turn,@new_turn)){ - my $size=scalar @new_turn; - #if ($min_dist > $size){ - if( ($min_dist+$offset) > $size && $max_len>=$size){ - push (@new_turn,$fwd_turn); - push (@turns,\@new_turn); - if($fwd_turn eq $ended_turns){ - push(@turns_to_dst,\@new_turn); - my ($path_ref,$port_ref) = get_path_from_turns($self,\@new_turn); - push(@paths_to_dst,$path_ref); - push(@ports_to_dst,$port_ref); - $min_dist=$size+1 if ($min_dist > $size); - } #if - - }#if - }#if - }#foreach - }#if - $n++; - }while( defined $turns[$n]); - - - - #print "\@paths_to_dst". Dumper(@paths_to_dst). "\n \@ports_to_dst". Dumper(@ports_to_dst) . "\n" ; - - - return (\@paths_to_dst,\@ports_to_dst); - + my @turns; + my @ports; + my @turns_to_dst; + my @first_turn=($start_turns); + $turns[0]=\@first_turn; + # select one path + my $n=0; + my $min_dist=1000000; + do{ + my @current_turn= @{$turns[$n]}; + # get head node + my $head_turn = $current_turn[-1]; + if(defined $head_turn){ + #get all turns + my @all_fwd_turns = @{$graph{$head_turn}} if (defined $graph{$head_turn}); + foreach my $fwd_turn (@all_fwd_turns){ + my @new_turn=@current_turn; + #add new turn to head_turns if they are not in turns before + if(!defined get_scolar_pos($fwd_turn,@new_turn)){ + my $size=scalar @new_turn; + #if ($min_dist > $size){ + if( ($min_dist+$offset) > $size && $max_len>=$size){ + push (@new_turn,$fwd_turn); + push (@turns,\@new_turn); + if($fwd_turn eq $ended_turns){ + push(@turns_to_dst,\@new_turn); + my ($path_ref,$port_ref) = get_path_from_turns($self,\@new_turn); + push(@paths_to_dst,$path_ref); + push(@ports_to_dst,$port_ref); + $min_dist=$size+1 if ($min_dist > $size); + } #if + }#if + }#if + }#foreach + }#if + $n++; + }while( defined $turns[$n]); + #print "\@paths_to_dst". Dumper(@paths_to_dst). "\n \@ports_to_dst". Dumper(@ports_to_dst) . "\n" ; + return (\@paths_to_dst,\@ports_to_dst); } - - - sub get_turn_code { - my $turn =shift; - my ($pn1,$rn1,$pn2,$rn2)= sscanf( "ROUTER%u_%u::ROUTER%u_%u",$turn); - if(defined $rn1){ - return ( ($rn1 << 20)+ ($pn1 << 16) + ($rn2 << 4) + $pn2); - } - ($rn1,$pn2,$rn2)= sscanf( "ENDP_%u::ROUTER%u_%u",$turn); - if(defined $rn1){ - return ( ($rn1 << 20)+ (1 << 16) + ($rn2 << 4) + $pn2); - } - ($pn1,$rn1,$rn2)= sscanf( "ROUTER%u_%u::ENDP_%u",$turn); - return ( ($rn1 << 20)+ ($pn1 << 16) + ($rn2 << 4) + 1); + my $turn =shift; + my ($pn1,$rn1,$pn2,$rn2)= sscanf( "ROUTER%u_%u::ROUTER%u_%u",$turn); + if(defined $rn1){ + return ( ($rn1 << 20)+ ($pn1 << 16) + ($rn2 << 4) + $pn2); + } + ($rn1,$pn2,$rn2)= sscanf( "ENDP_%u::ROUTER%u_%u",$turn); + if(defined $rn1){ + return ( ($rn1 << 20)+ (1 << 16) + ($rn2 << 4) + $pn2); + } + ($pn1,$rn1,$rn2)= sscanf( "ROUTER%u_%u::ENDP_%u",$turn); + return ( ($rn1 << 20)+ ($pn1 << 16) + ($rn2 << 4) + 1); } sub get_turn_str { - my $code =shift; - my $pn2 = $code & 0xF; - $code >>=4; - my $rn2 = $code & 0xFFF; - $code >>=12; - my $pn1 =$code & 0xF; - $code >>=4; - my $rn1=$code; - my $st1 = ($pn1==1)? "ENDP_${rn1}" : "ROUTER${pn1}_${rn1}"; - my $st2 = ($pn2==1)? "ENDP_${rn2}" : "ROUTER${pn2}_${rn2}"; - - return "${st1}::${st2}"; + my $code =shift; + my $pn2 = $code & 0xF; + $code >>=4; + my $rn2 = $code & 0xFFF; + $code >>=12; + my $pn1 =$code & 0xF; + $code >>=4; + my $rn1=$code; + my $st1 = ($pn1==1)? "ENDP_${rn1}" : "ROUTER${pn1}_${rn1}"; + my $st2 = ($pn2==1)? "ENDP_${rn2}" : "ROUTER${pn2}_${rn2}"; + return "${st1}::${st2}"; } sub get_turn_involved_routrs{ - my ($s1,$s2,$info)=@_; - my ($r1,$ra2) = split /::/, $s1; - my ($rb2,$r3) = split /::/, $s2; - add_colored_info($info,"Error in turn format. $s1 -> $s2 : $ra2 should be equal with $rb2 ",'red') if($ra2 ne $rb2); - return ($r1,$ra2,$r3); + my ($s1,$s2,$info)=@_; + my ($r1,$ra2) = split /::/, $s1; + my ($rb2,$r3) = split /::/, $s2; + add_colored_info($info,"Error in turn format. $s1 -> $s2 : $ra2 should be equal with $rb2 ",'red') if($ra2 ne $rb2); + return ($r1,$ra2,$r3); } sub get_path_edges_graph_file{ - my ($ref1,$ref2) = @_; - my @a_nodes = @{$ref1}; - my %graph = %{$ref2}; - - my $old_r; - foreach my $r (@a_nodes){ - - if(defined $old_r){ - my $str1 = "$old_r $r"; - my $n1 = get_turn_code($old_r); - my $n2 = get_turn_code($r); - my $str2 = "$n1 $n2"; - $graph{$str2}=$str1; - } - $old_r=$r; - } - return %graph; -} - - - + my ($ref1,$ref2) = @_; + my @a_nodes = @{$ref1}; + my %graph = %{$ref2}; + my $old_r; + foreach my $r (@a_nodes){ + if(defined $old_r){ + my $str1 = "$old_r $r"; + my $n1 = get_turn_code($old_r); + my $n2 = get_turn_code($r); + my $str2 = "$n1 $n2"; + $graph{$str2}=$str1; + } + $old_r=$r; + } + return %graph; +} sub get_forbiden_turns_old { -#sub gen_aciclic_turn_graph { - my ($self,$info)=@_; - my @forbiden_turn; - add_info($info,"Calculate forbidden turns to avoid deadlock \n"); - #step 1: get the list of all minimal paths between all source and destination pairs - my $graph=''; - my $graph_coded=''; - my @all_endpoints=get_list_of_all_endpoints($self); - - my %edge_graph; - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - if($src ne $dst){ - my ($paths_to_dst,$ports_to_dst) = get_all_paths_between_two_endps($self,$src, $dst); - foreach my $path (@{$paths_to_dst}) { - if (defined $path){ - #path counting - my @a_nodes= get_adjacent_node_in_a_path($path);#get_adjacent_router_in_a_path($path); - print "@a_nodes = \@a_nodes \n"; - %edge_graph = get_path_edges_graph_file (\@a_nodes,\%edge_graph); - #$graph =$graph. $str1; - #$graph_coded = $graph_coded . $str2; - }#defined path - }#foreach - }#if - }#froeach - - }#froeach - - foreach my $p (sort keys %edge_graph){ - $graph_coded .="$p\n"; - $graph .= "$edge_graph{$p}\n"; - } - - my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; - save_file ("$tmp_dir/paths_graph.edges",$graph); - save_file ("$tmp_dir/paths_graph_coded.edges",$graph_coded); - - - #remove old files - my @files = File::Find::Rule->file() +#sub gen_aciclic_turn_graph { + my ($self,$info)=@_; + my @forbiden_turn; + add_info($info,"Calculate forbidden turns to avoid deadlock \n"); + #step 1: get the list of all minimal paths between all source and destination pairs + my $graph=''; + my $graph_coded=''; + my @all_endpoints=get_list_of_all_endpoints($self); + my %edge_graph; + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + if($src ne $dst){ + my ($paths_to_dst,$ports_to_dst) = get_all_paths_between_two_endps($self,$src, $dst); + foreach my $path (@{$paths_to_dst}) { + if (defined $path){ + #path counting + my @a_nodes= get_adjacent_node_in_a_path($path);#get_adjacent_router_in_a_path($path); + print "@a_nodes = \@a_nodes \n"; + %edge_graph = get_path_edges_graph_file (\@a_nodes,\%edge_graph); + #$graph =$graph. $str1; + #$graph_coded = $graph_coded . $str2; + }#defined path + }#foreach + }#if + }#froeach + }#froeach + foreach my $p (sort keys %edge_graph){ + $graph_coded .="$p\n"; + $graph .= "$edge_graph{$p}\n"; + } + my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; + save_file ("$tmp_dir/paths_graph.edges",$graph); + save_file ("$tmp_dir/paths_graph_coded.edges",$graph_coded); + #remove old files + my @files = File::Find::Rule->file() ->name( 'paths_graph_coded_removed*.edges') - ->in( "$tmp_dir" ); - foreach my $f (@files){ - unlink $f if (-f "$f"); - } - - # run remove_cycle_edges_by_dfs on coded graph - my $remover_dire = get_project_dir()."/mpsoc/remove_cycle/"; - my $cmd = "cd $remover_dire; - python break_cycles.py -g $tmp_dir/paths_graph_coded.edges; - python remove_cycle_edges_by_dfs.py -g $tmp_dir/paths_graph_coded.edges; - python remove_cycle_edges_by_minimum_feedback_arc_set_greedy.py -g $tmp_dir/paths_graph_coded.edges"; - #sort paths_graph_coded.edges | uniq > newfile.db - - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - add_colored_info($info,"$stderr\n",'red'); - }else { - add_info($info,"$stdout\n"); - } - # find the files with the list edges removal - @files = File::Find::Rule->file() - ->name( 'paths_graph_coded_removed*.edges') - ->in( "$tmp_dir" ); - - - my $line_num; - my $out; - foreach my $f (@files){ - my $n =count_file_line_num ($f); - $line_num = $n if(! defined $line_num); - if($n <= $line_num){ - $out = $f; - $line_num=$n; - } - } - - - # check if the output file is generated - if (-f $out ){ - add_colored_info($info,"$out file has been selected as it has the minimum number of edge removal of $line_num \n",'blue'); - - } else { - add_colored_info($info,"could not find a paths_graph_coded_removed*.edges file. Please make sure $cmd has been run successfully\n",'red'); - return; - - } - - - - - my $r; - open my $fh, "<", $out or $r = "$!\n"; + ->in( "$tmp_dir" ); + foreach my $f (@files){ + unlink $f if (-f "$f"); + } + # run remove_cycle_edges_by_dfs on coded graph + my $remover_dire = get_project_dir()."/mpsoc/remove_cycle/"; + my $cmd = "cd $remover_dire; + python break_cycles.py -g $tmp_dir/paths_graph_coded.edges; + python remove_cycle_edges_by_dfs.py -g $tmp_dir/paths_graph_coded.edges; + python remove_cycle_edges_by_minimum_feedback_arc_set_greedy.py -g $tmp_dir/paths_graph_coded.edges"; + #sort paths_graph_coded.edges | uniq > newfile.db + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + add_colored_info($info,"$stderr\n",'red'); + }else { + add_info($info,"$stdout\n"); + } + # find the files with the list edges removal + @files = File::Find::Rule->file() + ->name( 'paths_graph_coded_removed*.edges') + ->in( "$tmp_dir" ); + my $line_num; + my $out; + foreach my $f (@files){ + my $n =count_file_line_num ($f); + $line_num = $n if(! defined $line_num); + if($n <= $line_num){ + $out = $f; + $line_num=$n; + } + } + # check if the output file is generated + if (-f $out ){ + add_colored_info($info,"$out file has been selected as it has the minimum number of edge removal of $line_num \n",'blue'); + } else { + add_colored_info($info,"could not find a paths_graph_coded_removed*.edges file. Please make sure $cmd has been run successfully\n",'red'); + return; + } + my $r; + open my $fh, "<", $out or $r = "$!\n"; if(defined $r) { - add_colored_info($info,"Could not open $out: $r",'red'); - return; - } - + add_colored_info($info,"Could not open $out: $r",'red'); + return; + } add_colored_info($info,"List of forbidden turns: \n",'blue'); - - while (my $line = <$fh>) { - chomp $line; - $line=~ s/^\s+|\s+$//g; - my ($s1,$s2) = split /\s/, $line; - $s1 = get_turn_str($s1); - $s2 = get_turn_str($s2); - my @turn = get_turn_involved_routrs($s1,$s2); - my $str = get_path_instance_string($self,\@turn); - my $string=join('->',@turn); - push (@forbiden_turn, $string); - add_info($info,"$str\n"); - - } - return @forbiden_turn; - + while (my $line = <$fh>) { + chomp $line; + $line=~ s/^\s+|\s+$//g; + my ($s1,$s2) = split /\s/, $line; + $s1 = get_turn_str($s1); + $s2 = get_turn_str($s2); + my @turn = get_turn_involved_routrs($s1,$s2); + my $str = get_path_instance_string($self,\@turn); + my $string=join('->',@turn); + push (@forbiden_turn, $string); + add_info($info,"$str\n"); + } + return @forbiden_turn; } - sub gen_turn_graph{ - my $self=shift; - my %edge_graph; - my @all_nodes=get_list_of_all_nodes($self); - foreach my $node1 (@all_nodes ){ - my $pnum1=$self->object_get_attribute("$node1",'PNUM'); - for (my $i=0;$i<$pnum1; $i++){ - my $port1 = "Port[${i}]"; - my $connect1 = $self->{$node1}{'PCONNECT'}{$port1}; - if (defined $connect1) { - my ($node2,$Rport2)=split(/\s*,\s*/,$connect1); - my $pnum2=$self->object_get_attribute("$node2",'PNUM'); - for (my $j=0;$j<$pnum2; $j++){ - my $port2 = "Port[${j}]"; - my $connect2 = $self->{$node2}{'PCONNECT'}{$port2}; - if (defined $connect2) { - my ($node3,$Rport3)=split(/\s*,\s*/,$connect2); - if($node1 ne $node3){ - my @a_nodes= ("${node1}::${node2}","${node2}::${node3}"); - %edge_graph = get_path_edges_graph_file (\@a_nodes,\%edge_graph); - } - - }#if - }#for - }#if - }#for - } - return %edge_graph; + my $self=shift; + my %edge_graph; + my @all_nodes=get_list_of_all_nodes($self); + foreach my $node1 (@all_nodes ){ + my $pnum1=$self->object_get_attribute("$node1",'PNUM'); + for (my $i=0;$i<$pnum1; $i++){ + my $port1 = "Port[${i}]"; + my $connect1 = $self->{$node1}{'PCONNECT'}{$port1}; + if (defined $connect1) { + my ($node2,$Rport2)=split(/\s*,\s*/,$connect1); + my $pnum2=$self->object_get_attribute("$node2",'PNUM'); + for (my $j=0;$j<$pnum2; $j++){ + my $port2 = "Port[${j}]"; + my $connect2 = $self->{$node2}{'PCONNECT'}{$port2}; + if (defined $connect2) { + my ($node3,$Rport3)=split(/\s*,\s*/,$connect2); + if($node1 ne $node3){ + my @a_nodes= ("${node1}::${node2}","${node2}::${node3}"); + %edge_graph = get_path_edges_graph_file (\@a_nodes,\%edge_graph); + } + }#if + }#for + }#if + }#for + } + return %edge_graph; } sub gen_aciclic_turn_graph { - - my ($self,$info)=@_; - - #my @forbiden_turn; - - add_info($info,"Generate an acyclic turn graph to avoid deadlock \n"); - #step 1: get the list of turn in topology. A turn is a path that include three nodes. - my $graph=''; - my $graph_coded=''; - - my %edge_graph =gen_turn_graph($self); - - - foreach my $p (sort keys %edge_graph){ - $graph_coded .="$p\n"; - $graph .= "$edge_graph{$p}\n"; - } - - my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; - save_file ("$tmp_dir/paths_graph.edges",$graph); - save_file ("$tmp_dir/paths_graph_coded.edges",$graph_coded); - - - #remove old files - my @files = File::Find::Rule->file() - ->name( 'paths_graph_coded_removed*.edges') - ->in( "$tmp_dir" ); - foreach my $f (@files){ - unlink $f if (-f "$f"); - } - - # run remove_cycle_edges_by_dfs on coded graph - my $remover_dire = get_project_dir()."/mpsoc/remove_cycle/"; - my $cmd = "cd $remover_dire; - python break_cycles.py -g $tmp_dir/paths_graph_coded.edges; - python remove_cycle_edges_by_dfs.py -g $tmp_dir/paths_graph_coded.edges; - python remove_cycle_edges_by_minimum_feedback_arc_set_greedy.py -g $tmp_dir/paths_graph_coded.edges"; - #sort paths_graph_coded.edges | uniq > newfile.db - - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - add_colored_info($info,"$stderr\n",'red'); - }else { - add_info($info,"$stdout\n"); - } - # find the files with the list edges removal - @files = File::Find::Rule->file() - ->name( 'paths_graph_coded_removed*.edges') - ->in( "$tmp_dir" ); - my $line_num; - my $out; - my %all_outs; - foreach my $f (@files){ - - my $n =count_file_line_num ($f); - $all_outs{$f}=$n; - - } - - my @graph_array=sort keys %edge_graph; - my @acyclic_turns; - my @removed_edge; - my $result=0; - - my %algorithms; - - foreach my $file (sort {$all_outs{$a} <=> $all_outs{$b}} keys %all_outs) { - $line_num = $all_outs{$file}; - $out=$file; - add_info($info,"check if $file file $line_num edges removal results in a connected graph\n"); - - @removed_edge=(); - open(FILE,$file); - if (tell FILE ){ - add_colored_info($info,"Cannot open $file to read: $!\n",'red'); - return; - } - while (my $line = ) { - chomp($line); - $line=~ s/^\s+|\s+$//g; - push(@removed_edge,$line); - } - close FILE; - - @acyclic_turns = get_diff_array ( \@graph_array , \@removed_edge ); - - - - $result = check_diff_graph_be_connected ($self,\@acyclic_turns,$info); - if($result == 1){ - my $alg = capture_string_between ('paths_graph_coded_removed_by_',$file,".edges"); - $algorithms{$alg}=$line_num; - #save @acyclic_turns for this algorithm - open(F, ">$tmp_dir/$alg.alg") || die "Can not creat: $!"; - print F perl_file_header("$alg.alg"); - print F Data::Dumper->Dump([\@acyclic_turns],['turn']); - close(F ) || die "Error closing file: $!"; - } - - - } - - $self->object_add_attribute('routing_auto','acyclic_algorithms',\%algorithms); - - + my ($self,$info)=@_; + #my @forbiden_turn; + add_info($info,"Generate an acyclic turn graph to avoid deadlock \n"); + #step 1: get the list of turn in topology. A turn is a path that include three nodes. + my $graph=''; + my $graph_coded=''; + my %edge_graph =gen_turn_graph($self); + foreach my $p (sort keys %edge_graph){ + $graph_coded .="$p\n"; + $graph .= "$edge_graph{$p}\n"; + } + my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; + save_file ("$tmp_dir/paths_graph.edges",$graph); + save_file ("$tmp_dir/paths_graph_coded.edges",$graph_coded); + #remove old files + my @files = File::Find::Rule->file() + ->name( 'paths_graph_coded_removed*.edges') + ->in( "$tmp_dir" ); + foreach my $f (@files){ + unlink $f if (-f "$f"); + } + # run remove_cycle_edges_by_dfs on coded graph + my $remover_dire = get_project_dir()."/mpsoc/remove_cycle/"; + my $cmd = "cd $remover_dire; + python break_cycles.py -g $tmp_dir/paths_graph_coded.edges; + python remove_cycle_edges_by_dfs.py -g $tmp_dir/paths_graph_coded.edges; + python remove_cycle_edges_by_minimum_feedback_arc_set_greedy.py -g $tmp_dir/paths_graph_coded.edges"; + #sort paths_graph_coded.edges | uniq > newfile.db + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + add_colored_info($info,"$stderr\n",'red'); + }else { + add_info($info,"$stdout\n"); + } + # find the files with the list edges removal + @files = File::Find::Rule->file() + ->name( 'paths_graph_coded_removed*.edges') + ->in( "$tmp_dir" ); + my $line_num; + my $out; + my %all_outs; + foreach my $f (@files){ + my $n =count_file_line_num ($f); + $all_outs{$f}=$n; + } + my @graph_array=sort keys %edge_graph; + my @acyclic_turns; + my @removed_edge; + my $result=0; + my %algorithms; + foreach my $file (sort {$all_outs{$a} <=> $all_outs{$b}} keys %all_outs) { + $line_num = $all_outs{$file}; + $out=$file; + add_info($info,"check if $file file $line_num edges removal results in a connected graph\n"); + @removed_edge=(); + open(FILE,$file); + if (tell FILE ){ + add_colored_info($info,"Cannot open $file to read: $!\n",'red'); + return; + } + while (my $line = ) { + chomp($line); + $line=~ s/^\s+|\s+$//g; + push(@removed_edge,$line); + } + close FILE; + @acyclic_turns = get_diff_array ( \@graph_array , \@removed_edge ); + $result = check_diff_graph_be_connected ($self,\@acyclic_turns,$info); + if($result == 1){ + my $alg = capture_string_between ('paths_graph_coded_removed_by_',$file,".edges"); + $algorithms{$alg}=$line_num; + #save @acyclic_turns for this algorithm + open(F, ">$tmp_dir/$alg.alg") || die "Can not creat: $!"; + print F perl_file_header("$alg.alg"); + print F Data::Dumper->Dump([\@acyclic_turns],['turn']); + close(F ) || die "Error closing file: $!"; + } + } + $self->object_add_attribute('routing_auto','acyclic_algorithms',\%algorithms); if (scalar (keys %algorithms) == 0){ - add_colored_info($info,"Unable to find any directed acyclic graph for routing\n",'red'); - return; - } - - return; - #add_colored_info($info,"$out file has been selected as it has the minimum number of edge removal of $line_num and its connected\n",'blue'); - - - + add_colored_info($info,"Unable to find any directed acyclic graph for routing\n",'red'); + return; + } + return; + #add_colored_info($info,"$out file has been selected as it has the minimum number of edge removal of $line_num and its connected\n",'blue'); #add_colored_info($info,"List of forbidden turns: \n",'blue'); - - foreach my $line (@removed_edge) { - chomp $line; - my ($s1,$s2) = split /\s/, $line; - $s1 = get_turn_str($s1); - $s2 = get_turn_str($s2); - my @turn = get_turn_involved_routrs($s1,$s2); - my $str = get_path_instance_string($self,\@turn); - my $string=join('->',@turn); - # push (@forbiden_turn, $string); - add_info($info,"$str\n"); - - } - - # $self->object_add_attribute('routing_auto','acyclic_turns',\@acyclic_turns); - -# return @forbiden_turn; - + foreach my $line (@removed_edge) { + chomp $line; + my ($s1,$s2) = split /\s/, $line; + $s1 = get_turn_str($s1); + $s2 = get_turn_str($s2); + my @turn = get_turn_involved_routrs($s1,$s2); + my $str = get_path_instance_string($self,\@turn); + my $string=join('->',@turn); + # push (@forbiden_turn, $string); + add_info($info,"$str\n"); + } + # $self->object_add_attribute('routing_auto','acyclic_turns',\@acyclic_turns); + # return @forbiden_turn; } - - sub check_diff_graph_be_connected { - my ($self,$ref,$info)=@_; - my @diff = @{$ref}; - my %all_turns; - my %graph; - - foreach my $str (@diff){ - my ($s1,$s2) = split /\s/, $str; - $all_turns{$s1}=1; - $all_turns{$s2}=1; - push(@{$graph{$s1}},$s2); - - } - - my @all_endpoints=get_list_of_all_endpoints($self); - my @start_turns; - my @ended_turns; - foreach my $endp (@all_endpoints){ - - my $src_port = "Port[0]"; - my $connect = $self->{$endp}{'PCONNECT'}{$src_port}; - if(defined $connect){ - my ($node,$pnode)=split(/\s*,\s*/,$connect); - push (@start_turns, get_turn_code("${endp}::${node}")); - push (@ended_turns, get_turn_code("${node}::${endp}")); - } - } - - my $k=0; - foreach my $s (@start_turns){# we should see all @ended_turns - - my @seen_turns=($s,$ended_turns[$k]);# put connect to itself connection as seen node. - $k++; - my @next_turns =@{$graph{$s}}; - - while (scalar @next_turns>0){ - - - #print "\@next_nodes = @next_nodes\n"; - #print "\@seen_nodes = @seen_nodes\n"; - my $n = pop (@next_turns); - #print "\$n = $n \n"; - my @nn; - @nn = @{$graph{$n}} if (defined $graph{$n}); - #print "\@nn = @nn \n"; - push (@seen_turns, $n); - @diff = get_diff_array ( \@nn , \@seen_turns ); - #print "\@diff = @diff \n"; - push (@next_turns,@diff); - - } - - my @sep = get_diff_array (\@ended_turns,\@seen_turns); - - if( scalar @sep > 0) { - my $s1 = get_turn_str($s); - my ($a1,$a2) = split ('::',$s1); - my $n1=$self->object_get_attribute("$a1",'NAME'); - - $s1 = get_turn_str($sep[0]); - my($a3,$a4) = split ('::',$s1); - my $n2=$self->object_get_attribute("$a4",'NAME'); - - add_info($info,"\t $n1 is not connected to $n2. \n"); - return 0; - } - - - } - - - add_info($info,"\t All endpoints are connected in chanel dpenedency graph. \n"); - return 1; - -} - - - -sub get_path_instance_string { - my ($self,$path_ref)=@_; - my @path = @{$path_ref}; - my @path_inst; - foreach my $p (@path){ - push (@path_inst, $self->object_get_attribute("$p",'NAME')); - - } - my $string=join('->',@path_inst); - return $string; -} + my ($self,$ref,$info)=@_; + my @diff = @{$ref}; + my %all_turns; + my %graph; + foreach my $str (@diff){ + my ($s1,$s2) = split /\s/, $str; + $all_turns{$s1}=1; + $all_turns{$s2}=1; + push(@{$graph{$s1}},$s2); + } + my @all_endpoints=get_list_of_all_endpoints($self); + my @start_turns; + my @ended_turns; + foreach my $endp (@all_endpoints){ + my $src_port = "Port[0]"; + my $connect = $self->{$endp}{'PCONNECT'}{$src_port}; + if(defined $connect){ + my ($node,$pnode)=split(/\s*,\s*/,$connect); + push (@start_turns, get_turn_code("${endp}::${node}")); + push (@ended_turns, get_turn_code("${node}::${endp}")); + } + } + my $k=0; + foreach my $s (@start_turns){# we should see all @ended_turns + my @seen_turns=($s,$ended_turns[$k]);# put connect to itself connection as seen node. + $k++; + my @next_turns =@{$graph{$s}}; + while (scalar @next_turns>0){ + #print "\@next_nodes = @next_nodes\n"; + #print "\@seen_nodes = @seen_nodes\n"; + my $n = pop (@next_turns); + #print "\$n = $n \n"; + my @nn; + @nn = @{$graph{$n}} if (defined $graph{$n}); + #print "\@nn = @nn \n"; + push (@seen_turns, $n); + @diff = get_diff_array ( \@nn , \@seen_turns ); + #print "\@diff = @diff \n"; + push (@next_turns,@diff); + } + my @sep = get_diff_array (\@ended_turns,\@seen_turns); + if( scalar @sep > 0) { + my $s1 = get_turn_str($s); + my ($a1,$a2) = split ('::',$s1); + my $n1=$self->object_get_attribute("$a1",'NAME'); + $s1 = get_turn_str($sep[0]); + my($a3,$a4) = split ('::',$s1); + my $n2=$self->object_get_attribute("$a4",'NAME'); + add_info($info,"\t $n1 is not connected to $n2. \n"); + return 0; + } + } + add_info($info,"\t All endpoints are connected in chanel dpenedency graph. \n"); + return 1; +} +sub get_path_instance_string { + my ($self,$path_ref)=@_; + my @path = @{$path_ref}; + my @path_inst; + foreach my $p (@path){ + push (@path_inst, $self->object_get_attribute("$p",'NAME')); + } + my $string=join('->',@path_inst); + return $string; +} sub remove_cycle_paths { - my ($self,$info,$paths_ref, $fturn_ref)=@_; - my @free_paths; - my @paths= @{$paths_ref}; - my @fturns= @{$fturn_ref}; - my $remove; - - - - foreach my $path (@paths) { - my @p = @$path; - my $turn; - my $string=join('->',@p); - #print "$string\n"; - $remove=0; - foreach my $t (@fturns){ - if ($string =~ /$t-/){ - $remove=1; - $turn=$t; - last; - } - - } - push (@free_paths,$path) if($remove == 0); - if($remove == 1){ - my @ft = split /->/, $turn; - add_info($info,"path ".get_path_instance_string($self,$path)." is removed due to turn ".get_path_instance_string($self,\@ft)."\n") - } - } - return @free_paths; -} - - - - - - - + my ($self,$info,$paths_ref, $fturn_ref)=@_; + my @free_paths; + my @paths= @{$paths_ref}; + my @fturns= @{$fturn_ref}; + my $remove; + foreach my $path (@paths) { + my @p = @$path; + my $turn; + my $string=join('->',@p); + #print "$string\n"; + $remove=0; + foreach my $t (@fturns){ + if ($string =~ /$t-/){ + $remove=1; + $turn=$t; + last; + } + } + push (@free_paths,$path) if($remove == 0); + if($remove == 1){ + my @ft = split /->/, $turn; + add_info($info,"path ".get_path_instance_string($self,$path)." is removed due to turn ".get_path_instance_string($self,\@ft)."\n") + } + } + return @free_paths; +} sub auto_route { - my ($self,$info)=@_; - my %Psize; - my $alg = $self->object_get_attribute('routing_auto', 'CYCLE_FREE_ALG'); - my ($alg_name,$line) = split (/\s+--\s+/,$alg); - - if(!defined $line){ - add_colored_info($info,"No acyclic turn model is selected. click on Generate Cycle-free and make sure it runs successfully!\n",'red'); - return; - } - my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; - my $model_file = "$tmp_dir/$alg_name.alg"; - my ($pp,$r,$err) = regen_object($model_file); - if ($r){ - add_colored_info($info,"**Error: cannot open $model_file file: $err\n",'red'); - return; + my ($self,$info)=@_; + my %Psize; + my $alg = $self->object_get_attribute('routing_auto', 'CYCLE_FREE_ALG'); + my ($alg_name,$line) = split (/\s+--\s+/,$alg); + if(!defined $line){ + add_colored_info($info,"No acyclic turn model is selected. click on Generate Cycle-free and make sure it runs successfully!\n",'red'); + return; + } + my $tmp_dir = "$ENV{'PRONOC_WORK'}/tmp"; + my $model_file = "$tmp_dir/$alg_name.alg"; + my ($pp,$r,$err) = regen_object($model_file); + if ($r){ + add_colored_info($info,"**Error: cannot open $model_file file: $err\n",'red'); + return; } else { - add_info($info,"Use $alg_name algorithm for obtaing acyclic paths\n"); - } - - my @acyclic_turns = @{$pp}; - my %rusage = get_router_usage ($self,\@acyclic_turns); - - - #step 1: calculate all minimal paths between all source and destination pairs - add_info($info,"Calculate all paths between all source and destination pairs\n"); - my @all_endpoints=get_list_of_all_endpoints($self); - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - if($src ne $dst){ - my ($paths_to_dst,$ports_to_dst) = get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,\@acyclic_turns); - my @cyle_free_paths= @{$paths_to_dst} if (defined $paths_to_dst); - my $size = scalar @cyle_free_paths; - $Psize{"${src}::$dst"} = $size; - } - } - } - #step 2: Remove cyclic paths between all source and destination pairs - - - - - - - #step 3 sort source destination based on the number of paths - my @keys = sort { $Psize{$a} <=> $Psize{$b} } keys(%Psize); - for my $key ( @keys) { - my $size=$Psize{$key}; - #print "size = $size\n"; - next if(defined $self->object_get_attribute('Route',$key)); - - # print "($key)->($Psize{$key})\n"; + add_info($info,"Use $alg_name algorithm for obtaing acyclic paths\n"); + } + my @acyclic_turns = @{$pp}; + my %rusage = get_router_usage ($self,\@acyclic_turns); + #step 1: calculate all minimal paths between all source and destination pairs + add_info($info,"Calculate all paths between all source and destination pairs\n"); + my @all_endpoints=get_list_of_all_endpoints($self); + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + if($src ne $dst){ + my ($paths_to_dst,$ports_to_dst) = get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,\@acyclic_turns); + my @cyle_free_paths= @{$paths_to_dst} if (defined $paths_to_dst); + my $size = scalar @cyle_free_paths; + $Psize{"${src}::$dst"} = $size; + } + } + } + #step 2: Remove cyclic paths between all source and destination pairs + #step 3 sort source destination based on the number of paths + my @keys = sort { $Psize{$a} <=> $Psize{$b} } keys(%Psize); + for my $key ( @keys) { + my $size=$Psize{$key}; + #print "size = $size\n"; + next if(defined $self->object_get_attribute('Route',$key)); + # print "($key)->($Psize{$key})\n"; my ($src , $dst)=split ('::',$key); my ($paths_to_dst,$ports_to_dst) = get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,\@acyclic_turns); #my @cyle_free_paths=remove_cycle_paths($self,$info,$paths_to_dst, \@forbiden_turn); my @cyle_free_paths= @{$paths_to_dst} if (defined $paths_to_dst); my @sort_paths=sort_paths_based_on_router_usage($self,\@cyle_free_paths,\%rusage); - - # my @sort_paths=sort_paths_based_on_link_usage($self,\@cyle_free_paths); - - - + # my @sort_paths=sort_paths_based_on_link_usage($self,\@cyle_free_paths); my $path; my $n=0; foreach my $p (@sort_paths ){ - if(check_cyclick_loop($self,$p)==0){ - $path=$p; - #my @rrr=($p); - #remove_cycle_paths($self,$info,\@rrr, \@forbiden_turn); - - last; - } else { - print "***Error something goes wrong in acyclic turns model ****************************\n"; - } - $n++; + if(check_cyclick_loop($self,$p)==0){ + $path=$p; + #my @rrr=($p); + #remove_cycle_paths($self,$info,\@rrr, \@forbiden_turn); + last; + } else { + print "***Error something goes wrong in acyclic turns model ****************************\n"; + } + $n++; } if(!defined $path){ - #extract path from acyclic turn graph. This graph is connected so there must be atleast a path between each endpoint pairs there. however this path does not match the offset or size lentgh - - - set_gui_status($self,"ref",1); - add_colored_info($info,"Failed to find an acyclic routing paths for $key nodes!\n",'red'); - return FALSE ; - + #extract path from acyclic turn graph. This graph is connected so there must be atleast a path between each endpoint pairs there. however this path does not match the offset or size lentgh + set_gui_status($self,"ref",1); + add_colored_info($info,"Failed to find an acyclic routing paths for $key nodes!\n",'red'); + return FALSE ; } - $self->object_add_attribute('Route',$key,$path); - - } - - set_gui_status($self,"ref",1); - add_colored_info($info,"The routeing function table is generated successfully!\n",'blue'); - return TRUE; -} - + } + set_gui_status($self,"ref",1); + add_colored_info($info,"The routeing function table is generated successfully!\n",'blue'); + return TRUE; +} sub clean_route { - my ($self,$info)=@_; - - my @all_endpoints=get_list_of_all_endpoints($self); - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ + my ($self,$info)=@_; + my @all_endpoints=get_list_of_all_endpoints($self); + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ $self->object_add_attribute('Route',"${src}::$dst",undef); - - }} - - set_gui_status($self,"ref",1); - add_colored_info($info,"The Routing function table is cleared!\n",'blue'); - return TRUE; -} - - + }} + set_gui_status($self,"ref",1); + add_colored_info($info,"The Routing function table is cleared!\n",'blue'); + return TRUE; +} sub average{ my($data) = @_; if (not @$data) { - return 0; + return 0; } my $total = 0; foreach (@$data) { - $total += $_; + $total += $_; } my $average = $total / @$data; return $average; } + sub stdev{ my($data) = @_; if(@$data == 1){ @@ -2699,184 +2048,143 @@ sub stdev{ } sub clone_hash{ - my $ref=shift; - my %hash=%{$ref}; - my %copy; - foreach my $p (keys %hash){ - if (defined $hash{$p}){ $copy{$p} = $hash{$p};} - } - return %copy; + my $ref=shift; + my %hash=%{$ref}; + my %copy; + foreach my $p (keys %hash){ + if (defined $hash{$p}){ $copy{$p} = $hash{$p};} + } + return %copy; } - sub sort_paths_based_on_router_usage{ - my ($self,$paths_to_dst,$usage)=@_; - my %scored; - my %usage_r= %{$usage}; - #get list of 30% high congested ruters - my @A = sort { $usage_r{$b} <=> $usage_r{$a} } keys %usage_r; - #my $t = (scalar @A)*.3; # %30 - my %congested; - foreach my $a ( @A){ - $congested{$a}=$usage_r{$a};# if(scalar(keys %congested)<$t); - } - - my $i=0; - foreach my $path (@{$paths_to_dst}) { - my $val = 0; - my $num=0; - for my $r (@{$path}){ - if(defined $congested{$r}){ - $val+=$congested{$r}**1.5;# pow of 3/2 to give higher weight to more congested routers - $num++; - } - } - $scored{$i}=($num==0)? 0 : $val/$num; #average weight of congested routers - $i++; - } - - my @order = sort { $scored{$a} <=> $scored{$b} } keys %scored; - my @sorted; - - - - $i=0; - foreach my $a ( @order){ - $sorted[$i]=${$paths_to_dst}[$a]; - $i++; - #print "\$max{$a}=$max{$a}," - } - - #print "\n"; - - return @sorted; -} - + my ($self,$paths_to_dst,$usage)=@_; + my %scored; + my %usage_r= %{$usage}; + #get list of 30% high congested ruters + my @A = sort { $usage_r{$b} <=> $usage_r{$a} } keys %usage_r; + #my $t = (scalar @A)*.3; # %30 + my %congested; + foreach my $a ( @A){ + $congested{$a}=$usage_r{$a};# if(scalar(keys %congested)<$t); + } + my $i=0; + foreach my $path (@{$paths_to_dst}) { + my $val = 0; + my $num=0; + for my $r (@{$path}){ + if(defined $congested{$r}){ + $val+=$congested{$r}**1.5;# pow of 3/2 to give higher weight to more congested routers + $num++; + } + } + $scored{$i}=($num==0)? 0 : $val/$num; #average weight of congested routers + $i++; + } + my @order = sort { $scored{$a} <=> $scored{$b} } keys %scored; + my @sorted; + $i=0; + foreach my $a ( @order){ + $sorted[$i]=${$paths_to_dst}[$a]; + $i++; + #print "\$max{$a}=$max{$a}," + } + #print "\n"; + return @sorted; +} sub sort_paths_based_on_link_usage{ - my ($self,$paths_to_dst)=@_; - - my %L_num; - my %max; - my @all_endpoints=get_list_of_all_endpoints($self); - #get link count - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - my $path = $self->object_get_attribute('Route',"${src}::$dst"); - if (defined $path){ - #path counting - my @p= get_adjacent_router_in_a_path($path); - - foreach my $r (@p){ - $L_num{$r} ++; - } - - } - } - } - #get std_devision of link for each path if added - my $i=0; - foreach my $path (@{$paths_to_dst}) { - my %copy = clone_hash(\%L_num); - my @p=get_adjacent_router_in_a_path($path); - foreach my $r (@p){ - $copy{$r} ++; - } - my @l = sort values (%copy); - my $std=stdev(\@l); - $max{$i}=$std*100; - $i++; - } - - - my @order = sort { $max{$a} <=> $max{$b} } keys(%max); - - #print "*********** @order ************"; - my @sorted; - $i=0; - foreach my $a ( @order){ - $sorted[$i]=${$paths_to_dst}[$a]; - $i++; - #print "\$max{$a}=$max{$a}," - } - - #print "\n"; - - return @sorted; - - + my ($self,$paths_to_dst)=@_; + my %L_num; + my %max; + my @all_endpoints=get_list_of_all_endpoints($self); + #get link count + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + my $path = $self->object_get_attribute('Route',"${src}::$dst"); + if (defined $path){ + #path counting + my @p= get_adjacent_router_in_a_path($path); + foreach my $r (@p){ + $L_num{$r} ++; + } + } + } + } + #get std_devision of link for each path if added + my $i=0; + foreach my $path (@{$paths_to_dst}) { + my %copy = clone_hash(\%L_num); + my @p=get_adjacent_router_in_a_path($path); + foreach my $r (@p){ + $copy{$r} ++; + } + my @l = sort values (%copy); + my $std=stdev(\@l); + $max{$i}=$std*100; + $i++; + } + my @order = sort { $max{$a} <=> $max{$b} } keys(%max); + #print "*********** @order ************"; + my @sorted; + $i=0; + foreach my $a ( @order){ + $sorted[$i]=${$paths_to_dst}[$a]; + $i++; + #print "\$max{$a}=$max{$a}," + } + #print "\n"; + return @sorted; } - sub get_router_usage{ - my ($self,$acycle_turn_ref)=@_; - - my @all_endpoints=get_list_of_all_endpoints($self); - my %router_cnt; - #get router counts - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - #get list of all path between a source and destination nodes - my ($paths_to_dst,$ports_to_dst)= get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,$acycle_turn_ref); - - my @paths = @{$paths_to_dst}; - foreach my $path (@paths){ - shift @{$path}; #remove source node from the path - pop @{$path}; #remove the destination node from the path - foreach my $q ( @{$path}){ - $router_cnt{"$q"} = ( defined $router_cnt{"$q"})? $router_cnt{"$q"}+1 : 1; - } - } - } - } - - return %router_cnt; - + my ($self,$acycle_turn_ref)=@_; + my @all_endpoints=get_list_of_all_endpoints($self); + my %router_cnt; + #get router counts + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + #get list of all path between a source and destination nodes + my ($paths_to_dst,$ports_to_dst)= get_all_paths_between_two_endps_using_accyclic_turn($self,$src, $dst,$acycle_turn_ref); + my @paths = @{$paths_to_dst}; + foreach my $path (@paths){ + shift @{$path}; #remove source node from the path + pop @{$path}; #remove the destination node from the path + foreach my $q ( @{$path}){ + $router_cnt{"$q"} = ( defined $router_cnt{"$q"})? $router_cnt{"$q"}+1 : 1; + } + } + } + } + return %router_cnt; } - sub check_cyclick_loop{ - my ($self,$paths_to_dst)=@_; - - - my %graph; - my @all_endpoints=get_list_of_all_endpoints($self); - # create routing dependency graph - - foreach my $src (@all_endpoints ){ - foreach my $dst (@all_endpoints ){ - my $path = $self->object_get_attribute('Route',"${src}::$dst"); - if (defined $path){ - #path counting - my @p= get_adjacent_node_in_a_path($path); - %graph=add_route_edge_to_graph(\%graph,\@p); - - } - } - } - - my @p= get_adjacent_node_in_a_path($paths_to_dst); - %graph=add_route_edge_to_graph(\%graph,\@p); - - my $result = Algorithm::TSort::cicle_detect( Algorithm::TSort::Graph( ADJ => \%graph ), keys %graph ); - - #print Data::Dumper->Dump([\%graph],["link"]); - #print "result=$result\n"; - - - - - - - - return $result; - - + my ($self,$paths_to_dst)=@_; + my %graph; + my @all_endpoints=get_list_of_all_endpoints($self); + # create routing dependency graph + foreach my $src (@all_endpoints ){ + foreach my $dst (@all_endpoints ){ + my $path = $self->object_get_attribute('Route',"${src}::$dst"); + if (defined $path){ + #path counting + my @p= get_adjacent_node_in_a_path($path); + %graph=add_route_edge_to_graph(\%graph,\@p); + } + } + } + my @p= get_adjacent_node_in_a_path($paths_to_dst); + %graph=add_route_edge_to_graph(\%graph,\@p); + my $result = Algorithm::TSort::cicle_detect( Algorithm::TSort::Graph( ADJ => \%graph ), keys %graph ); + #print Data::Dumper->Dump([\%graph],["link"]); + #print "result=$result\n"; + return $result; } sub generate_topology{ - my ($self,$info)=@_; - my $name=$self->object_get_attribute('save_as'); + my ($self,$info)=@_; + my $name=$self->object_get_attribute('save_as'); my $error = check_verilog_identifier_syntax($name); if ( defined $error ){ #message_dialog("The \"$name\" is given with an unacceptable formatting. The mpsoc name will be used as top level verilog module name so it must follow Verilog identifier declaration formatting:\n $error"); @@ -2893,330 +2201,251 @@ sub generate_topology{ add_colored_info($info, $message,'red' ); return 0; } - - - - - #make destination dir - my $dir =get_project_dir()."/mpsoc/rtl/src_topology/$name"; - mkpath("$dir",1,01777) unless (-d $dir) ; - mkpath("$dir/../common",1,01777) unless (-d "$dir/../common") ; - - #save topology image file - $self->object_add_attribute("graph_save","name","$dir/$name"); - $self->object_add_attribute("graph_save","extension",'png'); - $self->object_add_attribute("graph_save","enable",1); - - show_custom_topology_diagram ($self,undef,"topology_diagram"); - - - - #generate topology top module verilog file - generate_topology_top_v($self,$info,$dir); - generate_topology_top_genvar_v($self,$info,$dir); - generate_routing_v($self,$info,$dir); - #generate_connection_v($self,$info,$dir); - add_routing_instance_v($self,$info,$dir); - add_noc_instance_v($self,$info,$dir); - add_noc_custom_h($self,$info,$dir); - save_topology_parameter_object_file($self,$info); - - #create the file list - my $txt="+incdir+./\n"; - my @files = File::Find::Rule->file() - ->name( '*.v','*.sv') - ->in( "$dir/../" ); + #make destination dir + my $dir =get_project_dir()."/mpsoc/rtl/src_topology/$name"; + mkpath("$dir",1,01777) unless (-d $dir) ; + mkpath("$dir/../common",1,01777) unless (-d "$dir/../common") ; + #save topology image file + $self->object_add_attribute("graph_save","name","$dir/$name"); + $self->object_add_attribute("graph_save","extension",'png'); + $self->object_add_attribute("graph_save","enable",1); + show_custom_topology_diagram ($self,undef,"topology_diagram"); + #generate topology top module verilog file + generate_topology_top_v($self,$info,$dir); + generate_topology_top_genvar_v($self,$info,$dir); + generate_routing_v($self,$info,$dir); + #generate_connection_v($self,$info,$dir); + add_routing_instance_v($self,$info,$dir); + add_noc_instance_v($self,$info,$dir); + add_noc_custom_h($self,$info,$dir); + save_topology_parameter_object_file($self,$info); + #create the file list + my $txt="+incdir+./\n"; + my @files = File::Find::Rule->file() + ->name( '*.v','*.sv') + ->in( "$dir/../" ); foreach my $f (@files){ - my $d = basename(dirname(abs_path($f))); - my $n = basename($f); - $txt.="./$d/$n\n"; + my $d = basename(dirname(abs_path($f))); + my $n = basename($f); + $txt.="./$d/$n\n"; } - save_file("$dir/../custom_flist.f",$txt); - - + save_file("$dir/../custom_flist.f",$txt); + message_dialog("Custom topology \"$name\" is generated in $dir!"); } - sub save_topology_parameter_object_file{ - my ($self,$info)=@_; - my $name=$self->object_get_attribute('save_as'); - my $rname=$self->object_get_attribute('routing_name'); - my $dir =get_project_dir()."/mpsoc/rtl/src_topology"; - my $file="$dir/param.obj"; - - my %param; - - if(-f $file){ - my ($pp,$r,$err) = regen_object($file ); - if ($r){ + my ($self,$info)=@_; + my $name=$self->object_get_attribute('save_as'); + my $rname=$self->object_get_attribute('routing_name'); + my $dir =get_project_dir()."/mpsoc/rtl/src_topology"; + my $file="$dir/param.obj"; + my %param; + if(-f $file){ + my ($pp,$r,$err) = regen_object($file ); + if ($r){ add_info($info,"**Error: cannot open $file file: $err\n"); return; - } - - %param=%{$pp}; - } - - - my @ends=get_list_of_all_endpoints($self); + } + %param=%{$pp}; + } + my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - my $MAX_P=0; my %router_ps; foreach my $p (@routers){ - my $Pnum=$self->object_get_attribute("$p",'PNUM'); - $MAX_P =$Pnum if($Pnum>$MAX_P ); - $router_ps{$Pnum}=(defined $router_ps{$Pnum})? $router_ps{$Pnum}+1 : '1'; - } - + my $Pnum=$self->object_get_attribute("$p",'PNUM'); + $MAX_P =$Pnum if($Pnum>$MAX_P ); + $router_ps{$Pnum}=(defined $router_ps{$Pnum})? $router_ps{$Pnum}+1 : '1'; + } my $NE= scalar @ends; my $NR= scalar @routers; - - - $param{"\"$name\""}{'T1'}=$NE; - $param{"\"$name\""}{'T2'}=$NR; - $param{"\"$name\""}{'T3'}=$MAX_P; - my $routs = $param{"\"$name\""}{'ROUTE_NAME'}; - my $new="\"$rname\""; - if(!defined $routs){ - $param{"\"$name\""}{'ROUTE_NAME'}=$new; - } - else { - my @r=split(/\s*,\s*/,$routs); - unless( grep (/^$new$/,@r)){ - $param{"\"$name\""}{'ROUTE_NAME'}= $routs.",$new" ; - } - } - - $param{"\"$name\""}{'ROUTER_Ps'}= \%router_ps; - - - my @er_addr; - foreach my $end (@ends){ - my $connect = $self->{$end}{'PCONNECT'}{'Port[0]'}; - my ($Rname,$Rport)=split(/\s*,\s*/,$connect); - my $R = get_scolar_pos($Rname,@routers); - push(@er_addr,$R); - } - $param{"\"$name\""}{'er_addr'}= \@er_addr; - - - - + $param{"\"$name\""}{'T1'}=$NE; + $param{"\"$name\""}{'T2'}=$NR; + $param{"\"$name\""}{'T3'}=$MAX_P; + my $routs = $param{"\"$name\""}{'ROUTE_NAME'}; + my $new="\"$rname\""; + if(!defined $routs){ + $param{"\"$name\""}{'ROUTE_NAME'}=$new; + } + else { + my @r=split(/\s*,\s*/,$routs); + unless( grep (/^$new$/,@r)){ + $param{"\"$name\""}{'ROUTE_NAME'}= $routs.",$new" ; + } + } + $param{"\"$name\""}{'ROUTER_Ps'}= \%router_ps; + my @er_addr; + foreach my $end (@ends){ + my $connect = $self->{$end}{'PCONNECT'}{'Port[0]'}; + my ($Rname,$Rport)=split(/\s*,\s*/,$connect); + my $R = get_scolar_pos($Rname,@routers); + push(@er_addr,$R); + } + $param{"\"$name\""}{'er_addr'}= \@er_addr; open(FILE, ">$file") || die "Can not open: $!"; print FILE perl_file_header("$file"); print FILE Data::Dumper->Dump([\%param],['Topology']); close(FILE) || die "Error closing file: $!"; - } - sub get_path_route_widgets { - my ($self,$info)=@_; - - my $w1 = show_paths_between_two_endps($self,$info); - my $w2 = routing_summary($self,$info); + my ($self,$info)=@_; + my $w1 = show_paths_between_two_endps($self,$info); + my $w2 = routing_summary($self,$info); my $h=gen_hpaned($w1,.15,$w2); - $h -> pack1($w1, TRUE, TRUE); - $h -> pack2($w2, TRUE, TRUE); - return $h; + $h -> pack1($w1, TRUE, TRUE); + $h -> pack2($w2, TRUE, TRUE); + return $h; } - sub load_nwm{ - my ($self,$info)=@_; - load_net_maker($self,$info); - my $n=0; + my ($self,$info)=@_; + load_net_maker($self,$info); + my $n=0; my $sample="sample$n"; - $n++; - $self->object_add_attribute("id",undef,$n); - $self->object_add_attribute("active_setting",undef,undef); - $self->object_add_attribute_order("samples",$sample); - $self->object_add_attribute($sample,"color",1); - add_color_to_gd($self); + $n++; + $self->object_add_attribute("id",undef,$n); + $self->object_add_attribute("active_setting",undef,undef); + $self->object_add_attribute_order("samples",$sample); + $self->object_add_attribute($sample,"color",1); + add_color_to_gd($self); } sub build_network_maker_gui { - my ($self) = @_; - set_gui_status($self,"ideal",0); - $self->object_add_attribute ("process_notebook","currentpage",0); - my $main_table= def_table(2,10,FALSE); - + my ($self) = @_; + set_gui_status($self,"ideal",0); + $self->object_add_attribute ("process_notebook","currentpage",0); + my $main_table= def_table(2,10,FALSE); my ($infobox,$info)= create_txview(); - - - my $notebook = gen_notebook(); - $notebook->set_tab_pos ('left'); - $notebook->set_scrollable(TRUE); - - - - my $page0=take_node_num_page($self); - my $page1=take_instance_page($self); - my $page2=connection_page_auto($self,$info); - my $page3=connection_page($self,$info); - my $page4=routing_page_manual($self,$info); - - my $page0_win = add_widget_to_scrolled_win($page0); - my $page1_win = add_widget_to_scrolled_win($page1); - my $page2_win = add_widget_to_scrolled_win($page2); - my $page3_win = add_widget_to_scrolled_win($page3); - my $page4_win = add_widget_to_scrolled_win($page4); - - - $notebook->append_page ($page0_win,gen_label_in_center (" Nodes #")); - $notebook->append_page ($page1_win,gen_label_in_center ("Instance")); - $notebook->append_page ($page2_win,gen_label_in_center ("Connection Auto")); - $notebook->append_page ($page3_win,gen_label_in_center ("Connection Manual")); - $notebook->append_page ($page4_win,gen_label_in_center ("Route Select")); - - - $notebook->signal_connect( 'switch-page'=> sub{ # rebulid the current page - $self->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber - set_gui_status($self,"ref",1); - }); - - - my $draw=custom_topology_diagram($self); - my $h1=gen_hpaned($notebook,.35,$draw); - - - my $v2=gen_vpaned($h1,.65,$infobox); - my $pronoc_dir = get_project_dir(); #mpsoc dir addr - my $target_dir= "$pronoc_dir/mpsoc/rtl/src_topology/"; + my $notebook = gen_notebook(); + $notebook->set_tab_pos ('left'); + $notebook->set_scrollable(TRUE); + my $page0=take_node_num_page($self); + my $page1=take_instance_page($self); + my $page2=connection_page_auto($self,$info); + my $page3=connection_page($self,$info); + my $page4=routing_page_manual($self,$info); + my $page0_win = add_widget_to_scrolled_win($page0); + my $page1_win = add_widget_to_scrolled_win($page1); + my $page2_win = add_widget_to_scrolled_win($page2); + my $page3_win = add_widget_to_scrolled_win($page3); + my $page4_win = add_widget_to_scrolled_win($page4); + $notebook->append_page ($page0_win,gen_label_in_center (" Nodes #")); + $notebook->append_page ($page1_win,gen_label_in_center ("Instance")); + $notebook->append_page ($page2_win,gen_label_in_center ("Connection Auto")); + $notebook->append_page ($page3_win,gen_label_in_center ("Connection Manual")); + $notebook->append_page ($page4_win,gen_label_in_center ("Route Select")); + $notebook->signal_connect( 'switch-page'=> sub{ # rebulid the current page + $self->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber + set_gui_status($self,"ref",1); + }); + my $draw=custom_topology_diagram($self); + my $h1=gen_hpaned($notebook,.35,$draw); + my $v2=gen_vpaned($h1,.65,$infobox); + my $pronoc_dir = get_project_dir(); #mpsoc dir addr + my $target_dir= "$pronoc_dir/mpsoc/rtl/src_topology/"; my ($entrybox,$entry ) =gen_save_load_widget ( - $self, #the object + $self, #the object "Topology name",#the label shown for setting configuration - 'save_as',#the key name for saveing the setting configuration in object + 'save_as',#the key name for saveing the setting configuration in object 'Custom NoC Topology',#the label full name show in tool tips $target_dir,#Where the generted RTL files are loacted. Undef if not aplicaple 'soc',#check the given name match the SoC or mpsoc name rules 'lib/netwmaker',#where the current configuration seting file is saved 'NWM',#the extenstion given for configuration seting file - \&load_nwm,#refrence to load function - $info + \&load_nwm,#refrence to load function + $info ); - - - my $generate = def_image_button('icons/gen.png','Generate'); - my ($entrybox2,$entry2) = def_h_labeled_entry('Routing Alg. name:',undef); - - $entry2->signal_connect( 'changed'=> sub{ - my $name=$entry2->get_text(); - $self->object_add_attribute ("routing_name",undef,$name); - }); - - $main_table->attach_defaults ($v2 , 0, 12, 0,24); - $main_table->attach ($entrybox,2, 4, 24,25,'expand','shrink',2,2); - $main_table->attach ($entrybox2,4, 6, 24,25,'expand','shrink',2,2); - $main_table->attach ($generate, 6, 9, 24,25,'expand','shrink',2,2); - - my $sc_win = add_widget_to_scrolled_win($main_table); - - #setting for graphs - my $n=0; + my $generate = def_image_button('icons/gen.png','Generate'); + my ($entrybox2,$entry2) = def_h_labeled_entry('Routing Alg. name:',undef); + $entry2->signal_connect( 'changed'=> sub{ + my $name=$entry2->get_text(); + $self->object_add_attribute ("routing_name",undef,$name); + }); + $main_table->attach_defaults ($v2 , 0, 12, 0,24); + $main_table->attach ($entrybox,2, 4, 24,25,'expand','shrink',2,2); + $main_table->attach ($entrybox2,4, 6, 24,25,'expand','shrink',2,2); + $main_table->attach ($generate, 6, 9, 24,25,'expand','shrink',2,2); + my $sc_win = add_widget_to_scrolled_win($main_table); + #setting for graphs + my $n=0; my $sample="sample$n"; - $n++; - $self->object_add_attribute("id",undef,$n); - $self->object_add_attribute("active_setting",undef,undef); - $self->object_add_attribute_order("samples",$sample); - $self->object_add_attribute($sample,"color",1); - add_color_to_gd($self); - - $generate->signal_connect("clicked" => sub{ - generate_topology($self,$info); - - }); - - - - #check soc status every 0.5 second. refresh device table if there is any changes - Glib::Timeout->add (100, sub{ - - my ($state,$timeout)= get_gui_status($self); - - if ($timeout>0){ - $timeout--; - set_gui_status($self,$state,$timeout); - return TRUE; - - } - if($state eq "ideal"){ - return TRUE; - - } - - if($state eq "ref" || $state eq "redraw"){ - - my $page_num=$self->object_get_attribute ("process_notebook","currentpage"); - if($state eq "ref"){ - if($page_num==0){ - $page0->destroy; - $page0=take_node_num_page($self); - add_widget_to_scrolled_win($page0,$page0_win); - $page0_win->show_all; - - } - if($page_num==1){ - $page1->destroy; - $page1=take_instance_page($self); - add_widget_to_scrolled_win($page1,$page1_win); - $page1_win->show_all; - } - if($page_num==2){ - $page2->destroy; - $page2=connection_page_auto($self,$info); - add_widget_to_scrolled_win($page2,$page2_win); - $page2_win->show_all; - } - if($page_num==3){ - $page3->destroy; - $page3=connection_page($self,$info); - add_widget_to_scrolled_win($page3,$page3_win); - $page3_win->show_all; - } - if($page_num==4){ - $page4->destroy; - $page4=routing_page_manual($self,$info); - add_widget_to_scrolled_win($page4,$page4_win); - $page4_win->show_all; - } - - } - - if($page_num==4 ){ - $draw->destroy; - $draw = get_path_route_widgets($self,$info); - $h1 -> pack2($draw, TRUE, TRUE); - - - }else{ - - $draw->destroy; - $draw=custom_topology_diagram($self); - $h1 -> pack2($draw, TRUE, TRUE); - } - my $saved_name=$self->object_get_attribute('save_as'); - $entry->set_text($saved_name)if(defined $saved_name); - - $saved_name = $self->object_get_attribute('routing_name'); - $entry2->set_text($saved_name) if(defined $saved_name); - - set_gui_status($self,"ideal",0); - $main_table->show_all(); - - return TRUE; - - } - - #refresh GUI - - - $main_table->show_all(); - set_gui_status($self,"ideal",0); - - return TRUE; - - } ); - - return $sc_win; + $n++; + $self->object_add_attribute("id",undef,$n); + $self->object_add_attribute("active_setting",undef,undef); + $self->object_add_attribute_order("samples",$sample); + $self->object_add_attribute($sample,"color",1); + add_color_to_gd($self); + $generate->signal_connect("clicked" => sub{ + generate_topology($self,$info); + }); + #check soc status every 0.5 second. refresh device table if there is any changes + Glib::Timeout->add (100, sub{ + my ($state,$timeout)= get_gui_status($self); + if ($timeout>0){ + $timeout--; + set_gui_status($self,$state,$timeout); + return TRUE; + } + if($state eq "ideal"){ + return TRUE; + } + if($state eq "ref" || $state eq "redraw"){ + my $page_num=$self->object_get_attribute ("process_notebook","currentpage"); + if($state eq "ref"){ + if($page_num==0){ + $page0->destroy; + $page0=take_node_num_page($self); + add_widget_to_scrolled_win($page0,$page0_win); + $page0_win->show_all; + } + if($page_num==1){ + $page1->destroy; + $page1=take_instance_page($self); + add_widget_to_scrolled_win($page1,$page1_win); + $page1_win->show_all; + } + if($page_num==2){ + $page2->destroy; + $page2=connection_page_auto($self,$info); + add_widget_to_scrolled_win($page2,$page2_win); + $page2_win->show_all; + } + if($page_num==3){ + $page3->destroy; + $page3=connection_page($self,$info); + add_widget_to_scrolled_win($page3,$page3_win); + $page3_win->show_all; + } + if($page_num==4){ + $page4->destroy; + $page4=routing_page_manual($self,$info); + add_widget_to_scrolled_win($page4,$page4_win); + $page4_win->show_all; + } + } + if($page_num==4 ){ + $draw->destroy; + $draw = get_path_route_widgets($self,$info); + $h1 -> pack2($draw, TRUE, TRUE); + }else{ + $draw->destroy; + $draw=custom_topology_diagram($self); + $h1 -> pack2($draw, TRUE, TRUE); + } + my $saved_name=$self->object_get_attribute('save_as'); + $entry->set_text($saved_name)if(defined $saved_name); + $saved_name = $self->object_get_attribute('routing_name'); + $entry2->set_text($saved_name) if(defined $saved_name); + set_gui_status($self,"ideal",0); + $main_table->show_all(); + return TRUE; + } + #refresh GUI + $main_table->show_all(); + set_gui_status($self,"ideal",0); + return TRUE; + } ); + return $sc_win; } +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/orcc.pl b/mpsoc/perl_gui/lib/perl/orcc.pl index 6e1aed1..80bde5c 100644 --- a/mpsoc/perl_gui/lib/perl/orcc.pl +++ b/mpsoc/perl_gui/lib/perl/orcc.pl @@ -2,771 +2,570 @@ use constant::boolean; use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - - use String::Scanf; # imports sscanf() - sub select_orcc_generated_srcs { - my ($self)=@_; - #my $window = def_popwin_size(80,80,"Generate software using ORCC compiler",'percent'); - #my $table = def_table(10, 10, FALSE); - #$table->attach_defaults($infobox,0,20,$row,$row+1); - - #pass noc parameter to trace generator - my %p; - my $params_ref=$self->object_get_attribute('noc_param'); - if(defined $params_ref ){ - - $p{'noc_param'}=$params_ref; - } - #pass mpsoc name to trace genrator - my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); - $p{'mpsoc_name'}=$mpsoc_name; - - #pass soc names to trace genrator - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + my ($self)=@_; + #my $window = def_popwin_size(80,80,"Generate software using ORCC compiler",'percent'); + #my $table = def_table(10, 10, FALSE); + #$table->attach_defaults($infobox,0,20,$row,$row+1); + #pass noc parameter to trace generator + my %p; + my $params_ref=$self->object_get_attribute('noc_param'); + if(defined $params_ref ){ + $p{'noc_param'}=$params_ref; + } + #pass mpsoc name to trace genrator + my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); + $p{'mpsoc_name'}=$mpsoc_name; + #pass soc names to trace genrator + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); for (my $tile_num=0;$tile_num<$NE;$tile_num++){ my ($soc_name,$num)= $self->mpsoc_get_tile_soc_name($tile_num); my $top=$self->mpsoc_get_soc($soc_name); if(defined $top){ - my @nis=get_NI_instance_list($top); - my $inst_name=$top->top_get_def_of_instance($nis[0],'instance'); - $p{'ni_name'}{$tile_num}=$inst_name; - $p{'soc_name'}{$tile_num}=$soc_name; + my @nis=get_NI_instance_list($top); + my $inst_name=$top->top_get_def_of_instance($nis[0],'instance'); + $p{'ni_name'}{$tile_num}=$inst_name; + $p{'soc_name'}{$tile_num}=$soc_name; } } - - - - - - - my $trace_gen= trace_gen_main('orcc',\%p);#,$window); - - #$window->add ($trace_gen); - #$window->show_all(); - - return $trace_gen; - my $table; - - - - - $self->object_add_attribute("file_id",undef,0); - $self->object_add_attribute("trace_id",undef,0); - - - - - - my $col=0; - my $row=0; - my $add = def_image_button('icons/import.png',"Load"); - set_tip($add,'Select ORCC generated CSV file'); - - - $table->attach($add,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; - my ($infobox,$info)= create_txview(); - - - + my $trace_gen= trace_gen_main('orcc',\%p);#,$window); + #$window->add ($trace_gen); + #$window->show_all(); + return $trace_gen; + my $table; + $self->object_add_attribute("file_id",undef,0); + $self->object_add_attribute("trace_id",undef,0); + my $col=0; + my $row=0; + my $add = def_image_button('icons/import.png',"Load"); + set_tip($add,'Select ORCC generated CSV file'); + $table->attach($add,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; + my ($infobox,$info)= create_txview(); my $draw = def_image_button('icons/diagram.png'); - set_tip($draw,'View Actor Connection Graph'); - $table->attach($draw,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; - $draw->signal_connect ( 'clicked'=> sub{ - show_trace_diagram($self,'trace'); - }); + set_tip($draw,'View Actor Connection Graph'); + $table->attach($draw,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; + $draw->signal_connect ( 'clicked'=> sub{ + show_trace_diagram($self,'trace'); + }); $row++; $col=0; my $map=actor_map($self,$info); - $table->attach_defaults($map,0,5,$row,$row+1); - - - my $i; - for ($i=$row; $i<5; $i++){ - - my $temp=gen_label_in_center(" "); - $table->attach_defaults ($temp, 0, 6 , $i, $i+1); - } - $row=$i; - - - $col=5; - my $next=def_image_button('icons/right.png','Next'); - $table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; - - - - $add->signal_connect ( 'clicked'=> sub{ - - my $file; + $table->attach_defaults($map,0,5,$row,$row+1); + my $i; + for ($i=$row; $i<5; $i++){ + my $temp=gen_label_in_center(" "); + $table->attach_defaults ($temp, 0, 6 , $i, $i+1); + } + $row=$i; + $col=5; + my $next=def_image_button('icons/right.png','Next'); + $table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++; + $add->signal_connect ( 'clicked'=> sub{ + my $file; my $dialog = gen_file_dialog('Select the ORCC generated CSV File','csv'); - - - - - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - load_orcc_csv($self,$file,$info); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + load_orcc_csv($self,$file,$info); } - $dialog->destroy; - }); - - - - + $dialog->destroy; + }); } - - - - sub load_orcc_file{ - my($self,$tview)=@_; - my $file; + my($self,$tview)=@_; + my $file; my $dialog = gen_file_dialog( undef,"csv"); - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - load_orcc_csv($self,$file,$tview); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + load_orcc_csv($self,$file,$tview); } - $dialog->destroy; + $dialog->destroy; } - - - - sub load_orcc_csv{ - my ($self,$file,$info)=@_; - - add_info($info,"Use $file for generating actors network\n"); - unless (-e $file){ - add_colored_info($info,"Cannot find $file\n",'red'); - return; - } - - my $f_id=$self->object_get_attribute("file_id",undef); - my $t_id=$self->object_get_attribute("trace_id",undef); - - open my $in, "<:encoding(utf8)", $file or die "$file: $!"; - my $sect=0; - my $net; - my @actors; - - my %chanels; - - while (my $line = <$in>) { - chomp $line; - $line =~ s/[^\S\n]+//g; #remove space - - if ($line =~ /Name,Package,Actors,Connections/){ - $sect=1; - next; - } - if ($line =~ /Name,Incoming,Outgoing,Inputs,Outputs/){ - $sect=2; - next; - } - if ($line =~ /Source,SrcPort,Target,TgtPort/){ - $sect=3; - next; - } - if($sect==1){ - my @fileds=split(/\s*,\s*/,$line); - if(defined $fileds[0]){$net=$fileds[0] if($fileds[0]=~/^\w/);} - } - if($sect==2){ - my @fileds=split(/\s*,\s*/,$line); - if(defined $fileds[0]){ push(@actors,$fileds[0]) if($fileds[0]=~/^\w/);} - } - if($sect==3){ - my @fileds=split(/\s*,\s*/,$line); - if(defined $fileds[0]){ - my $src=$fileds[0]; - my $src_port=$fileds[1]; - my $dest=$fileds[2]; - my $dst_port=$fileds[3]; - my $buff_Size=$fileds[4]; - - - $chanels{"${src}:$src_port"}= (defined $chanels{"${src}:$src_port"})? $chanels{"${src}:$src_port"}+1 : 0; - my $cc=$chanels{"${src}:$src_port"}; - #print "find chanel for ** ${src}_$src_port -> ${dest}_$dst_port**: $cc\n"; - - add_trace($self, "${net}:${f_id}:","raw",$t_id, $src,$dest, 1,$file, $src_port,$dst_port,$buff_Size,$chanels{"${src}:$src_port"},0); - #print "add_trace($self, \"${net}:${f_id}:\",\"raw\",$t_id, $src,$dest, 1,$file, $src_port,$dst_port,$buff_Size,$chanels{\"${src}:$src_port\"});\n"; - $t_id++; - } - - } - $self->set_gui_status('ref',0); - - } - - my $num=scalar @actors; - if($num==0){ - add_colored_info($info,"Could not find any actor in $file\n",'red'); - return; - } - add_info($info,"total of $num actors have found:\n\t"); - my $n=1; - foreach my $act (@actors){ - add_colored_info($info,"$n-$act ",'blue'); - $n++; - } - add_info($info,"\n"); - - $f_id++; - $self->object_add_attribute("trace_id",undef,$t_id); - $self->object_add_attribute("file_id",undef,$f_id); - - - + my ($self,$file,$info)=@_; + add_info($info,"Use $file for generating actors network\n"); + unless (-e $file){ + add_colored_info($info,"Cannot find $file\n",'red'); + return; + } + my $f_id=$self->object_get_attribute("file_id",undef); + my $t_id=$self->object_get_attribute("trace_id",undef); + open my $in, "<:encoding(utf8)", $file or die "$file: $!"; + my $sect=0; + my $net; + my @actors; + my %chanels; + while (my $line = <$in>) { + chomp $line; + $line =~ s/[^\S\n]+//g; #remove space + if ($line =~ /Name,Package,Actors,Connections/){ + $sect=1; + next; + } + if ($line =~ /Name,Incoming,Outgoing,Inputs,Outputs/){ + $sect=2; + next; + } + if ($line =~ /Source,SrcPort,Target,TgtPort/){ + $sect=3; + next; + } + if($sect==1){ + my @fileds=split(/\s*,\s*/,$line); + if(defined $fileds[0]){$net=$fileds[0] if($fileds[0]=~/^\w/);} + } + if($sect==2){ + my @fileds=split(/\s*,\s*/,$line); + if(defined $fileds[0]){ push(@actors,$fileds[0]) if($fileds[0]=~/^\w/);} + } + if($sect==3){ + my @fileds=split(/\s*,\s*/,$line); + if(defined $fileds[0]){ + my $src=$fileds[0]; + my $src_port=$fileds[1]; + my $dest=$fileds[2]; + my $dst_port=$fileds[3]; + my $buff_Size=$fileds[4]; + $chanels{"${src}:$src_port"}= (defined $chanels{"${src}:$src_port"})? $chanels{"${src}:$src_port"}+1 : 0; + my $cc=$chanels{"${src}:$src_port"}; + #print "find chanel for ** ${src}_$src_port -> ${dest}_$dst_port**: $cc\n"; + add_trace($self, "${net}:${f_id}:","raw",$t_id, $src,$dest, 1,$file, $src_port,$dst_port,$buff_Size,$chanels{"${src}:$src_port"},0); + #print "add_trace($self, \"${net}:${f_id}:\",\"raw\",$t_id, $src,$dest, 1,$file, $src_port,$dst_port,$buff_Size,$chanels{\"${src}:$src_port\"});\n"; + $t_id++; + } + } + $self->set_gui_status('ref',0); + } + my $num=scalar @actors; + if($num==0){ + add_colored_info($info,"Could not find any actor in $file\n",'red'); + return; + } + add_info($info,"total of $num actors have found:\n\t"); + my $n=1; + foreach my $act (@actors){ + add_colored_info($info,"$n-$act ",'blue'); + $n++; + } + add_info($info,"\n"); + $f_id++; + $self->object_add_attribute("trace_id",undef,$t_id); + $self->object_add_attribute("file_id",undef,$f_id); } - sub update_merge_actor_list{ - my ($self,$tview)=@_; - - #delete old merge objects + my ($self,$tview)=@_; + #delete old merge objects remove_all_traces ($self,'merge'); - - #add not mereged traces - my $t_id=0; - my $ungrouped_ref= $self->object_get_attribute("grouping",'ungrouped'); - my @ungrouped = (defined $ungrouped_ref)? @{$ungrouped_ref}:[]; - foreach my $actor (@ungrouped){ - my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); - foreach my $inject (@injectors) { - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,'raw',$inject); - my $tdst=$self->get_item_group_name('grouping',$dst); - $dst_port=0 if (!defined $dst_port); - if($tdst ne $dst){ - $dst_port="${dst}_$dst_port"; - } - - add_trace($self, "$file_id",'merge',$t_id, $src,$tdst,$Mbytes,$file_name, $src_port,$dst_port,$buff_size,$chanel,$vc,$class); - if(defined $min_pck){ - add_trace_extra($self, "$file_id",'merge',$t_id,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var ); - } - $t_id++; - } - - } - - #update group list - my $group_num=$self->object_get_attribute("grouping",'group_num'); - my $gname=$self->object_get_attribute("grouping",'group_name_root'); - for(my $i=0;$i<$group_num;$i=$i+1){ - my $gref = $self->object_get_attribute("grouping","$gname($i)"); - next if(! defined $gref); - my @grouped = @{$gref}; - next if (scalar @grouped == 0); - - - my $merged_actor = $self->object_get_attribute('grouping',"group($i)"."_name"); - $merged_actor = "group($i)" if(!defined $merged_actor); - #my $tile =get_task_give_tile($self,$merged_actor); - # print "my $tile =get_task_give_tile($self,$merged_actor);\n"; - #my $tile_id=get_tile_id($self,$merged_actor); - #my $tile_id = tile_id_number($tile); - - #add_info($tview,"Generating $merged_actor.c grouped actor file from: @grouped actors\n"); - - - my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); - $mpsoc_name = 'tmp' if (!defined $mpsoc_name); - my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - - #setp 1 : find local communication ports in merged actor - foreach my $actor (@grouped) { - my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); - #Where does it transfer? - foreach my $inject (@injectors) { - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,'raw',$inject); - $dst_port=0 if (!defined $dst_port); - $src_port=0 if (!defined $src_port); - my $dst_actor=$dst; - if (check_scolar_exist_in_array($dst,\@grouped)){ - #print "$src $src_port is locally connected to $dst $dst_port\n"; - $self->object_add_attribute("locally_connected","${dst}_${dst_port}","${src}_${src_port}"); - } - else - { - #my ($net,$num,$name)=split(':',$src); - my $merge_src="$merged_actor"; - $src_port="${src}_$src_port"; - - my $file="$target_dir/sw/$actor.c"; - - my $tdst=$self->get_item_group_name('grouping',$dst); - # ($dnet,$dnum,$dname)=split(':',$tdst); - if($tdst ne $dst){ - #my ($dnet,$dnum,$dname)=split(':',$dst); - $dst_port="${dst}_$dst_port"; - } - - add_trace($self, "$file_id",'merge',$t_id, $merge_src,$tdst, $Mbytes,$file, $src_port,$dst_port,$buff_size,$chanel,$vc,$class); - if(defined $min_pck){ - add_trace_extra($self, "$file_id",'merge',$t_id,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var ); - } - $t_id++; - }#else - }#$ink=ject - }#actor - } + #add not mereged traces + my $t_id=0; + my $ungrouped_ref= $self->object_get_attribute("grouping",'ungrouped'); + my @ungrouped = (defined $ungrouped_ref)? @{$ungrouped_ref}:[]; + foreach my $actor (@ungrouped){ + my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); + foreach my $inject (@injectors) { + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,'raw',$inject); + my $tdst=$self->get_item_group_name('grouping',$dst); + $dst_port=0 if (!defined $dst_port); + if($tdst ne $dst){ + $dst_port="${dst}_$dst_port"; + } + add_trace($self, "$file_id",'merge',$t_id, $src,$tdst,$Mbytes,$file_name, $src_port,$dst_port,$buff_size,$chanel,$vc,$class); + if(defined $min_pck){ + add_trace_extra($self, "$file_id",'merge',$t_id,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var ); + } + $t_id++; + } + } + #update group list + my $group_num=$self->object_get_attribute("grouping",'group_num'); + my $gname=$self->object_get_attribute("grouping",'group_name_root'); + for(my $i=0;$i<$group_num;$i=$i+1){ + my $gref = $self->object_get_attribute("grouping","$gname($i)"); + next if(! defined $gref); + my @grouped = @{$gref}; + next if (scalar @grouped == 0); + my $merged_actor = $self->object_get_attribute('grouping',"group($i)"."_name"); + $merged_actor = "group($i)" if(!defined $merged_actor); + #my $tile =get_task_give_tile($self,$merged_actor); + # print "my $tile =get_task_give_tile($self,$merged_actor);\n"; + #my $tile_id=get_tile_id($self,$merged_actor); + #my $tile_id = tile_id_number($tile); + #add_info($tview,"Generating $merged_actor.c grouped actor file from: @grouped actors\n"); + my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); + $mpsoc_name = 'tmp' if (!defined $mpsoc_name); + my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + #setp 1 : find local communication ports in merged actor + foreach my $actor (@grouped) { + my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); + #Where does it transfer? + foreach my $inject (@injectors) { + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,'raw',$inject); + $dst_port=0 if (!defined $dst_port); + $src_port=0 if (!defined $src_port); + my $dst_actor=$dst; + if (check_scolar_exist_in_array($dst,\@grouped)){ + #print "$src $src_port is locally connected to $dst $dst_port\n"; + $self->object_add_attribute("locally_connected","${dst}_${dst_port}","${src}_${src_port}"); + } + else + { + #my ($net,$num,$name)=split(':',$src); + my $merge_src="$merged_actor"; + $src_port="${src}_$src_port"; + my $file="$target_dir/sw/$actor.c"; + my $tdst=$self->get_item_group_name('grouping',$dst); + # ($dnet,$dnum,$dname)=split(':',$tdst); + if($tdst ne $dst){ + #my ($dnet,$dnum,$dname)=split(':',$dst); + $dst_port="${dst}_$dst_port"; + } + add_trace($self, "$file_id",'merge',$t_id, $merge_src,$tdst, $Mbytes,$file, $src_port,$dst_port,$buff_size,$chanel,$vc,$class); + if(defined $min_pck){ + add_trace_extra($self, "$file_id",'merge',$t_id,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var ); + } + $t_id++; + }#else + }#$ink=ject + }#actor + } } - - sub get_port_num{ - my ($self,$hash_ref,$actor,$port_name,$chanel) =@_; + my ($self,$hash_ref,$actor,$port_name,$chanel) =@_; return undef if(!defined $hash_ref); my %hash = %{$hash_ref}; - - my $port_num =(defined $chanel)? $hash{$actor}{$port_name}{$chanel} : $hash{$actor}{$port_name}; - if(!defined $port_num){ - #its a merged actor - my $merge_actor=$self->get_item_group_name('grouping',$actor); - #my($net,$num,$name)=split(':',$merge_actor); - my $merge_port="${actor}_$port_name"; - return $hash{$merge_actor}{$merge_port}{$chanel} if(defined $chanel); - return $hash{$merge_actor}{$merge_port}; - } - return $port_num; + my $port_num =(defined $chanel)? $hash{$actor}{$port_name}{$chanel} : $hash{$actor}{$port_name}; + if(!defined $port_num){ + #its a merged actor + my $merge_actor=$self->get_item_group_name('grouping',$actor); + #my($net,$num,$name)=split(':',$merge_actor); + my $merge_port="${actor}_$port_name"; + return $hash{$merge_actor}{$merge_port}{$chanel} if(defined $chanel); + return $hash{$merge_actor}{$merge_port}; + } + return $port_num; } - - - - - - sub get_fifo_list{ - my ($self)=@_; - my %fifos; - - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my $actor=get_task_assigned_to_tile($self,$tile_num); - next if(!defined $actor); - my $fifo_num=0; - my $ref = $self->get_items_in_a_group("grouping",$actor); - my @merge_actors = (defined $ref)? @{$ref} : ($actor); - foreach my $actor (@merge_actors){ - my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); - foreach my $inject (@injectors) { - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,'raw',$inject); - - $fifos{"${actor}_${src_port}"}{'size'}=$buff_size; - $fifos{"$actor"}{'file'}="$file_name"; - $fifos{"${actor}_${src_port}"}{'fifo_num'}=$fifo_num; - $fifos{"${actor}_${src_port}"}{'chanel_num'}= 0 if(!defined $fifos{"${actor}_${src_port}"}{'chanel_num'}); - $fifos{"${actor}_${src_port}"}{'chanel_num'}++; - $fifo_num++; - $fifos{"tile_$tile_num"}{'fifo_num'}=$fifo_num; - } - } + my ($self)=@_; + my %fifos; + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + my $actor=get_task_assigned_to_tile($self,$tile_num); + next if(!defined $actor); + my $fifo_num=0; + my $ref = $self->get_items_in_a_group("grouping",$actor); + my @merge_actors = (defined $ref)? @{$ref} : ($actor); + foreach my $actor (@merge_actors){ + my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); + foreach my $inject (@injectors) { + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,'raw',$inject); + $fifos{"${actor}_${src_port}"}{'size'}=$buff_size; + $fifos{"$actor"}{'file'}="$file_name"; + $fifos{"${actor}_${src_port}"}{'fifo_num'}=$fifo_num; + $fifos{"${actor}_${src_port}"}{'chanel_num'}= 0 if(!defined $fifos{"${actor}_${src_port}"}{'chanel_num'}); + $fifos{"${actor}_${src_port}"}{'chanel_num'}++; + $fifo_num++; + $fifos{"tile_$tile_num"}{'fifo_num'}=$fifo_num; + } + } } - - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my $actor=get_task_assigned_to_tile($self,$tile_num); - next if(!defined $actor); - my $fifo_num=$fifos{"tile_$tile_num"}{'fifo_num'}; - $fifo_num= 0 if(!defined $fifo_num); - my $ref = $self->get_items_in_a_group("grouping",$actor); - my @merge_actors = (defined $ref)? @{$ref} : ($actor); - foreach my $actor (@merge_actors){ - my @sinkers = get_all_dest_traces_of_actr ($self,$actor,'raw'); - foreach my $sink (@sinkers){ - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,'raw',$sink); - - $fifos{"${actor}_${dst_port}"}{'size'}=$buff_size; - $fifos{"$actor"}{'file'}="$file_name"; - $fifos{"${actor}_${dst_port}"}{'chanel_num'}=$fifos{"${src}_${src_port}"}{'chanel_num'}; - - my $src_fifo_name= $self->object_get_attribute("locally_connected","${actor}_${dst_port}"); - if (defined $src_fifo_name){ - #its localy connected. src fifo num and dst fifo num are identical - $fifos{"${actor}_${dst_port}"}{'fifo_num'}=$fifos{"$src_fifo_name"}{'fifo_num'}; - #print "\$fifos{\"${actor}_${dst_port}\"}{'fifo_num'}=\$fifos{\"$src_fifo_name\"}{'fifo_num'}=$fifos{$src_fifo_name}{'fifo_num'};\n"; - }else{ - $fifos{"${actor}_${dst_port}"}{'fifo_num'}=$fifo_num; - $fifo_num++; - $fifos{"tile_$tile_num"}{'fifo_num'}=$fifo_num; - } - - } - } + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + my $actor=get_task_assigned_to_tile($self,$tile_num); + next if(!defined $actor); + my $fifo_num=$fifos{"tile_$tile_num"}{'fifo_num'}; + $fifo_num= 0 if(!defined $fifo_num); + my $ref = $self->get_items_in_a_group("grouping",$actor); + my @merge_actors = (defined $ref)? @{$ref} : ($actor); + foreach my $actor (@merge_actors){ + my @sinkers = get_all_dest_traces_of_actr ($self,$actor,'raw'); + foreach my $sink (@sinkers){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,'raw',$sink); + $fifos{"${actor}_${dst_port}"}{'size'}=$buff_size; + $fifos{"$actor"}{'file'}="$file_name"; + $fifos{"${actor}_${dst_port}"}{'chanel_num'}=$fifos{"${src}_${src_port}"}{'chanel_num'}; + my $src_fifo_name= $self->object_get_attribute("locally_connected","${actor}_${dst_port}"); + if (defined $src_fifo_name){ + #its localy connected. src fifo num and dst fifo num are identical + $fifos{"${actor}_${dst_port}"}{'fifo_num'}=$fifos{"$src_fifo_name"}{'fifo_num'}; + #print "\$fifos{\"${actor}_${dst_port}\"}{'fifo_num'}=\$fifos{\"$src_fifo_name\"}{'fifo_num'}=$fifos{$src_fifo_name}{'fifo_num'};\n"; + }else{ + $fifos{"${actor}_${dst_port}"}{'fifo_num'}=$fifo_num; + $fifo_num++; + $fifos{"tile_$tile_num"}{'fifo_num'}=$fifo_num; + } + } + } } - - # print Dumper (\%fifos); - - - return %fifos; + # print Dumper (\%fifos); + return %fifos; } - sub get_dest_chanel_from_orcc_file{ - my ($actor_file,$actor,$dst_port)=@_; - #print ("-------------------\n"); - my $str = "${actor}_${dst_port}->read_inds\\s*\\["; - my $txt = load_file($actor_file); - my $n = capture_number_after($str,$txt); - return $n; + my ($actor_file,$actor,$dst_port)=@_; + #print ("-------------------\n"); + my $str = "${actor}_${dst_port}->read_inds\\s*\\["; + my $txt = load_file($actor_file); + my $n = capture_number_after($str,$txt); + return $n; } - sub genereate_output_orcc{ - my ($self,$tview,$window)=@_; - - # Code each actor destination port - - - my %soc_names=%{$self->object_get_attribute('soc_name')}; + my ($self,$tview,$window)=@_; + # Code each actor destination port + my %soc_names=%{$self->object_get_attribute('soc_name')}; my %ni_names =%{$self->object_get_attribute('ni_name')}; - - add_info($tview,"Generating grouped actor files\n"); - my $group_num=$self->object_get_attribute("grouping",'group_num'); - my $gname=$self->object_get_attribute("grouping",'group_name_root'); - - - my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); + add_info($tview,"Generating grouped actor files\n"); + my $group_num=$self->object_get_attribute("grouping",'group_num'); + my $gname=$self->object_get_attribute("grouping",'group_name_root'); + my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - update_merge_actor_list ($self,$tview); - my %srcp_number=get_srcport_constant_list($self,'merge'); - my %dstp_number=get_destport_constant_list($self,'merge'); - - #print "srcport:\n". Dumper(%srcp_number); - #print "dstport:\n". Dumper(%dstp_number); - - add_info($tview,"Generating source files\n"); - - my $ungrouped_ref= $self->object_get_attribute("grouping",'ungrouped'); - my @ungrouped = (defined $ungrouped_ref)? @{$ungrouped_ref}:[]; - - my %fifos=get_fifo_list($self); - - - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my $target_orccdir= "$target_dir/sw/tile${tile_num}/orcc"; - my $actor_tile ="tile($tile_num)"; - my $actor_tile_id=$tile_num; - my $src_lib_file="$target_dir/sw/tile${actor_tile_id}/SOURCE_LIB"; - my $actor=get_task_assigned_to_tile($self,$tile_num); + my %srcp_number=get_srcport_constant_list($self,'merge'); + my %dstp_number=get_destport_constant_list($self,'merge'); + #print "srcport:\n". Dumper(%srcp_number); + #print "dstport:\n". Dumper(%dstp_number); + add_info($tview,"Generating source files\n"); + my $ungrouped_ref= $self->object_get_attribute("grouping",'ungrouped'); + my @ungrouped = (defined $ungrouped_ref)? @{$ungrouped_ref}:[]; + my %fifos=get_fifo_list($self); + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + my $target_orccdir= "$target_dir/sw/tile${tile_num}/orcc"; + my $actor_tile ="tile($tile_num)"; + my $actor_tile_id=$tile_num; + my $src_lib_file="$target_dir/sw/tile${actor_tile_id}/SOURCE_LIB"; + my $actor=get_task_assigned_to_tile($self,$tile_num); my $soc_name=$soc_names{$actor_tile_id}; - my $ni_name=$ni_names{$actor_tile_id}; + my $ni_name=$ni_names{$actor_tile_id}; my $max_dst_port_num=0; - - - #remove old orcc lib folder - rmtree("$target_orccdir"); - - #generate main.c - my $r; - my @actors_file_names; - my $main_c = "$target_dir/sw/tile${actor_tile_id}/main.c"; - unlink $main_c; #delete old main.c file - open my $fd, ">$main_c" or $r = "$!\n"; - if(defined $r) { - add_colored_info($tview,"Could not open $main_c to write: $r",'red'); - return; - } - - #generate source_lib file - my $src_lib="SOURCE_LIB += $soc_name.c "; - - - if (!defined $actor){ - print $fd main_c_template($soc_name); - close($fd); - #write makefile source lib list file - save_file($src_lib_file,$src_lib); - next; - } - - - - mkpath("$target_orccdir",1,0755); - - print $fd autogen_warning(); - print $fd get_license_header($main_c); - - my $ref = $self->get_items_in_a_group("grouping",$actor); - my @merge_actors = (defined $ref)? @{$ref} : ($actor); - - my $main_include = "#include + rmtree("$target_orccdir"); + #generate main.c + my $r; + my @actors_file_names; + my $main_c = "$target_dir/sw/tile${actor_tile_id}/main.c"; + unlink $main_c; #delete old main.c file + open my $fd, ">$main_c" or $r = "$!\n"; + if(defined $r) { + add_colored_info($tview,"Could not open $main_c to write: $r",'red'); + return; + } + #generate source_lib file + my $src_lib="SOURCE_LIB += $soc_name.c "; + if (!defined $actor){ + print $fd main_c_template($soc_name); + close($fd); + #write makefile source lib list file + save_file($src_lib_file,$src_lib); + next; + } + mkpath("$target_orccdir",1,0755); + print $fd autogen_warning(); + print $fd get_license_header($main_c); + my $ref = $self->get_items_in_a_group("grouping",$actor); + my @merge_actors = (defined $ref)? @{$ref} : ($actor); + my $main_include = "#include #include \"$soc_name.h\" #include \"orcc/orcc_lib.h\" "; - - - - my $main_def=""; - my $main_fifo_def=""; - my $main_fifo_assign=""; - my $main_fifo_rst_ptr=" + my $main_def=""; + my $main_fifo_def=""; + my $main_fifo_assign=""; + my $main_fifo_rst_ptr=" volatile unsigned char iport_array[${ni_name}_NUM_VCs]; volatile unsigned char oport_array[${ni_name}_NUM_VCs]; unsigned int credit_buff[${ni_name}_NUM_VCs]; - void reset_all_fifo_ptr(void){\n"; - - my $all_got_packet_function=""; - my $all_sent_packet_done_function=""; - my $all_check_packet_function=""; - my $all_update_credit=""; - my $all_init_actor=""; - my $all_run_actor=""; - my $actors_str=''; - - - - #start generation - - - foreach my $actor (@merge_actors){ - my $actor_file= get_actr_file_name($self,$actor,'raw'); - my ($fname,$fpath,$fsuffix) = fileparse("$actor_file",qr"\..[^.]*$"); - my $target_actor_file="$target_orccdir/$fname.c"; - my $target_actor_header="$target_orccdir/$fname.h"; - open my $fc, ">$target_actor_file" or $r = "$!\n"; - if(defined $r) { - add_colored_info($tview,"Could not open $target_actor_file to write: $r",'red'); - return; - } - - my $LH=uc "${fname}"; - my $actor_h="#ifndef\t ${LH}_H\n\t#define\t${LH}_H\n\n"; - my $schedul=''; - my $Hw_fifo_define='' ; - my $transfer_str=''; - my $sink_str=''; - my $crdit_update=''; - - - - - - my $actor_got_pck_func= " -char ${actor}_got_packet_function( unsigned char iport, unsigned int v){ + my $all_got_packet_function=""; + my $all_sent_packet_done_function=""; + my $all_check_packet_function=""; + my $all_update_credit=""; + my $all_init_actor=""; + my $all_run_actor=""; + my $actors_str=''; + #start generation + foreach my $actor (@merge_actors){ + my $actor_file= get_actr_file_name($self,$actor,'raw'); + my ($fname,$fpath,$fsuffix) = fileparse("$actor_file",qr"\..[^.]*$"); + my $target_actor_file="$target_orccdir/$fname.c"; + my $target_actor_header="$target_orccdir/$fname.h"; + open my $fc, ">$target_actor_file" or $r = "$!\n"; + if(defined $r) { + add_colored_info($tview,"Could not open $target_actor_file to write: $r",'red'); + return; + } + my $LH=uc "${fname}"; + my $actor_h="#ifndef\t ${LH}_H\n\t#define\t${LH}_H\n\n"; + my $schedul=''; + my $Hw_fifo_define='' ; + my $transfer_str=''; + my $sink_str=''; + my $crdit_update=''; + my $actor_got_pck_func= " +char ${actor}_got_packet_function( unsigned char iport, unsigned int v){ "; - my $actor_update_credit= " + my $actor_update_credit= " char ${actor}_update_credit (unsigned int credit_port,unsigned int credit_value){ "; - - my $actor_check_pck_func= " + my $actor_check_pck_func= " char ${actor}_check_packet_function (unsigned char iport,unsigned int size){ -"; - - my $actor_sent_pck_done_func= " +"; + my $actor_sent_pck_done_func= " char ${actor}_sent_packet_done_function (unsigned char oport){ -"; - - my $actor_init=" -void ${actor}_init_actor (schedinfo_t * si) { "; - - my $actor_local_connect; - - #schedular function - - $schedul =" - ${actor}_scheduler(si);"; - - #For each actor which is mapped to this tile, we need to find all the traces going in and out to this tile - #1- get the actor generated C file name: - - #push(@actors_file_names, $actor_file); - #2- where it mapped? - # my $actor_tile = $self->object_get_attribute("MAP_TILE",$actor); - # my $actor_tile_id=get_tile_id($self,$actor); - #3- How many traces it transfers? - - my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); - - #4- Where does it transffer? - foreach my $inject (@injectors) { - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,'raw',$inject); - - $vc= 0 if(!defined $vc); - $class= 0 if(!defined $class); - - #my $dst_tile = $self->object_get_attribute("MAP_TILE",$dst_actor); - my $dst_actor=$self->get_item_group_name('grouping',$dst); - my $dst_tile = get_task_give_tile($self,$dst_actor); - #my $dst_tile_id=get_tile_id($self,$dst_actor); - my $dst_tile_id=tile_id_number($dst_tile); - - - if($dst_tile eq $actor_tile){ - # this trace is connected locally in one tile - #my $rr="\t\t${dst}_$dst_port->read_inds[$chanel]= ${src}_${src_port}->write_ind;\n"; - #$actor_local_connect=(defined $actor_local_connect)? $actor_local_connect.$rr:$rr; - next; - } - - #5-Now generate all transfer functions (add inject ports) - #my ($net,$num,$name)=split(':',$actor); - #print "dstp_number{$dst}{$dst_port}= $dstp_number{$dst}{$dst_port};\n"; - - my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel); - my $dstportnum = get_port_num($self,\%dstp_number,$dst,$dst_port); - - - if(!defined $dstportnum){ - print Dumper (\$self); - print Dumper (\%dstp_number); - print "my $dstportnum = get_port_num($self,\%dstp_number,$dst,$dst_port);\n"; - print "***********************fix me**********\n"; - exit(); - } - - - - if($chanel==0){ - $Hw_fifo_define=$Hw_fifo_define." -// transfer ${src_port} port definitions: + my $actor_init=" +void ${actor}_init_actor (schedinfo_t * si) { +"; + my $actor_local_connect; + #schedular function + $schedul =" + ${actor}_scheduler(si);"; + #For each actor which is mapped to this tile, we need to find all the traces going in and out to this tile + #1- get the actor generated C file name: + #push(@actors_file_names, $actor_file); + #2- where it mapped? + # my $actor_tile = $self->object_get_attribute("MAP_TILE",$actor); + # my $actor_tile_id=get_tile_id($self,$actor); + #3- How many traces it transfers? + my @injectors= get_all_source_traces_of_actr($self,$actor,'raw'); + #4- Where does it transffer? + foreach my $inject (@injectors) { + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,'raw',$inject); + $vc= 0 if(!defined $vc); + $class= 0 if(!defined $class); + #my $dst_tile = $self->object_get_attribute("MAP_TILE",$dst_actor); + my $dst_actor=$self->get_item_group_name('grouping',$dst); + my $dst_tile = get_task_give_tile($self,$dst_actor); + #my $dst_tile_id=get_tile_id($self,$dst_actor); + my $dst_tile_id=tile_id_number($dst_tile); + if($dst_tile eq $actor_tile){ + # this trace is connected locally in one tile + #my $rr="\t\t${dst}_$dst_port->read_inds[$chanel]= ${src}_${src_port}->write_ind;\n"; + #$actor_local_connect=(defined $actor_local_connect)? $actor_local_connect.$rr:$rr; + next; + } + #5-Now generate all transfer functions (add inject ports) + #my ($net,$num,$name)=split(':',$actor); + #print "dstp_number{$dst}{$dst_port}= $dstp_number{$dst}{$dst_port};\n"; + my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel); + my $dstportnum = get_port_num($self,\%dstp_number,$dst,$dst_port); + if(!defined $dstportnum){ + print Dumper (\$self); + print Dumper (\%dstp_number); + print "my $dstportnum = get_port_num($self,\%dstp_number,$dst,$dst_port);\n"; + print "***********************fix me**********\n"; + exit(); + } + if($chanel==0){ + $Hw_fifo_define=$Hw_fifo_define." +// transfer ${src_port} port definitions: #define ${src_port}_w $init_weight -#define ${src_port}_v $vc +#define ${src_port}_v $vc #define ${src_port}_class_num $class #define ${src_port}_queue_pointer (unsigned int)&tokens_${src_port}[0] -#define ${src_port}_queue_size_in_byte (SIZE_${src_port} << ${actor}_${src_port}_size_shift) -#define ${src_port}_end_index index_${src_port} - +#define ${src_port}_queue_size_in_byte (SIZE_${src_port} << ${actor}_${src_port}_size_shift) +#define ${src_port}_end_index index_${src_port} "; - - #$actor_init.="\t${actor}_${src_port}->write_ind=0;\n"; - - } - - $Hw_fifo_define=$Hw_fifo_define." -// ${src_port} read chanel ${chanel} definition -#define ${src_port}_ch${chanel}_dest_port_num $dstportnum + #$actor_init.="\t${actor}_${src_port}->write_ind=0;\n"; + } + $Hw_fifo_define=$Hw_fifo_define." +// ${src_port} read chanel ${chanel} definition +#define ${src_port}_ch${chanel}_dest_port_num $dstportnum #define ${src_port}_ch${chanel}_dest_phy_addr PHY_ADDR_ENDP_${dst_tile_id} #define ${src_port}_ch${chanel}_src_port_num $srcportnum #define ${src_port}_ch${chanel}_start_index ${actor}_${src_port}->read_inds[$chanel] #define ${src_port}_ch${chanel}_start_index_in_byte ((${src_port}_ch${chanel}_start_index % SIZE_${src_port}) << ${actor}_${src_port}_size_shift) -#define ${src_port}_ch${chanel}_has_data_to_send (${src_port}_end_index > ${src_port}_ch${chanel}_start_index) -#define ${src_port}_ch${chanel}_data_to_send_size (${src_port}_end_index - ${src_port}_ch${chanel}_start_index) +#define ${src_port}_ch${chanel}_has_data_to_send (${src_port}_end_index > ${src_port}_ch${chanel}_start_index) +#define ${src_port}_ch${chanel}_data_to_send_size (${src_port}_end_index - ${src_port}_ch${chanel}_start_index) #define ${src_port}_ch${chanel}_send_data_size_in_byte (${src_port}_ch${chanel}_data_to_send_size << ${actor}_${src_port}_size_shift) - - -static unsigned int ${src_port}_ch${chanel}_credit = ${src_port}_queue_size_in_byte; +static unsigned int ${src_port}_ch${chanel}_credit = ${src_port}_queue_size_in_byte; static unsigned int ${src_port}_ch${chanel}_send_data; "; #$actor_init.="\t${src_port}_ch${chanel}_credit = ${src_port}_queue_size_in_byte;\n"; - - #$actor_init.="\t${actor}_${src_port}->read_inds[$chanel]=0;\n"; - - $transfer_str=$transfer_str." - if(${src_port}_ch${chanel}_has_data_to_send){ - // if the sent vc is not busy and the sent_done_isr is not asserted sent a new packet - if(${ni_name}_send_is_free(${src_port}_v) && (oport_array[${src_port}_v]==255) ){ //(${ni_name}_packet_is_sent(${src_port}_v)==0)) { - - //ask NI to transfer the data - if(transfer_manage (${src_port}_w, ${src_port}_v, ${src_port}_class_num,${src_port}_ch${chanel}_dest_port_num , ${src_port}_queue_pointer , ${src_port}_queue_size_in_byte, - ${src_port}_ch${chanel}_start_index_in_byte, ${src_port}_ch${chanel}_send_data_size_in_byte, ${src_port}_ch${chanel}_dest_phy_addr, ${src_port}_ch${chanel}_credit,${src_port}_ch${chanel}_src_port_num, & ${src_port}_ch${chanel}_send_data, & ${src_port}_ch${chanel}_credit )){ - - } - }//has data - }//not busy - "; - - $actor_sent_pck_done_func=$actor_sent_pck_done_func." - - if(oport == ${src_port}_ch${chanel}_src_port_num){ - ${src_port}_ch${chanel}_start_index= ${src_port}_ch${chanel}_start_index+ (${src_port}_ch${chanel}_send_data>>${actor}_${src_port}_size_shift); - #ifdef ORCC_DEBUG_EN - if (${src_port}_ch${chanel}_data_to_send_size > SIZE_${src_port}){ - printf (\"Error the waiting data in ${actor} ${src_port} quque (\%u) is larger than the queue size (\%u)\\n\",${src_port}_ch${chanel}_data_to_send_size,SIZE_${src_port} ); - } - #endif - return 1; - } - - "; - - $actor_update_credit =$actor_update_credit." - if( credit_port == ${src_port}_ch${chanel}_src_port_num){ - ${src_port}_ch${chanel}_credit += (credit_value << ${actor}_${src_port}_size_shift); //credit value in byte - #ifdef ORCC_DEBUG_EN - if (${src_port}_ch${chanel}_credit > (SIZE_${src_port} << ${actor}_${src_port}_size_shift )){ - printf (\"Error the credit counter in ${actor} ${src_port}_ch${chanel} (\%u) is larger than the queue size (\%u)\\n\",${src_port}_ch${chanel}_credit,SIZE_${src_port} ); - } - #endif - return 1; - } + #$actor_init.="\t${actor}_${src_port}->read_inds[$chanel]=0;\n"; + $transfer_str=$transfer_str." + if(${src_port}_ch${chanel}_has_data_to_send){ + // if the sent vc is not busy and the sent_done_isr is not asserted sent a new packet + if(${ni_name}_send_is_free(${src_port}_v) && (oport_array[${src_port}_v]==255) ){ //(${ni_name}_packet_is_sent(${src_port}_v)==0)) { + //ask NI to transfer the data + if(transfer_manage (${src_port}_w, ${src_port}_v, ${src_port}_class_num,${src_port}_ch${chanel}_dest_port_num , ${src_port}_queue_pointer , ${src_port}_queue_size_in_byte, + ${src_port}_ch${chanel}_start_index_in_byte, ${src_port}_ch${chanel}_send_data_size_in_byte, ${src_port}_ch${chanel}_dest_phy_addr, ${src_port}_ch${chanel}_credit,${src_port}_ch${chanel}_src_port_num, & ${src_port}_ch${chanel}_send_data, & ${src_port}_ch${chanel}_credit )){ + } + }//has data + }//not busy + "; + $actor_sent_pck_done_func=$actor_sent_pck_done_func." + if(oport == ${src_port}_ch${chanel}_src_port_num){ + ${src_port}_ch${chanel}_start_index= ${src_port}_ch${chanel}_start_index+ (${src_port}_ch${chanel}_send_data>>${actor}_${src_port}_size_shift); + #ifdef ORCC_DEBUG_EN + if (${src_port}_ch${chanel}_data_to_send_size > SIZE_${src_port}){ + printf (\"Error the waiting data in ${actor} ${src_port} quque (\%u) is larger than the queue size (\%u)\\n\",${src_port}_ch${chanel}_data_to_send_size,SIZE_${src_port} ); + } + #endif + return 1; + } + "; + $actor_update_credit =$actor_update_credit." + if( credit_port == ${src_port}_ch${chanel}_src_port_num){ + ${src_port}_ch${chanel}_credit += (credit_value << ${actor}_${src_port}_size_shift); //credit value in byte + #ifdef ORCC_DEBUG_EN + if (${src_port}_ch${chanel}_credit > (SIZE_${src_port} << ${actor}_${src_port}_size_shift )){ + printf (\"Error the credit counter in ${actor} ${src_port}_ch${chanel} (\%u) is larger than the queue size (\%u)\\n\",${src_port}_ch${chanel}_credit,SIZE_${src_port} ); + } + #endif + return 1; + } "; - - }# end inject - - - - - #6-Where the packet comes from? we need to update the sender with the remaining credit - my @sinkers = get_all_dest_traces_of_actr ($self,$actor,'raw'); - foreach my $sink (@sinkers){ - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,'raw',$sink); - - my $dst_chnl =get_dest_chanel_from_orcc_file($actor_file,$actor,$dst_port); - - my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel); - my $src_actor=$self->get_item_group_name('grouping',$src); - my $src_tile = get_task_give_tile($self,$src_actor); - #my $src_tile_id=get_tile_id($self,$src); - my $src_tile_id=tile_id_number($src_tile); - - #print "my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel);\n"; - - if($src_tile eq $actor_tile){ - - next; - } - - if(!defined $srcportnum){ - print Dumper (\$self); - print Dumper (\%srcp_number); - print "my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel);\n"; - print "***********************fix me**********\n"; - exit(); - } - - #7 We need to add sink ports - #save the input port index before running the credit -#$actor_init.=\t${actor}_${dst_port}->read_inds[0]=0; + }# end inject + #6-Where the packet comes from? we need to update the sender with the remaining credit + my @sinkers = get_all_dest_traces_of_actr ($self,$actor,'raw'); + foreach my $sink (@sinkers){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,'raw',$sink); + my $dst_chnl =get_dest_chanel_from_orcc_file($actor_file,$actor,$dst_port); + my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel); + my $src_actor=$self->get_item_group_name('grouping',$src); + my $src_tile = get_task_give_tile($self,$src_actor); + #my $src_tile_id=get_tile_id($self,$src); + my $src_tile_id=tile_id_number($src_tile); + #print "my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel);\n"; + if($src_tile eq $actor_tile){ + next; + } + if(!defined $srcportnum){ + print Dumper (\$self); + print Dumper (\%srcp_number); + print "my $srcportnum = get_port_num($self,\%srcp_number,$src,$src_port,$chanel);\n"; + print "***********************fix me**********\n"; + exit(); + } + #7 We need to add sink ports + #save the input port index before running the credit +#$actor_init.=\t${actor}_${dst_port}->read_inds[0]=0; #$actor_init.=\t${actor}_${dst_port}->write_ind=0; - - $actor_init =$actor_init." + $actor_init =$actor_init." \tread_${dst_port}(); -\tindex_${dst_port}_sender=index_$dst_port; +\tindex_${dst_port}_sender=index_$dst_port; "; - - my $dstportnum = get_port_num($self,\%dstp_number,$dst,$dst_port); - $max_dst_port_num=$dstportnum if($dstportnum > $max_dst_port_num ); - - $Hw_fifo_define=$Hw_fifo_define." -// Receiver port ${dst_port} port definitions: -static unsigned int index_${dst_port}_sender; - + my $dstportnum = get_port_num($self,\%dstp_number,$dst,$dst_port); + $max_dst_port_num=$dstportnum if($dstportnum > $max_dst_port_num ); + $Hw_fifo_define=$Hw_fifo_define." +// Receiver port ${dst_port} port definitions: +static unsigned int index_${dst_port}_sender; #define ${dst_port}_credit_w 1 -#define ${dst_port}_credit_v 0 //Alternatively it can be another VC +#define ${dst_port}_credit_v 0 //Alternatively it can be another VC #define ${dst_port}_credit_class_num 0 //Alternatively it can be another class #define ${dst_port}_credit_dest_port 0 //0 is reserved for credit #define ${dst_port}_credit_pointer (unsigned int)&credit_send_buff @@ -778,854 +577,609 @@ sub genereate_output_orcc{ #define ${dst_port}_src_port_num $srcportnum #define ${dst_port}_dst_port_num $dstportnum #define ${dst_port}_queu_pointer (unsigned int)&tokens_${dst_port}[0] -#define ${dst_port}_queue_size_in_byte (SIZE_${dst_port} << ${actor}_${dst_port}_size_shift) -#define ${dst_port}_start_index_in_byte ((${actor}_${dst_port}->write_ind % SIZE_${dst_port})<< ${actor}_${dst_port}_size_shift) +#define ${dst_port}_queue_size_in_byte (SIZE_${dst_port} << ${actor}_${dst_port}_size_shift) +#define ${dst_port}_start_index_in_byte ((${actor}_${dst_port}->write_ind % SIZE_${dst_port})<< ${actor}_${dst_port}_size_shift) #define ${dst_port}_read_indx ${actor}_${dst_port}->read_inds[$dst_chnl] -#define ${dst_port}_data_num_to_process (${actor}_${dst_port}->write_ind -${dst_port}_read_indx) +#define ${dst_port}_data_num_to_process (${actor}_${dst_port}->write_ind -${dst_port}_read_indx) "; - - - $crdit_update=$crdit_update." - if( ${dst_port}_has_credit_to_send){ - if(${ni_name}_send_is_free(${dst_port}_credit_v) && (oport_array[${dst_port}_credit_v]==255) ){ // (${ni_name}_packet_is_sent(${dst_port}_credit_v)==0)){ - //credit_num = (SIZE_${dst_port} - ${dst_port}_data_num_to_process)& 0xFFFF; - credit_num = (index_$dst_port - index_${dst_port}_sender)& 0xFFFF; - credit_send_buff= ( (${dst_port}_src_port_num <<16) | credit_num ); // most significant 16 bits indicates the port, list significant 16 bits are credit in word - #ifdef ORCC_DEBUG_EN - if(${dst_port}_data_num_to_process > SIZE_${dst_port}){ - printf(\"Error ${dst_port}_data_num_to_process (\%u) is larger than SIZE_${dst_port} (\%u)\\n\",${dst_port}_data_num_to_process,SIZE_${dst_port}); - } - #endif - if( transfer_manage (${dst_port}_credit_w, ${dst_port}_credit_v, ${dst_port}_credit_class_num, ${dst_port}_credit_dest_port, ${dst_port}_credit_pointer, ${dst_port}_credit_size_in_byte, ${dst_port}_credit_start_index, ${dst_port}_credit_send_data_size_in_byte, ${dst_port}_credit_dest_phy_addr, 5,${dst_port}_credit_dest_port, &tmp1,&tmp2 ) ){ - index_${dst_port}_sender=index_${dst_port}; - } - } - } - "; - - $actor_got_pck_func=$actor_got_pck_func." - if (iport == ${dst_port}_dst_port_num){ - ${ni_name}_receive (v, ${dst_port}_queu_pointer , ${dst_port}_queue_size_in_byte, ${dst_port}_start_index_in_byte); - return 1; - } + $crdit_update=$crdit_update." + if( ${dst_port}_has_credit_to_send){ + if(${ni_name}_send_is_free(${dst_port}_credit_v) && (oport_array[${dst_port}_credit_v]==255) ){ // (${ni_name}_packet_is_sent(${dst_port}_credit_v)==0)){ + //credit_num = (SIZE_${dst_port} - ${dst_port}_data_num_to_process)& 0xFFFF; + credit_num = (index_$dst_port - index_${dst_port}_sender)& 0xFFFF; + credit_send_buff= ( (${dst_port}_src_port_num <<16) | credit_num ); // most significant 16 bits indicates the port, list significant 16 bits are credit in word + #ifdef ORCC_DEBUG_EN + if(${dst_port}_data_num_to_process > SIZE_${dst_port}){ + printf(\"Error ${dst_port}_data_num_to_process (\%u) is larger than SIZE_${dst_port} (\%u)\\n\",${dst_port}_data_num_to_process,SIZE_${dst_port}); + } + #endif + if( transfer_manage (${dst_port}_credit_w, ${dst_port}_credit_v, ${dst_port}_credit_class_num, ${dst_port}_credit_dest_port, ${dst_port}_credit_pointer, ${dst_port}_credit_size_in_byte, ${dst_port}_credit_start_index, ${dst_port}_credit_send_data_size_in_byte, ${dst_port}_credit_dest_phy_addr, 5,${dst_port}_credit_dest_port, &tmp1,&tmp2 ) ){ + index_${dst_port}_sender=index_${dst_port}; + } + } + } + "; + $actor_got_pck_func=$actor_got_pck_func." + if (iport == ${dst_port}_dst_port_num){ + ${ni_name}_receive (v, ${dst_port}_queu_pointer , ${dst_port}_queue_size_in_byte, ${dst_port}_start_index_in_byte); + return 1; + } "; - - $actor_check_pck_func =$actor_check_pck_func." - if(iport==${dst_port}_dst_port_num){ - ${actor}_${dst_port}->write_ind = ${actor}_${dst_port}->write_ind + (size >> ${actor}_${dst_port}_size_shift); - #ifdef ORCC_DEBUG_EN - unsigned int diff = ${actor}_${dst_port}->write_ind - ${dst_port}_read_indx; - if(diff > SIZE_${dst_port})\{ - printf (\"Error in ${actor}_${dst_port}: Write_index(\%u) - Read_index(\%u) is larger than queue size (\%u)\\n\",${actor}_${dst_port}->write_ind , ${dst_port}_read_indx,SIZE_${dst_port}); - } - #endif - return 1; - } - "; - - - - - - - #print "\$fifos{\"$name\"}{'file'}=$file_name\n"; - #print "\$fifos ${name}_${dst_port}'size'=$buff_size;\n"; - - - - } #sink - - - - + $actor_check_pck_func =$actor_check_pck_func." + if(iport==${dst_port}_dst_port_num){ + ${actor}_${dst_port}->write_ind = ${actor}_${dst_port}->write_ind + (size >> ${actor}_${dst_port}_size_shift); + #ifdef ORCC_DEBUG_EN + unsigned int diff = ${actor}_${dst_port}->write_ind - ${dst_port}_read_indx; + if(diff > SIZE_${dst_port})\{ + printf (\"Error in ${actor}_${dst_port}: Write_index(\%u) - Read_index(\%u) is larger than queue size (\%u)\\n\",${actor}_${dst_port}->write_ind , ${dst_port}_read_indx,SIZE_${dst_port}); + } + #endif + return 1; + } + "; + #print "\$fifos{\"$name\"}{'file'}=$file_name\n"; + #print "\$fifos ${name}_${dst_port}'size'=$buff_size;\n"; + } #sink $actor_h=$actor_h."void ${actor}_initialize(schedinfo_t *);\n"; -$actor_h=$actor_h."void ${actor}_scheduler(schedinfo_t *);\n"; - -$actor_h=$actor_h."char ${actor}_got_packet_function(unsigned char , unsigned int);\n"; -$all_got_packet_function=$all_got_packet_function."\t\t\t\t${actor}_got_packet_function(iport,i);\n"; +$actor_h=$actor_h."void ${actor}_scheduler(schedinfo_t *);\n"; +$actor_h=$actor_h."char ${actor}_got_packet_function(unsigned char , unsigned int);\n"; +$all_got_packet_function=$all_got_packet_function."\t\t\t\t${actor}_got_packet_function(iport,i);\n"; $actor_got_pck_func=$actor_got_pck_func." - #ifdef ORCC_DEBUG_EN - printf(\"Wrong got pck port \%u\\n\",iport); - #endif - return 0; -} + #ifdef ORCC_DEBUG_EN + printf(\"Wrong got pck port \%u\\n\",iport); + #endif + return 0; +} "; - $actor_h=$actor_h."char ${actor}_check_packet_function(unsigned char,unsigned int);\n"; $all_check_packet_function = $all_check_packet_function."\t\t\t\t${actor}_check_packet_function(iport,size);\n"; $actor_check_pck_func=$actor_check_pck_func." - #ifdef ORCC_DEBUG_EN - printf(\"Wrong check pck port \%u\\n\",iport); - #endif - return 0; -} + #ifdef ORCC_DEBUG_EN + printf(\"Wrong check pck port \%u\\n\",iport); + #endif + return 0; +} "; $actor_h=$actor_h."char ${actor}_sent_packet_done_function(unsigned char);\n"; $all_sent_packet_done_function = $all_sent_packet_done_function."\t\t\t\t${actor}_sent_packet_done_function(oport);\n"; $actor_sent_pck_done_func=$actor_sent_pck_done_func." - #ifdef ORCC_DEBUG_EN - printf(\"Wrong sent done port \%u\\n\",oport); - #endif - return 0; + #ifdef ORCC_DEBUG_EN + printf(\"Wrong sent done port \%u\\n\",oport); + #endif + return 0; } "; $actor_h=$actor_h."char ${actor}_update_credit(unsigned int, unsigned int);\n"; $all_update_credit=$all_update_credit."\t\t\t\t${actor}_update_credit(credit_port,credit_value);\n"; -$actor_update_credit =$actor_update_credit." - #ifdef ORCC_DEBUG_EN - printf(\"Wrong ${actor} Credit port \%u\\n\",credit_port); - #endif - return 0; +$actor_update_credit =$actor_update_credit." + #ifdef ORCC_DEBUG_EN + printf(\"Wrong ${actor} Credit port \%u\\n\",credit_port); + #endif + return 0; } -"; -$actor_h=$actor_h."void ${actor}_init_actor(schedinfo_t *);\n"; -$all_init_actor=$all_init_actor."\t${actor}_init_actor(&si);\n"; +"; +$actor_h=$actor_h."void ${actor}_init_actor(schedinfo_t *);\n"; +$all_init_actor=$all_init_actor."\t${actor}_init_actor(&si);\n"; $actor_init=$actor_init." - - ${actor}_initialize(si); - + ${actor}_initialize(si); } -"; - -$actor_h=$actor_h."void ${actor}_run_actor(schedinfo_t *);\n"; -$all_run_actor=$all_run_actor."\t\t${actor}_run_actor(&si);\n"; +"; +$actor_h=$actor_h."void ${actor}_run_actor(schedinfo_t *);\n"; +$all_run_actor=$all_run_actor."\t\t${actor}_run_actor(&si);\n"; #$all_run_actor=$all_run_actor.$actor_local_connect if(defined $actor_local_connect); - -my $t = (length $crdit_update > 10 )? "unsigned int tmp1,tmp2,credit_num,credit_send_buff;" : ""; - +my $t = (length $crdit_update > 10 )? "unsigned int tmp1,tmp2,credit_num,credit_send_buff;" : ""; my $actor_run=" -void ${actor}_run_actor (schedinfo_t * si) { - - //unsigned int credit_send_buff; - - //run schedular - - +void ${actor}_run_actor (schedinfo_t * si) { + //unsigned int credit_send_buff; + //run schedular $schedul - - //check if input ports have credit update to send - $t - $crdit_update - - //check if output port has data to send - $transfer_str - - #if (ORCC_SENT_DONT_INT_EN == 0) - if(${ni_name}_any_sent_done_isr_is_asserted()) sent_packet_done_function(); - #endif - - #if (ORCC_SAVE_DONT_INT_EN == 0) - if(${ni_name}_any_save_done_isr_is_asserted()) check_packet_function(); - #endif - - #if (ORCC_GOT_PCK_INT_EN == 0) - if(${ni_name}_any_got_pck_isr_is_asserted()) got_packet_function(); - #endif - - #if (ORCC_GOT_ERR_INT_EN == 0) - if(${ni_name}_any_err_isr_is_asserted()) error_handling_function(); - #endif - + //check if input ports have credit update to send + $t + $crdit_update + //check if output port has data to send + $transfer_str + #if (ORCC_SENT_DONT_INT_EN == 0) + if(${ni_name}_any_sent_done_isr_is_asserted()) sent_packet_done_function(); + #endif + #if (ORCC_SAVE_DONT_INT_EN == 0) + if(${ni_name}_any_save_done_isr_is_asserted()) check_packet_function(); + #endif + #if (ORCC_GOT_PCK_INT_EN == 0) + if(${ni_name}_any_got_pck_isr_is_asserted()) got_packet_function(); + #endif + #if (ORCC_GOT_ERR_INT_EN == 0) + if(${ni_name}_any_err_isr_is_asserted()) error_handling_function(); + #endif } "; - - - - - - my $r; - - add_colored_info($tview,"actor name: $actor\n",'green'); - - - - #copy orcc lib files - - my $orcc_lib_dir = get_project_dir()."/mpsoc/src_c/orcc/lib"; - opendir(DIR,"$orcc_lib_dir") or $r= "$!\n"; - if(defined $r) { - add_colored_info($tview,"cannot open directory: $r",'red'); - return; - } - foreach my $name (readdir(DIR)) - { - # add_colored_info($tview,"copy ($orcc_lib_dir/$name,$target_dir/sw/tile${actor_tile_id}/);\n ",'red'); - copy ("$orcc_lib_dir/$name","$target_orccdir/"); - } - - - - - - - - #print $fe "orcc/$fname.c "; - #$main_include=$main_include."#include \"orcc/$fname.c\"\n"; - $main_include=$main_include."#include \"orcc/$fname.h\"\n"; - - $src_lib="$src_lib orcc/$fname.c"; - - print $fc " // Generated from $actor_file\n"; - my $defines=""; - my $pval = $self->object_get_attribute("map_param","add_debug"); - $defines .= ($pval eq '1\'b1')? "#define ORCC_DEBUG_EN\n" : ""; - $pval = $self->object_get_attribute("map_param","sent_int"); - $defines .= ($pval eq '1\'b1')? "#define ORCC_SENT_DONT_INT_EN 1\n" : "#define ORCC_SENT_DONT_INT_EN 0\n"; - $pval = $self->object_get_attribute("map_param","receive_int"); - $defines .= ($pval eq '1\'b1')? "#define ORCC_SAVE_DONT_INT_EN 1\n" : "#define ORCC_SAVE_DONT_INT_EN 0\n"; - $pval = $self->object_get_attribute("map_param","receive_int"); - $defines .= ($pval eq '1\'b1')? "#define ORCC_GOT_PCK_INT_EN 1\n" : "#define ORCC_GOT_PCK_INT_EN 0\n"; - $pval = $self->object_get_attribute("map_param","got_err_int"); - $defines .= ($pval eq '1\'b1')? "#define ORCC_GOT_ERR_INT_EN 1\n" : "#define ORCC_GOT_ERR_INT_EN 0\n"; - - - - print $fc " -#include -#include \"../$soc_name.h\" + my $r; + add_colored_info($tview,"actor name: $actor\n",'green'); + #copy orcc lib files + my $orcc_lib_dir = get_project_dir()."/mpsoc/src_c/orcc/lib"; + opendir(DIR,"$orcc_lib_dir") or $r= "$!\n"; + if(defined $r) { + add_colored_info($tview,"cannot open directory: $r",'red'); + return; + } + foreach my $name (readdir(DIR)) + { + # add_colored_info($tview,"copy ($orcc_lib_dir/$name,$target_dir/sw/tile${actor_tile_id}/);\n ",'red'); + copy ("$orcc_lib_dir/$name","$target_orccdir/"); + } + #print $fe "orcc/$fname.c "; + #$main_include=$main_include."#include \"orcc/$fname.c\"\n"; + $main_include=$main_include."#include \"orcc/$fname.h\"\n"; + $src_lib="$src_lib orcc/$fname.c"; + print $fc " // Generated from $actor_file\n"; + my $defines=""; + my $pval = $self->object_get_attribute("map_param","add_debug"); + $defines .= ($pval eq '1\'b1')? "#define ORCC_DEBUG_EN\n" : ""; + $pval = $self->object_get_attribute("map_param","sent_int"); + $defines .= ($pval eq '1\'b1')? "#define ORCC_SENT_DONT_INT_EN 1\n" : "#define ORCC_SENT_DONT_INT_EN 0\n"; + $pval = $self->object_get_attribute("map_param","receive_int"); + $defines .= ($pval eq '1\'b1')? "#define ORCC_SAVE_DONT_INT_EN 1\n" : "#define ORCC_SAVE_DONT_INT_EN 0\n"; + $pval = $self->object_get_attribute("map_param","receive_int"); + $defines .= ($pval eq '1\'b1')? "#define ORCC_GOT_PCK_INT_EN 1\n" : "#define ORCC_GOT_PCK_INT_EN 0\n"; + $pval = $self->object_get_attribute("map_param","got_err_int"); + $defines .= ($pval eq '1\'b1')? "#define ORCC_GOT_ERR_INT_EN 1\n" : "#define ORCC_GOT_ERR_INT_EN 0\n"; + print $fc " +#include +#include \"../$soc_name.h\" #include \"orcc_lib.h\" #include \"../../phy_addr.h\" #include \"$fname.h\" - - extern volatile unsigned char oport_array [${ni_name}_NUM_VCs]; - "; - - - - my $origen_def=""; - my $origen_fuctions=""; - - - #read actor file name and remove unnecessarily codes. comment every files start with #include and extern - open my $fh, "<", $actor_file or $r = "$!\n"; + my $origen_def=""; + my $origen_fuctions=""; + #read actor file name and remove unnecessarily codes. comment every files start with #include and extern + open my $fh, "<", $actor_file or $r = "$!\n"; if(defined $r) { - add_colored_info($tview,"Could not open $actor_file: $r",'red'); - return; - } - while (my $line = <$fh>) { - chomp $line; - #search for fifo size inside the file - if( $line =~ /^\s*#define\s+SIZE_\w+/){ - #example: #define SIZE_operand_1 32 - my $text = $line; - $text =~ s/\s+/ /g; # remove extra spaces - $text =~ s/^\s+//; #ltrim - my ($fifo_name,$size) = sscanf("#define SIZE_%s %u",$text); - $actor_h = $actor_h."#define SIZE_${actor}_$fifo_name $size\n"; - $fifos{"${actor}_$fifo_name"}{'size'}=$size; - } - - - $line = '//'.$line if( $line =~ /^\s*#include/); # comment every line start with #include - if( $line =~ /^\s*extern\s+/){ - my $extern=0; - $line =~ s/\s+/ /g; # remove extra spaces - $line =~ s/^\s+//; #ltrim - - #fifo - my ($type,$fifo_name) = sscanf("extern fifo_%s_t *%s;",$line); - if(defined $type){ - $extern=1; - if (defined $fifos{$fifo_name}){ - #add fifo definition: - my $size = $fifos{$fifo_name}{'size'}; - #if(!defined $size ){ - $size = "$fifo_name"; - #$size=~ s/^\s*${actor}_//g; - $size = "SIZE_$size"; - #} - - my $fnum = $fifos{"$fifo_name"}{'fifo_num'}; - my $ch_num= $fifos{"$fifo_name"}{'chanel_num'}; - $ch_num =1 if(!defined $ch_num); - - my $src_fifo_name= $self->object_get_attribute("locally_connected","$fifo_name"); - #printf "$src_fifo_name locally connected $fifo_name\n"; - - unless (defined $src_fifo_name){#check if destintion port is not localy connected - - $main_fifo_def=$main_fifo_def . "DECLARE_FIFO(${type}, $size, $fnum, $ch_num);\n"; - } - $main_fifo_assign=$main_fifo_assign . "fifo_${type}_t *$fifo_name = &fifo_$fnum;\n"; - $main_fifo_rst_ptr.="\t${fifo_name}->write_ind=0;\n"; - for (my $c=0; $c<$ch_num; $c++){ - $main_fifo_rst_ptr.="\t${fifo_name}->read_inds[$c]=0;\n" - } - - $origen_fuctions= $origen_fuctions . "$line \n"; - - #$main_fifo_rst_ptr.="\t printf(\"${fifo_name}_addr=%u\\n\", &${fifo_name}->contents[0]);\n"; - - my $shift = - ($type eq "i8" || $type eq "u8") ? 0 : - ($type eq "i16" || $type eq "u16") ? 1 : - ($type eq "i32" || $type eq "u32") ? 2 : - ($type eq "i64" || $type eq "u64") ? 3 : "undef_type check orcc.pl"; - - $origen_def=$origen_def. "#define ${fifo_name}_size_shift $shift \n"; - - - - }else{ - print Dumper(\%fifos); - add_colored_info($tview,"Could not find $fifo_name in csv file\n",'red'); - return; - } - } - - #connection_t - my ($connect_name) = sscanf("extern connection_t %s;",$line); - if(defined $connect_name ){ - $extern=1; - $main_def=$main_def . " connection_t $connect_name = {0, 0, 0, 0};// We dont need connection as they are done in hardware. just define to prevent error\n"; - $origen_fuctions= $origen_fuctions . "$line \n"; - } - - - #actor_t - my ($actor_name) = sscanf("extern actor_t %s;",$line); - if(defined $actor_name ){ - $extern=1; - if (defined $fifos{"$actor_name"}{'file'}){ - # print "===============================================================\n"; - #add actor definition - #search in network.c file for actor definition - my $csv=$fifos{"$actor_name"}{'file'}; - my ($fname,$path,$suffix) = fileparse("$csv",qr"\..[^.]*$"); - my $net= "$path/${fname}.c"; - - my @lines = get_line_have_string($net,"actor_t $actor_name",$tview); - if(defined $lines[0]){ - - #print $fd "void ${actor_name}_initialize(schedinfo_t *);\n"; - #print $fd "void ${actor_name}_scheduler (schedinfo_t *);\n"; - #print $fd "$lines[0]\n"; - $origen_fuctions= $origen_fuctions . "$line \n"; - $actors_str=$actors_str."$lines[0]\n" if($actor_name eq $actor); - } - - } - - - } - - $line= "//$line\n" ; # comment every files start with extern - add_colored_info($tview,"The Auto generator does not know how to define this extern definition:\n $line \n",'red') if($extern == 0); - $origen_fuctions = $origen_fuctions. "$line\n"; - }#extern - elsif( $line =~ /^\s?#define\s+/){ - $origen_def=$origen_def. "$line\n"; - }else{ - $origen_fuctions = $origen_fuctions. "$line\n"; - } - - } - - - -print $fc " + add_colored_info($tview,"Could not open $actor_file: $r",'red'); + return; + } + while (my $line = <$fh>) { + chomp $line; + #search for fifo size inside the file + if( $line =~ /^\s*#define\s+SIZE_\w+/){ + #example: #define SIZE_operand_1 32 + my $text = $line; + $text =~ s/\s+/ /g; # remove extra spaces + $text =~ s/^\s+//; #ltrim + my ($fifo_name,$size) = sscanf("#define SIZE_%s %u",$text); + $actor_h = $actor_h."#define SIZE_${actor}_$fifo_name $size\n"; + $fifos{"${actor}_$fifo_name"}{'size'}=$size; + } + $line = '//'.$line if( $line =~ /^\s*#include/); # comment every line start with #include + if( $line =~ /^\s*extern\s+/){ + my $extern=0; + $line =~ s/\s+/ /g; # remove extra spaces + $line =~ s/^\s+//; #ltrim + #fifo + my ($type,$fifo_name) = sscanf("extern fifo_%s_t *%s;",$line); + if(defined $type){ + $extern=1; + if (defined $fifos{$fifo_name}){ + #add fifo definition: + my $size = $fifos{$fifo_name}{'size'}; + #if(!defined $size ){ + $size = "$fifo_name"; + #$size=~ s/^\s*${actor}_//g; + $size = "SIZE_$size"; + #} + my $fnum = $fifos{"$fifo_name"}{'fifo_num'}; + my $ch_num= $fifos{"$fifo_name"}{'chanel_num'}; + $ch_num =1 if(!defined $ch_num); + my $src_fifo_name= $self->object_get_attribute("locally_connected","$fifo_name"); + #printf "$src_fifo_name locally connected $fifo_name\n"; + unless (defined $src_fifo_name){#check if destintion port is not localy connected + $main_fifo_def=$main_fifo_def . "DECLARE_FIFO(${type}, $size, $fnum, $ch_num);\n"; + } + $main_fifo_assign=$main_fifo_assign . "fifo_${type}_t *$fifo_name = &fifo_$fnum;\n"; + $main_fifo_rst_ptr.="\t${fifo_name}->write_ind=0;\n"; + for (my $c=0; $c<$ch_num; $c++){ + $main_fifo_rst_ptr.="\t${fifo_name}->read_inds[$c]=0;\n" + } + $origen_fuctions= $origen_fuctions . "$line \n"; + #$main_fifo_rst_ptr.="\t printf(\"${fifo_name}_addr=%u\\n\", &${fifo_name}->contents[0]);\n"; + my $shift = + ($type eq "i8" || $type eq "u8") ? 0 : + ($type eq "i16" || $type eq "u16") ? 1 : + ($type eq "i32" || $type eq "u32") ? 2 : + ($type eq "i64" || $type eq "u64") ? 3 : "undef_type check orcc.pl"; + $origen_def=$origen_def. "#define ${fifo_name}_size_shift $shift \n"; + }else{ + print Dumper(\%fifos); + add_colored_info($tview,"Could not find $fifo_name in csv file\n",'red'); + return; + } + } + #connection_t + my ($connect_name) = sscanf("extern connection_t %s;",$line); + if(defined $connect_name ){ + $extern=1; + $main_def=$main_def . " connection_t $connect_name = {0, 0, 0, 0};// We dont need connection as they are done in hardware. just define to prevent error\n"; + $origen_fuctions= $origen_fuctions . "$line \n"; + } + #actor_t + my ($actor_name) = sscanf("extern actor_t %s;",$line); + if(defined $actor_name ){ + $extern=1; + if (defined $fifos{"$actor_name"}{'file'}){ + # print "===============================================================\n"; + #add actor definition + #search in network.c file for actor definition + my $csv=$fifos{"$actor_name"}{'file'}; + my ($fname,$path,$suffix) = fileparse("$csv",qr"\..[^.]*$"); + my $net= "$path/${fname}.c"; + my @lines = get_line_have_string($net,"actor_t $actor_name",$tview); + if(defined $lines[0]){ + #print $fd "void ${actor_name}_initialize(schedinfo_t *);\n"; + #print $fd "void ${actor_name}_scheduler (schedinfo_t *);\n"; + #print $fd "$lines[0]\n"; + $origen_fuctions= $origen_fuctions . "$line \n"; + $actors_str=$actors_str."$lines[0]\n" if($actor_name eq $actor); + } + } + } + $line= "//$line\n" ; # comment every files start with extern + add_colored_info($tview,"The Auto generator does not know how to define this extern definition:\n $line \n",'red') if($extern == 0); + $origen_fuctions = $origen_fuctions. "$line\n"; + }#extern + elsif( $line =~ /^\s?#define\s+/){ + $origen_def=$origen_def. "$line\n"; + }else{ + $origen_fuctions = $origen_fuctions. "$line\n"; + } + } +print $fc " $origen_def - -$Hw_fifo_define - - -$origen_fuctions - +$Hw_fifo_define +$origen_fuctions $actor_got_pck_func - $actor_update_credit - $actor_check_pck_func - $actor_sent_pck_done_func - - - $actor_run - - - $actor_init - -"; - - - close($fc); - - $actor_h.="$defines - unsigned int transfer_manage (unsigned int, unsigned int, unsigned int, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned char, unsigned int *, unsigned int *); - void got_packet_function(void); - void check_packet_function (void); - void sent_packet_done_function (void); - void error_handling_function (void); +"; + close($fc); + $actor_h.="$defines + unsigned int transfer_manage (unsigned int, unsigned int, unsigned int, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned char, unsigned int *, unsigned int *); + void got_packet_function(void); + void check_packet_function (void); + void sent_packet_done_function (void); + void error_handling_function (void); #endif "; - open my $fp, ">$target_actor_header" or $r = "$!\n"; - if(defined $r) { - add_colored_info($tview,"Could not open $target_actor_header to write: $r",'red'); - return; - } - print $fp $actor_h; - close($fp); - - - - } - - - - - - my $got_pck_func= " + open my $fp, ">$target_actor_header" or $r = "$!\n"; + if(defined $r) { + add_colored_info($tview,"Could not open $target_actor_header to write: $r",'red'); + return; + } + print $fp $actor_h; + close($fp); + } + my $got_pck_func= " void got_packet_function(void){ - unsigned int i ; - unsigned char iport; - for (i=0;i<${ni_name}_NUM_VCs;i++){ - if((${ni_name}_got_packet(i)) && (iport_array[i]==255) && ni_receive_is_free(i) ) { - - iport =${ni_name}_RECEIVE_PRECAP_DATA_REG(i); - iport_array[i]=iport; - if(iport==0){ //a credit update packet is recived; - ${ni_name}_receive (i, (unsigned int)& credit_buff[i] , 4, 0); - }else{ + unsigned int i ; + unsigned char iport; + for (i=0;i<${ni_name}_NUM_VCs;i++){ + if((${ni_name}_got_packet(i)) && (iport_array[i]==255) && ni_receive_is_free(i) ) { + iport =${ni_name}_RECEIVE_PRECAP_DATA_REG(i); + iport_array[i]=iport; + if(iport==0){ //a credit update packet is recived; + ${ni_name}_receive (i, (unsigned int)& credit_buff[i] , 4, 0); + }else{ $all_got_packet_function - } - ${ni_name}_ack_got_pck_isr(i); - }//If ${ni_name} got packet - }//for + } + ${ni_name}_ack_got_pck_isr(i); + }//If ${ni_name} got packet + }//for }// got_packet_function - -"; - - - - - my $sent_packet_done_function = " - +"; + my $sent_packet_done_function = " void sent_packet_done_function (void){ - unsigned char oport; - unsigned int i; - for (i=0;i<${ni_name}_NUM_VCs;i++){ - if(${ni_name}_packet_is_sent(i)) { - oport= oport_array[i]; - if(oport==0){ // a credit update packet has sent out - - }else{ + unsigned char oport; + unsigned int i; + for (i=0;i<${ni_name}_NUM_VCs;i++){ + if(${ni_name}_packet_is_sent(i)) { + oport= oport_array[i]; + if(oport==0){ // a credit update packet has sent out + }else{ $all_sent_packet_done_function - } - oport_array[i]=255; - ${ni_name}_ack_send_done_isr(i); - }//If ${ni_name}_packet_is_sent - }//for -}//sent_packet_done_function - + } + oport_array[i]=255; + ${ni_name}_ack_send_done_isr(i); + }//If ${ni_name}_packet_is_sent + }//for +}//sent_packet_done_function "; - - - - my $check_pck_func =" - + my $check_pck_func =" void check_packet_function (void){ - unsigned char iport; - unsigned int i ,size ; - unsigned int credit_value,credit_port; - #ifdef ORCC_DEBUG_EN - struct SRC_INFOS src_info; - #endif - for (i=0;i<${ni_name}_NUM_VCs;i++){ - if(${ni_name}_packet_is_saved(i)) { - - size=${ni_name}_RECEIVE_DATA_SIZE_REG(i); //size in byte - iport= iport_array[i]; - - #ifdef ORCC_DEBUG_EN - src_info=get_src_info(i); - if(iport != src_info.r) printf (\"Error: iport missmatch \%u != \%u \\n\",iport, src_info.r ); - #endif - - iport_array[i]=255; - - if(iport==0){ // a credit update packet has been received - credit_port = credit_buff[i] >> 16; //output port num - credit_value = (credit_buff[i] & 0xFFFF); // credit value in word + unsigned char iport; + unsigned int i ,size ; + unsigned int credit_value,credit_port; + #ifdef ORCC_DEBUG_EN + struct SRC_INFOS src_info; + #endif + for (i=0;i<${ni_name}_NUM_VCs;i++){ + if(${ni_name}_packet_is_saved(i)) { + size=${ni_name}_RECEIVE_DATA_SIZE_REG(i); //size in byte + iport= iport_array[i]; + #ifdef ORCC_DEBUG_EN + src_info=get_src_info(i); + if(iport != src_info.r) printf (\"Error: iport missmatch \%u != \%u \\n\",iport, src_info.r ); + #endif + iport_array[i]=255; + if(iport==0){ // a credit update packet has been received + credit_port = credit_buff[i] >> 16; //output port num + credit_value = (credit_buff[i] & 0xFFFF); // credit value in word $all_update_credit - }else{ + }else{ $all_check_packet_function - } - ${ni_name}_ack_save_done_isr(i); - }//If ${ni_name}_packet_is_saved - }//for + } + ${ni_name}_ack_save_done_isr(i); + }//If ${ni_name}_packet_is_saved + }//for }// check_packet_function - -"; - +"; my $ni_isr=' - /* transfer_manage - w: initial weight - v: Virtual chanel number - class_num: message class number - dest_port: destination queue number - queue_pointer: address in byte - queue_size: queue size in byte - start_index: start index byte number - end_index: end index byte number - dest_phy_addr - credit: Number of byte available in destination queue + w: initial weight + v: Virtual chanel number + class_num: message class number + dest_port: destination queue number + queue_pointer: address in byte + queue_size: queue size in byte + start_index: start index byte number + end_index: end index byte number + dest_phy_addr + credit: Number of byte available in destination queue */ - - - unsigned int transfer_manage (unsigned int w, unsigned int v, unsigned int class_num, unsigned char dest_port, unsigned int queue_pointer,unsigned int queue_size, unsigned int start_index, unsigned int send_data_size_in_byte, unsigned int dest_phy_addr,unsigned int credit, unsigned char port_num, unsigned int * sent_dat_size, unsigned int * dest_credit_size){ - - - unsigned int start_addr_pointer; - unsigned int data_size=send_data_size_in_byte; + unsigned int start_addr_pointer; + unsigned int data_size=send_data_size_in_byte; '; - $ni_isr=$ni_isr." if (${ni_name}_send_is_busy(v)) return 0 ; // if VC is busy sending previous packet do nothing - "; - $ni_isr=$ni_isr.' - if(credit==0) return 0; + if(credit==0) return 0; if(data_size==0) return 0; start_addr_pointer = queue_pointer + start_index; if(data_size > credit) data_size = credit; // we dont want to send more data than the receiver credit - if((start_index + data_size) > queue_size) data_size = queue_size-start_index; // we only send data until end of the queue. The rest will be sent in next round starting from beginning of the queue - if(data_size==0) return 0; + if((start_index + data_size) > queue_size) data_size = queue_size-start_index; // we only send data until end of the queue. The rest will be sent in next round starting from beginning of the queue + if(data_size==0) return 0; '; - -$ni_isr=$ni_isr." - oport_array[v]= port_num; // port_num and data size should be saved before calling transfer function. - * sent_dat_size = data_size; - * dest_credit_size -= data_size; - ${ni_name}_transfer (w, v, class_num, dest_port , start_addr_pointer, data_size, dest_phy_addr); - return 1; -} - - - - - - - +$ni_isr=$ni_isr." + oport_array[v]= port_num; // port_num and data size should be saved before calling transfer function. + * sent_dat_size = data_size; + * dest_credit_size -= data_size; + ${ni_name}_transfer (w, v, class_num, dest_port , start_addr_pointer, data_size, dest_phy_addr); + return 1; +} void error_handling_function(){ - unsigned int i; - for (i=0;i<${ni_name}_NUM_VCs;i++){ - if(${ni_name}_got_buff_ovf(i)) { - printf (\"VC%u:The receiver allocated buffer size is smaller than the received packet size in core\%u\\n\",i,COREID); - ${ni_name}_ack_buff_ovf_isr(i); - } - if(${ni_name}_got_send_dsize_err(i)) { - printf (\"VC%u:The send data size is not set in core\%u\\n\",i,COREID); - ${ni_name}_ack_send_dsize_err_isr(i); - } - if(${ni_name}_got_burst_size_err(i)){ - printf (\"VC%u:The burst size is not set in core\%u\\n\",i,COREID); - ${ni_name}_ack_burst_size_err_isr(i); - } - if(${ni_name}_got_invalid_send_req(i)){ - printf( \"VC%u:A new send request is received while the DMA is still busy sending previous packet in core\%u\\n\",i,COREID); - ${ni_name}_ack_invalid_send_req_isr(i); - } - if(${ni_name}_got_crc_mismatch(i)){ - printf( \"VC%u:CRC miss-matched in core\%u\\n\",i,COREID); - ${ni_name}_ack_crc_mismatch_isr(i); - } - }//for -}//error_handle - - - - - + unsigned int i; + for (i=0;i<${ni_name}_NUM_VCs;i++){ + if(${ni_name}_got_buff_ovf(i)) { + printf (\"VC%u:The receiver allocated buffer size is smaller than the received packet size in core\%u\\n\",i,COREID); + ${ni_name}_ack_buff_ovf_isr(i); + } + if(${ni_name}_got_send_dsize_err(i)) { + printf (\"VC%u:The send data size is not set in core\%u\\n\",i,COREID); + ${ni_name}_ack_send_dsize_err_isr(i); + } + if(${ni_name}_got_burst_size_err(i)){ + printf (\"VC%u:The burst size is not set in core\%u\\n\",i,COREID); + ${ni_name}_ack_burst_size_err_isr(i); + } + if(${ni_name}_got_invalid_send_req(i)){ + printf( \"VC%u:A new send request is received while the DMA is still busy sending previous packet in core\%u\\n\",i,COREID); + ${ni_name}_ack_invalid_send_req_isr(i); + } + if(${ni_name}_got_crc_mismatch(i)){ + printf( \"VC%u:CRC miss-matched in core\%u\\n\",i,COREID); + ${ni_name}_ack_crc_mismatch_isr(i); + } + }//for +}//error_handle void ${ni_name}_isr(void){ - //place your interrupt code here - #if (ORCC_GOT_ERR_INT_EN == 1) - if(${ni_name}_any_err_isr_is_asserted() ){ - // An error ocure - error_handling_function(); - } - #endif - - #if (ORCC_SENT_DONT_INT_EN == 1) - if( ${ni_name}_any_sent_done_isr_is_asserted() ){ - //check which VC has finished sending the packet. - sent_packet_done_function(); - } - #endif - - #if (ORCC_GOT_PCK_INT_EN == 1 || ORCC_SAVE_DONT_INT_EN ==1) - // regardless of ORCC_SAVE_DONT_INT_EN we need to check if the fifo pointer has been updated with last packet data size before sending save command for new packet to NI. - if( ${ni_name}_any_save_done_isr_is_asserted()){ - //check which VC has finished saving the packet. This function must be called before got_packet_function - check_packet_function(); - } - #endif - - #if (ORCC_GOT_PCK_INT_EN == 1) - if(${ni_name}_any_got_pck_isr_is_asserted() ){ - //check which VC got packet - got_packet_function(); - } - #endif - - - - return; + //place your interrupt code here + #if (ORCC_GOT_ERR_INT_EN == 1) + if(${ni_name}_any_err_isr_is_asserted() ){ + // An error ocure + error_handling_function(); + } + #endif + #if (ORCC_SENT_DONT_INT_EN == 1) + if( ${ni_name}_any_sent_done_isr_is_asserted() ){ + //check which VC has finished sending the packet. + sent_packet_done_function(); + } + #endif + #if (ORCC_GOT_PCK_INT_EN == 1 || ORCC_SAVE_DONT_INT_EN ==1) + // regardless of ORCC_SAVE_DONT_INT_EN we need to check if the fifo pointer has been updated with last packet data size before sending save command for new packet to NI. + if( ${ni_name}_any_save_done_isr_is_asserted()){ + //check which VC has finished saving the packet. This function must be called before got_packet_function + check_packet_function(); + } + #endif + #if (ORCC_GOT_PCK_INT_EN == 1) + if(${ni_name}_any_got_pck_isr_is_asserted() ){ + //check which VC got packet + got_packet_function(); + } + #endif + return; } - - "; - - -my $v_val= $self->object_get_attribute('noc_param','V'); + "; +my $v_val= $self->object_get_attribute('noc_param','V'); my $opr =''; for (my $i=0;$i<$v_val; $i++){ - $opr = $opr."\toport_array[$i]=255;\n"; - $opr = $opr."\tiport_array[$i]=255;\n"; -} - + $opr = $opr."\toport_array[$i]=255;\n"; + $opr = $opr."\tiport_array[$i]=255;\n"; +} $main_fifo_rst_ptr.= "$opr -}\n"; - - -my $main=" +}\n"; +my $main=" int main(){ - schedinfo_t si; - reset_all_fifo_ptr(); -$all_init_actor - general_int_init(); - general_int_add(${ni_name}_INT_PIN, ${ni_name}_isr, 0); //${ni_name}_INT_PIN - // Enable ${ni_name} interrupt (its connected to interrupt pin 0) - general_int_enable(${ni_name}_INT_PIN); - general_cpu_int_en(); - // hw interrupt enable function: - // ${ni_name}_initial (burst_size, errors_int_en, send_int_en, save_int_en, got_pck_int_en) - ${ni_name}_initial (16,ORCC_GOT_ERR_INT_EN,ORCC_SENT_DONT_INT_EN,ORCC_SAVE_DONT_INT_EN,ORCC_GOT_PCK_INT_EN); - - delay(100); - while(1){ + schedinfo_t si; + reset_all_fifo_ptr(); +$all_init_actor + general_int_init(); + general_int_add(${ni_name}_INT_PIN, ${ni_name}_isr, 0); //${ni_name}_INT_PIN + // Enable ${ni_name} interrupt (its connected to interrupt pin 0) + general_int_enable(${ni_name}_INT_PIN); + general_cpu_int_en(); + // hw interrupt enable function: + // ${ni_name}_initial (burst_size, errors_int_en, send_int_en, save_int_en, got_pck_int_en) + ${ni_name}_initial (16,ORCC_GOT_ERR_INT_EN,ORCC_SENT_DONT_INT_EN,ORCC_SAVE_DONT_INT_EN,ORCC_GOT_PCK_INT_EN); + delay(100); + while(1){ $all_run_actor - } - return 0; -} - -"; - -my $log2=log2($max_dst_port_num +1); - -print $fd " + } + return 0; +} +"; +my $log2=log2($max_dst_port_num +1); +print $fd " $main_include - -#define MAX_DST_PORT_NUM $max_dst_port_num - -// make sure that the HDATA_PRECAPw widh is >= log2(MAX_DST_PORT_NUM) +#define MAX_DST_PORT_NUM $max_dst_port_num +// make sure that the HDATA_PRECAPw widh is >= log2(MAX_DST_PORT_NUM) #if ( $log2 > ${ni_name}_HDATA_PRECAPw ) - #error \" The value of HDATA_PRECAPw should be defined at least $log2. Open the processing tile generator and increase the NI HDATA_PRECAPw value >= $log2\" + #error \" The value of HDATA_PRECAPw should be defined at least $log2. Open the processing tile generator and increase the NI HDATA_PRECAPw value >= $log2\" #endif - -//make dure Byte_En is asserted in NI +//make dure Byte_En is asserted in NI #if (${ni_name}_BYTE_EN == 0) - #error \" The NI NI BYTE_EN parameter should be set as one for correct data comminication between cores. \" + #error \" The NI NI BYTE_EN parameter should be set as one for correct data comminication between cores. \" #endif - - // a simple delay function - void delay ( unsigned int num ){ - - while (num>0){ - num--; - nop(); // asm volatile (\"nop\"); - } - return; - + while (num>0){ + num--; + nop(); // asm volatile (\"nop\"); + } + return; } - - $actors_str - $main_fifo_def - $main_fifo_assign - $main_fifo_rst_ptr - $main_def - - - - -$got_pck_func - -$check_pck_func - -$sent_packet_done_function - +$got_pck_func +$check_pck_func +$sent_packet_done_function $ni_isr - $main - "; - - - - close($fd); - - - save_file($src_lib_file,$src_lib); - - - - - add_colored_info($tview,"$main_c file has been created successfully from @actors_file_names file \n",'blue'); - - } #actor - - - #done - message_dialog("The source files have been generated successfully"); - #print Dumper (\$self); + add_colored_info($tview,"$main_c file has been created successfully from @actors_file_names file \n",'blue'); + } #actor + #done + message_dialog("The source files have been generated successfully"); + #print Dumper (\$self); } #end sub - - - sub get_line_have_string{ - my ($file,$str,$tview)=@_; - my $r; - my @matches; - open my $fh, "<", $file or $r = "$!\n"; + my ($file,$str,$tview)=@_; + my $r; + my @matches; + open my $fh, "<", $file or $r = "$!\n"; if(defined $r) { - add_colored_info($tview,"Could not open $file: $r",'red'); - return; - } + add_colored_info($tview,"Could not open $file: $r",'red'); + return; + } while (my $line = <$fh>) { - chomp $line; - $line =~ s/\s+/ /g; # remove extra spaces - $line =~ s/^\s+//; #ltrim - if ($line =~ /$str/){ - push(@matches,$line); - } - + chomp $line; + $line =~ s/\s+/ /g; # remove extra spaces + $line =~ s/^\s+//; #ltrim + if ($line =~ /$str/){ + push(@matches,$line); + } } - return @matches; -} + return @matches; +} sub get_destport_constant_list{ - my ($self,$category)=@_; - my %destport_const; - #1- Get list of all actors - my @actors= get_all_tasks($self,$category); - foreach my $actor (@actors){ - - my $i=1; - #2- for each actor get the list of all input ports - my @sinkers= get_all_dest_traces_of_actr($self,$actor,$category); - #3- number each source port of this actor - foreach my $sink (@sinkers){ - - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,$category,$sink); - - $destport_const{$actor}{$dst_port}= $i; - #print "destport_const{$actor}{$dst_port}= $i;\n"; - $i++; - } - } - return %destport_const; + my ($self,$category)=@_; + my %destport_const; + #1- Get list of all actors + my @actors= get_all_tasks($self,$category); + foreach my $actor (@actors){ + my $i=1; + #2- for each actor get the list of all input ports + my @sinkers= get_all_dest_traces_of_actr($self,$actor,$category); + #3- number each source port of this actor + foreach my $sink (@sinkers){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,$category,$sink); + $destport_const{$actor}{$dst_port}= $i; + #print "destport_const{$actor}{$dst_port}= $i;\n"; + $i++; + } + } + return %destport_const; } - - - sub get_srcport_constant_list{ - my ($self,$category)=@_; - my %srcport_const; - #1- Get list of all actors - my @actors= get_all_tasks($self,$category); - #print "@actors\n**************************************************"; - foreach my $actor (@actors){ - - my $i=1; - #2- for each actor get the list of all output ports - my @injectors= get_all_source_traces_of_actr($self,$actor,$category); - #3- number each source port of this actor - foreach my $inject (@injectors){ - - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class - )=get_trace($self,$category,$inject); - - $srcport_const{$actor}{$src_port}{$chanel}= $i; - $i++; - } - } - return %srcport_const; + my ($self,$category)=@_; + my %srcport_const; + #1- Get list of all actors + my @actors= get_all_tasks($self,$category); + #print "@actors\n**************************************************"; + foreach my $actor (@actors){ + my $i=1; + #2- for each actor get the list of all output ports + my @injectors= get_all_source_traces_of_actr($self,$actor,$category); + #3- number each source port of this actor + foreach my $inject (@injectors){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var,$src_port,$dst_port,$buff_size,$chanel,$vc,$class + )=get_trace($self,$category,$inject); + $srcport_const{$actor}{$src_port}{$chanel}= $i; + $i++; + } + } + return %srcport_const; } - - - - sub get_all_dest_traces_of_actr{ - my ($self,$actor,$category)=@_; - my @traces =get_trace_list($self,$category); - my @sources; - foreach my $p (@traces){ - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var)=get_trace($self,$category,$p); - push (@sources,$p) if($dst eq $actor); - } - return @sources; + my ($self,$actor,$category)=@_; + my @traces =get_trace_list($self,$category); + my @sources; + foreach my $p (@traces){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var)=get_trace($self,$category,$p); + push (@sources,$p) if($dst eq $actor); + } + return @sources; } sub get_all_source_traces_of_actr{ - my ($self,$actor,$category)=@_; - my @traces =get_trace_list($self,$category); - my @dests; - foreach my $p (@traces){ - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var)=get_trace($self,$category,$p); - push (@dests,$p) if($src eq $actor); - } - return @dests; -} + my ($self,$actor,$category)=@_; + my @traces =get_trace_list($self,$category); + my @dests; + foreach my $p (@traces){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var)=get_trace($self,$category,$p); + push (@dests,$p) if($src eq $actor); + } + return @dests; +} sub get_actr_file_name { - my ($self,$actor,$category)=@_; - my @traces =get_trace_list($self,$category); - foreach my $p (@traces){ - my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var)=get_trace($self,$category,$p); - if($src eq $actor || $dst eq $actor){ - #the actor supposed to be located next to CSV file and have the same file name as actor name - my ($fname,$path,$suffix) = fileparse("$file_name",qr"\..[^.]*$"); - #my ($net,$num,$name)=split(':',$actor); - return "$path/${actor}.c"; - } - } - return undef; + my ($self,$actor,$category)=@_; + my @traces =get_trace_list($self,$category); + foreach my $p (@traces){ + my ($src,$dst, $Mbytes, $file_id, $file_name,$init_weight,$min_pck, $max_pck, $burst, $injct_rate, $injct_rate_var)=get_trace($self,$category,$p); + if($src eq $actor || $dst eq $actor){ + #the actor supposed to be located next to CSV file and have the same file name as actor name + my ($fname,$path,$suffix) = fileparse("$file_name",qr"\..[^.]*$"); + #my ($net,$num,$name)=split(':',$actor); + return "$path/${actor}.c"; + } + } + return undef; } - - - - - - - - - - - - - - - - - 1; diff --git a/mpsoc/perl_gui/lib/perl/phy_noc_gen.pl b/mpsoc/perl_gui/lib/perl/phy_noc_gen.pl index de37a95..3bd370d 100644 --- a/mpsoc/perl_gui/lib/perl/phy_noc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/phy_noc_gen.pl @@ -2,31 +2,26 @@ use strict; use warnings; use constant::boolean; - use Cwd 'abs_path'; use base 'Class::Accessor::Fast'; -require "widget.pl"; +require "widget.pl"; require "diagram.pl"; require "topology_verilog_gen.pl"; - use String::Scanf; # imports sscanf() - use FindBin; use lib $FindBin::Bin; use tsort; - use File::Basename; use Cwd 'abs_path'; __PACKAGE__->mk_accessors(qw{ window - sourceview + sourceview }); my $NAME = 'phy_noc_maker'; exit phy_noc_maker_main() unless caller; - sub phy_noc_maker_main { my $app = __PACKAGE__->new(); my $table=$app->build_phy_noc_gui(); @@ -39,11 +34,7 @@ sub get_noc_num_page { my $scrolled_win = gen_scr_win_with_adjst ($self,"noc${noc_num}_setting_gui"); add_widget_to_scrolled_win($table,$scrolled_win); my $row=noc_config ($self,$table,$info,$noc_num); - - return $scrolled_win; - - } my @pages=(); @@ -54,73 +45,63 @@ sub gen_notebook_phy { my $notebook = gen_notebook(); $notebook->set_tab_pos ('left'); $notebook->set_scrollable(TRUE); - for (my $i=0;$i<$phys;$i++){ $pages[$i]=get_noc_num_page($self,$i,$info); $page_wins[$i] = add_widget_to_scrolled_win($pages[$i]); $notebook->append_page ($page_wins[$i],gen_label_in_center (" NoC $i")); } - - $notebook->signal_connect( 'switch-page'=> sub{ # rebulid the current page + $notebook->signal_connect( 'switch-page'=> sub{ # rebulid the current page $self->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber - set_gui_status($self,"ref",1); - }); - + set_gui_status($self,"ref",1); + }); return $notebook; } - ############# # load_phy ############# - sub load_phy{ my ($soc,$info,$ip)=@_; my $file; - my $dialog = gen_file_dialog (undef, 'phy'); + my $dialog = gen_file_dialog (undef, 'phy'); my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/multi_nocs"); - - + $dialog->set_current_folder ("$dir/lib/multi_nocs"); if ( "ok" eq $dialog->run ) { $file = $dialog->get_filename; my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); if($suffix eq '.phy'){ my ($pp,$r,$err) = regen_object($file); - if ($r || !defined $pp){ + if ($r || !defined $pp){ show_info($info,"**Error reading $file file: $err\n"); $dialog->destroy; return; - } + } clone_obj($soc,$pp); - set_gui_status($soc,"load_file",0); - } + set_gui_status($soc,"load_file",0); + } } $dialog->destroy; } - sub generate_phynocs{ - my ($self,$info)=@_; + my ($self,$info)=@_; my $name=$self->object_get_attribute('phy_name'); return 0 if (check_mpsoc_name($name,$info,"Phy NoCs")); #make target dir my $pronoc_dir = get_project_dir(); #mpsoc dir addr my $target_dir= "$ENV{PRONOC_WORK}/src_phy_nocs/$name"; my $phys= $self->object_get_attribute('phy_num'); - - my $ports1=""; my $ports2=""; my $imports=""; my $nocs=""; my $flist1=perl_file_header("phy_nocs.flist"); my $flist2=""; - #create a unique verilog modules for each NoC + #create a unique verilog modules for each NoC for (my $i=0;$i<$phys;$i++){ my $append="N$i"; add_info($info,"Generating NoC$i Rtl code ...\n"); - mkpath("$target_dir/noc$i",1,0755); + mkpath("$target_dir/noc$i",1,0755); my $cmd = "perl $pronoc_dir/mpsoc/script/phy_noc_gen/phy_noc.pl $append $target_dir/noc$i"; run_cmd_textview_errors ($cmd,$info); gen_noc_localparam_v_file($self,"$target_dir/noc$i",undef,$i); @@ -135,65 +116,50 @@ sub generate_phynocs{ $flist2.="-F noc$i/noc_filelist_${append}.f\n"; $nocs.=" noc_top_${append} noc_${append} ( - .reset(reset), - .clk(clk), - .chan_in_all(chan_in_$append), - .chan_out_all(chan_out_$append), - .router_event() + .reset(reset), + .clk(clk), + .chan_in_all(chan_in_$append), + .chan_out_all(chan_out_$append), + .router_event() ); " } #copy common rtl modules my $cmd = "cp $pronoc_dir/mpsoc/rtl/*.v $target_dir/"; run_cmd_textview_errors ($cmd,$info); - - my $top=autogen_warning().get_license_header("${name}_top.v"); $top.="module ${name}_top( reset, - clk, + clk, $ports1 ); - $imports - input reset,clk; $ports2 - -$nocs +$nocs endmodule "; - save_file ("$target_dir/${name}_top.v",$top); save_file ("$target_dir/${name}.flist",$flist1.$flist2."./${name}_top.v"); - - message_dialog("Multiple physical NoCs \"$name\" has been created successfully at $target_dir/ " ); return 1; } - - - sub build_phy_noc_gui { my ($self) = @_; set_gui_status($self,"ideal",0); $self->object_add_attribute ("process_notebook","currentpage",0); my $main_table= def_table(2,10,FALSE); add_param_widget ($self,"Phy NoCs #:" , undef, 3, 'Spin-button', "1,20,1","Specify the number of independent phisical NoCs. each NoC can have its unique set of parameter configuration.", $main_table,24,0,1, 'phy_num', 1,'ref_nocs','vertical'); - my ($infobox,$info)= create_txview(); - my $notebook = gen_notebook_phy($self,$info); + my $notebook = gen_notebook_phy($self,$info); my $v2=gen_vpaned($notebook,.65,$infobox); - - my $pronoc_dir = get_project_dir(); #mpsoc dir addr my $target_dir= "$ENV{PRONOC_WORK}/src_phy_nocs/"; - my ($entrybox,$entry ) =gen_save_load_widget ( - $self, #the object + $self, #the object "Phy Name",#the label shown for setting configuration - 'phy_name',#the key name for saveing the setting configuration in object + 'phy_name',#the key name for saveing the setting configuration in object 'multiple physical NoCs',#the label full name show in tool tips $target_dir,#Where the generted RTL files are loacted. Undef if not aplicaple 'soc',#check the given name match the SoC or mpsoc name rules @@ -203,59 +169,46 @@ sub build_phy_noc_gui { $info ); my $generate = def_image_button('icons/gen.png','Generate'); - $main_table->attach_defaults ($v2 , 0, 12, 0,24); $main_table->attach ($entrybox,3, 4, 24,25,'expand','shrink',2,2); $main_table->attach ($generate, 6, 9, 24,25,'expand','shrink',2,2); my $sc_win = add_widget_to_scrolled_win($main_table); - - $generate->signal_connect("clicked" => sub{ + $generate->signal_connect("clicked" => sub{ my $load= show_gif("icons/load.gif"); $main_table->attach ($load, 9, 10, 24,25,'expand','shrink',2,2); $load->show_all; - generate_phynocs($self,$info); + generate_phynocs($self,$info); $load->destroy; - }); - - #check soc status every 0.5 second. refresh device table if there is any changes + }); + #check soc status every 0.5 second. refresh device table if there is any changes Glib::Timeout->add (100, sub{ my ($state,$timeout)= get_gui_status($self); - if ($timeout>0){ $timeout--; - set_gui_status($self,$state,$timeout); + set_gui_status($self,$state,$timeout); return TRUE; - } if($state eq "ideal"){ return TRUE; - } if($state eq 'ref_nocs'){ $notebook->destroy; $notebook = gen_notebook_phy($self,$info); - $v2 -> pack1($notebook, TRUE, TRUE); - $v2 -> show_all; + $v2 -> pack1($notebook, TRUE, TRUE); + $v2 -> show_all; } else { #only refresh current NoC setting my $page_num=$self->object_get_attribute ("process_notebook","currentpage"); $pages[$page_num]->destroy; $pages[$page_num]=get_noc_num_page($self,$page_num,$info); add_widget_to_scrolled_win($pages[$page_num],$page_wins[$page_num]); - $page_wins[$page_num]->show_all; - } - + $page_wins[$page_num]->show_all; + } my $saved_name=$self->object_get_attribute('save_as'); $entry->set_text($saved_name)if(defined $saved_name); - set_gui_status($self,"ideal",0); - $main_table->show_all(); - - + $main_table->show_all(); return TRUE; - } ); - + } ); return $sc_win; - } - -1; +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/readme_gen.pl b/mpsoc/perl_gui/lib/perl/readme_gen.pl index b11d911..ad56f7b 100755 --- a/mpsoc/perl_gui/lib/perl/readme_gen.pl +++ b/mpsoc/perl_gui/lib/perl/readme_gen.pl @@ -3,70 +3,60 @@ use Consts; sub get_license_header { - my $file_name=shift; - my $version = Consts::VERSION; - my $end = Consts::END_YEAR; - my $head=" + my $file_name=shift; + my $version = Consts::VERSION; + my $end = Consts::END_YEAR; + my $head=" /********************************************************************** -** File: $file_name +** File: $file_name ** -** Copyright (C) 2014-$end Alireza Monemi +** Copyright (C) 2014-$end Alireza Monemi ** -** This file is part of ProNoC $version +** This file is part of ProNoC $version ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ "; - - return $head; - } sub autogen_warning { - my $string =" /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/\n\n"; - return $string; - - } sub perl_file_header { - my $file_name=shift; - my $version = Consts::VERSION; - my $end = Consts::END_YEAR; + my $file_name=shift; + my $version = Consts::VERSION; + my $end = Consts::END_YEAR; my $head="####################################################################### -## File: $file_name +## File: $file_name ## -## Copyright (C) 2014-$end Alireza Monemi +## Copyright (C) 2014-$end Alireza Monemi ## -## This file is part of ProNoC $version +## This file is part of ProNoC $version ## -## WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT -## MAY CAUSE UNEXPECTED BEHAVIOR. +## WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT +## MAY CAUSE UNEXPECTED BEHAVIOR. ################################################################################ - "; return $head; } - - -1; +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/run_time_jtag_debug.pl b/mpsoc/perl_gui/lib/perl/run_time_jtag_debug.pl index be31727..d3c92a5 100644 --- a/mpsoc/perl_gui/lib/perl/run_time_jtag_debug.pl +++ b/mpsoc/perl_gui/lib/perl/run_time_jtag_debug.pl @@ -1,19 +1,15 @@ #!/usr/bin/perl -w use strict; use warnings; - use constant::boolean; - use FindBin; use lib $FindBin::Bin; - use Data::Dumper; use File::Which; use File::Basename; - use IPC::Run qw( harness start pump finish timeout ); - use Consts; + BEGIN { my $module = (Consts::GTK_VERSION==2) ? 'Gtk2' : 'Gtk3'; my $file = $module; @@ -23,928 +19,669 @@ BEGIN $module->import; } - - require "widget.pl"; require "uart.pl"; require "compile.pl"; - - use String::Scanf; # imports sscanf() - - use constant JTAG_UPDATE_WB_ADDR => 7; use constant JTAG_UPDATE_WB_WR_DATA=> 6; -use constant JTAG_UPDATE_WB_RD_DATA => 5; - - +use constant JTAG_UPDATE_WB_RD_DATA => 5; use base 'Class::Accessor::Fast'; + __PACKAGE__->mk_accessors(qw{ - window - sourceview + window + sourceview }); my $NAME = 'Soure Probe'; -my $path = ""; - - - +my $path = ""; my %memory; my %status; - sub source_probe_stand_alone(){ - $path = "../../"; - set_path_env(); - my $project_dir = get_project_dir(); #mpsoc dir addr - my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; - if (-f $paths_file){#} && defined $ENV{PRONOC_WORK} ) { - my $paths= do $paths_file; - set_gui_setting($paths); - } - - set_defualt_font_size(); - my $window=source_probe_main(); - $window->signal_connect (destroy => sub { gui_quite();}); + $path = "../../"; + set_path_env(); + my $project_dir = get_project_dir(); #mpsoc dir addr + my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; + if (-f $paths_file){#} && defined $ENV{PRONOC_WORK} ) { + my $paths= do $paths_file; + set_gui_setting($paths); + } + set_defualt_font_size(); + my $window=source_probe_main(); + $window->signal_connect (destroy => sub { gui_quite();}); } exit gtk_gui_run(\&source_probe_stand_alone) unless caller; - sub get_jtag_intfc_rst_cmd { - my $self=shift; - - my $vendor = $self->object_get_attribute('CTRL','VENDOR'); - my $board = $self->object_get_attribute('CTRL','Board_Name'); - my $chain = $self->object_get_attribute('CTRL','RESET_CHAIN'); - my $index = 127; - my $pronoc = get_project_dir(); - my $intfc = "$pronoc/mpsoc/boards/$vendor/$board/jtag_intfc.sh"; - #my $script = "$ENV{'PRONOC_WORK'}/tmp/script.bash"; - - my $t = ($vendor eq 'Xilinx') ? "-t $chain " : ""; - - my $cmd = "bash -c \"source $intfc; \\\$JTAG_INTFC $t -n $index"; - return $cmd; - + my $self=shift; + my $vendor = $self->object_get_attribute('CTRL','VENDOR'); + my $board = $self->object_get_attribute('CTRL','Board_Name'); + my $chain = $self->object_get_attribute('CTRL','RESET_CHAIN'); + my $index = 127; + my $pronoc = get_project_dir(); + my $intfc = "$pronoc/mpsoc/boards/$vendor/$board/jtag_intfc.sh"; + #my $script = "$ENV{'PRONOC_WORK'}/tmp/script.bash"; + my $t = ($vendor eq 'Xilinx') ? "-t $chain " : ""; + my $cmd = "bash -c \"source $intfc; \\\$JTAG_INTFC $t -n $index"; + return $cmd; } - sub jtag_enable_cpus_func{ - my ($self,$new,$tview)=@_; - my $intfc = get_jtag_intfc_rst_cmd($self); + my ($self,$new,$tview)=@_; + my $intfc = get_jtag_intfc_rst_cmd($self); my $e = ($new eq 'Enabled')? 0 : 2; - my $cmd = "$intfc -d I:1,D:2:$e,I:0\""; - add_info($tview,"$cmd\n"); - my $results =run_cmd_textview_errors($cmd,$tview); - return 1 if(!defined $results); - + my $cmd = "$intfc -d I:1,D:2:$e,I:0\""; + add_info($tview,"$cmd\n"); + my $results =run_cmd_textview_errors($cmd,$tview); + return 1 if(!defined $results); } sub jtag_reset_cpus_func { - my ($self,$tview)=@_; - my $intfc = get_jtag_intfc_rst_cmd($self); - - my $cmd = "$intfc -d I:1,D:2:1,D:2:0,I:0\""; - add_info($tview,"$cmd\n"); - my $results =run_cmd_textview_errors($cmd,$tview); - return 1 if(!defined $results); - -}; - - - - - + my ($self,$tview)=@_; + my $intfc = get_jtag_intfc_rst_cmd($self); + my $cmd = "$intfc -d I:1,D:2:1,D:2:0,I:0\""; + add_info($tview,"$cmd\n"); + my $results =run_cmd_textview_errors($cmd,$tview); + return 1 if(!defined $results); +}; sub source_probe_ctrl { - my ($self,$tview)=@_; - my $table= def_table(2,10,FALSE); - - my $vendor= $self->object_get_attribute('CTRL','VENDOR'); - $vendor= 'Xilinx' if(!defined $vendor); - - - #get the list of boards located in "boards/*" folder - my $pronoc = get_project_dir(); - - my @dirs = grep {-d} glob("$pronoc/mpsoc/boards/$vendor/*"); - my ($fpgas,$init); - - - foreach my $dir (@dirs) { - my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - $init="$name"; - } - - - my @info = ( - { label=>" FPGA Vendor name: ", param_name=>'VENDOR', type=>"Combo-box", default_val=>'Xilinx', content=>"Xilinx,Altera", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}, - { label=>" Board Name ", param_name=>'Board_Name', type=>"Combo-box", default_val=>$init, content=>$fpgas, info=>undef, param_parent=>'CTRL', ref_delay=> undef, new_status=>undef, loc=>'vertical'}, - { label=>" JTAG Index: ", param_name=>'JTAG_INDEX', type=>"Spin-button", default_val=>0, content=>"0,128,1", info=>undef, param_parent=>'CTRL', ref_delay=> undef, new_status=> undef, loc=>'vertical'} - ); - - - - if ($vendor eq "Xilinx" ) { - push (@info,{ label=>" JTAG CHAIN ", param_name=>'JTAG_CHAIN', type=>"Combo-box", default_val=>4, content=>"1,2,3,4", info=>undef, param_parent=>'CTRL', ref_delay=> 0, new_status=>'ref_ctrl', loc=>'vertical'}) ; - - } - - - my ($row,$col)=(0,6); - - foreach my $d (@info) { - my $wiget; - ($row,$col,$wiget)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); - my $sc=$col; - if($d->{param_name} eq 'Board_Name'){ - my $add=def_image_button("icons/plus.png"); - $table->attach ($add, $sc+4, $sc+5,$row-1,$row,'shrink','shrink',2,2); - set_tip($add, "Add new FPGA Board"); - $add-> signal_connect("clicked" => sub{ - add_new_fpga_board($self,undef,undef,undef,undef,$vendor); - }); - - } - - - } - - - $table->attach ( gen_Vsep(), 5, 6 , 0, $row+1,'fill','fill',2,2); - - #Column 2 - $row=0;$col=0; - my $d={ label=>" Number of Sources/Probes:", param_name=>'SP_NUM', type=>"Spin-button", default_val=>1, content=>"1,128,1", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_all', loc=>'vertical'}; - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); - $d={ label=>" Address format: ", param_name=>'R_ADDR_FORMAT', type=>"Combo-box", default_val=>'Decimal', content=>"Decimal,Hexadecimal", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'}, - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); - - - #enable - my $en_state=$self->object_get_attribute("CTRL","enable"); - if (!defined $en_state){ - $en_state='Enabled' ; - $self->object_add_attribute("CTRL","enable",$en_state); - } - my $enable= ($en_state eq 'Enabled')? def_colored_button('Enabled',17): def_colored_button('Disabled',4); - - my $reset= def_button('Reset'); - - if ($vendor eq "Xilinx" ) { - - my $w=gen_combobox_object ($self,'CTRL','RESET_CHAIN',"4,3,2,1","4",undef,undef); - my $h=gen_button_message ("The JTAG remote reset/enable is connected to the Jtag tab chain with the largest chain number in each tile. ","icons/help.png"); - my $b= def_pack_hbox(FALSE,0,(gen_label_in_center ("CPU(s) Chain:"),$w,$h)); - $table->attach ($b , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col+=1; - - }else{ - $table->attach (gen_label_in_center ("CPU(s)") , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col+=1; - } - - $table->attach ($reset , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col+=1; - $table->attach ($enable , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; - - $enable -> signal_connect("clicked" => sub{ - my $en_state=$self->object_get_attribute("CTRL","enable"); - my $new = ($en_state eq 'Enabled')? 'Disabled' : 'Enabled'; - jtag_enable_cpus_func($self,$new,$tview); - $self->object_add_attribute("CTRL","enable",$new); - set_gui_status($self,"ref",1); - }); - - $reset -> signal_connect("clicked" => sub{ - jtag_reset_cpus_func($self,$tview); - }); - - - my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); - add_widget_to_scrolled_win($table,$scrolled_win); - return $scrolled_win; + my ($self,$tview)=@_; + my $table= def_table(2,10,FALSE); + my $vendor= $self->object_get_attribute('CTRL','VENDOR'); + $vendor= 'Xilinx' if(!defined $vendor); + #get the list of boards located in "boards/*" folder + my $pronoc = get_project_dir(); + my @dirs = grep {-d} glob("$pronoc/mpsoc/boards/$vendor/*"); + my ($fpgas,$init); + foreach my $dir (@dirs) { + my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$"); + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + $init="$name"; + } + my @info = ( + { label=>" FPGA Vendor name: ", param_name=>'VENDOR', type=>"Combo-box", default_val=>'Xilinx', content=>"Xilinx,Altera", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}, + { label=>" Board Name ", param_name=>'Board_Name', type=>"Combo-box", default_val=>$init, content=>$fpgas, info=>undef, param_parent=>'CTRL', ref_delay=> undef, new_status=>undef, loc=>'vertical'}, + { label=>" JTAG Index: ", param_name=>'JTAG_INDEX', type=>"Spin-button", default_val=>0, content=>"0,128,1", info=>undef, param_parent=>'CTRL', ref_delay=> undef, new_status=> undef, loc=>'vertical'} + ); + if ($vendor eq "Xilinx" ) { + push (@info,{ label=>" JTAG CHAIN ", param_name=>'JTAG_CHAIN', type=>"Combo-box", default_val=>4, content=>"1,2,3,4", info=>undef, param_parent=>'CTRL', ref_delay=> 0, new_status=>'ref_ctrl', loc=>'vertical'}) ; + } + my ($row,$col)=(0,6); + foreach my $d (@info) { + my $wiget; + ($row,$col,$wiget)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); + my $sc=$col; + if($d->{param_name} eq 'Board_Name'){ + my $add=def_image_button("icons/plus.png"); + $table->attach ($add, $sc+4, $sc+5,$row-1,$row,'shrink','shrink',2,2); + set_tip($add, "Add new FPGA Board"); + $add-> signal_connect("clicked" => sub{ + add_new_fpga_board($self,undef,undef,undef,undef,$vendor); + }); + } + } + $table->attach ( gen_Vsep(), 5, 6 , 0, $row+1,'fill','fill',2,2); + #Column 2 + $row=0;$col=0; + my $d={ label=>" Number of Sources/Probes:", param_name=>'SP_NUM', type=>"Spin-button", default_val=>1, content=>"1,128,1", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_all', loc=>'vertical'}; + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); + $d={ label=>" Address format: ", param_name=>'R_ADDR_FORMAT', type=>"Combo-box", default_val=>'Decimal', content=>"Decimal,Hexadecimal", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'}, + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); + #enable + my $en_state=$self->object_get_attribute("CTRL","enable"); + if (!defined $en_state){ + $en_state='Enabled' ; + $self->object_add_attribute("CTRL","enable",$en_state); + } + my $enable= ($en_state eq 'Enabled')? def_colored_button('Enabled',17): def_colored_button('Disabled',4); + my $reset= def_button('Reset'); + if ($vendor eq "Xilinx" ) { + my $w=gen_combobox_object ($self,'CTRL','RESET_CHAIN',"4,3,2,1","4",undef,undef); + my $h=gen_button_message ("The JTAG remote reset/enable is connected to the Jtag tab chain with the largest chain number in each tile. ","icons/help.png"); + my $b= def_pack_hbox(FALSE,0,(gen_label_in_center ("CPU(s) Chain:"),$w,$h)); + $table->attach ($b , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col+=1; + }else{ + $table->attach (gen_label_in_center ("CPU(s)") , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col+=1; + } + $table->attach ($reset , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $col+=1; + $table->attach ($enable , $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++; + $enable -> signal_connect("clicked" => sub{ + my $en_state=$self->object_get_attribute("CTRL","enable"); + my $new = ($en_state eq 'Enabled')? 'Disabled' : 'Enabled'; + jtag_enable_cpus_func($self,$new,$tview); + $self->object_add_attribute("CTRL","enable",$new); + set_gui_status($self,"ref",1); + }); + $reset -> signal_connect("clicked" => sub{ + jtag_reset_cpus_func($self,$tview); + }); + my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); + add_widget_to_scrolled_win($table,$scrolled_win); + return $scrolled_win; } - - - - - - - sub soure_probe_widgets_old { - my $self=shift; - my $table= def_table(2,10,FALSE); - my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); - add_widget_to_scrolled_win($table,$scrolled_win); - my $num = $self->object_get_attribute('CTRL','SP_NUM'); - - my $y= 0; - my $x= 0; - - $table->attach (gen_label_in_center(" Source "), 0, 3 , $y, $y+1,'shrink','shrink',2,2); - $table->attach (gen_label_in_center(" Probe "), 4, 7 , $y, $y+1,'shrink','shrink',2,2); - $y++; - $table->attach ( gen_Hsep(), 0, 7 , $y, $y+1, 'fill','shrink',2,2); - - $y++; - my @sources; - for (my $i=0; $i<$num; $i+=1){ - my $n=$i+1; - $table->attach (gen_label_in_left(" $n- "), $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - my $entry=gen_entry( ); - $table->attach ($entry, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - - my $enter=def_image_button("icons/write.png","Write"); - - $table->attach ($enter, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - - $x++; #sep - - #probe - #$table->attach (gen_label_in_left(" Probe: " ) , $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - my $probe_val = $self-> object_get_attribute('SP','PROBE_$n'); - - my $probe_label= gen_label_in_left(" "); - - ${probe_val}=25 if ($n ==1); - - $probe_label->set_markup("XXXX") if(!defined $probe_val ); - $probe_label->set_markup(" ${probe_val} ") unless(!defined $probe_val ); - - my $frame = gen_frame(); - $frame->set_shadow_type ('in'); - # Animation - $frame->add ($probe_label); - - - $table->attach ($frame, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - my $read=def_image_button("icons/simulator.png","Read"); - $table->attach ($read, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - - $y++; $x=0; - $table->attach (gen_Hsep(), 0, 7 , $y, $y+1, 'fill','shrink',2,2); - $y++; - - } - - $table->attach ( gen_Vsep(), 3, 4 , 0, $y+1,'fill','fill',2,2); - $table->attach ( gen_Vsep(), 6, 7 , 0, $y+1,'fill','fill',2,2); - - return ($scrolled_win,\@sources); + my $self=shift; + my $table= def_table(2,10,FALSE); + my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); + add_widget_to_scrolled_win($table,$scrolled_win); + my $num = $self->object_get_attribute('CTRL','SP_NUM'); + my $y= 0; + my $x= 0; + $table->attach (gen_label_in_center(" Source "), 0, 3 , $y, $y+1,'shrink','shrink',2,2); + $table->attach (gen_label_in_center(" Probe "), 4, 7 , $y, $y+1,'shrink','shrink',2,2); + $y++; + $table->attach ( gen_Hsep(), 0, 7 , $y, $y+1, 'fill','shrink',2,2); + $y++; + my @sources; + for (my $i=0; $i<$num; $i+=1){ + my $n=$i+1; + $table->attach (gen_label_in_left(" $n- "), $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + my $entry=gen_entry( ); + $table->attach ($entry, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + my $enter=def_image_button("icons/write.png","Write"); + $table->attach ($enter, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + $x++; #sep + #probe + #$table->attach (gen_label_in_left(" Probe: " ) , $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + my $probe_val = $self-> object_get_attribute('SP','PROBE_$n'); + my $probe_label= gen_label_in_left(" "); + ${probe_val}=25 if ($n ==1); + $probe_label->set_markup("XXXX") if(!defined $probe_val ); + $probe_label->set_markup(" ${probe_val} ") unless(!defined $probe_val ); + my $frame = gen_frame(); + $frame->set_shadow_type ('in'); + # Animation + $frame->add ($probe_label); + $table->attach ($frame, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + my $read=def_image_button("icons/simulator.png","Read"); + $table->attach ($read, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + $y++; $x=0; + $table->attach (gen_Hsep(), 0, 7 , $y, $y+1, 'fill','shrink',2,2); + $y++; + } + $table->attach ( gen_Vsep(), 3, 4 , 0, $y+1,'fill','fill',2,2); + $table->attach ( gen_Vsep(), 6, 7 , 0, $y+1,'fill','fill',2,2); + return ($scrolled_win,\@sources); } sub read_mem_specefic_addr{ - my ($self,$addr,$tview)=@_; - add_info($tview,"Read addr: $addr\n"); - my $intfc = get_jtag_intfc_cmd($self); - $addr=($addr>>2); - $addr=sprintf("%x",$addr); - my $cmd = "$intfc -d I:${\JTAG_UPDATE_WB_RD_DATA},R:32:$addr,I:0\""; - add_info($tview,"$cmd\n"); - my $results =run_cmd_textview_errors($cmd,$tview); - return 1 if(!defined $results); - my ($hex)= sscanf("###read data#0x%s###read data#", $results); - ###read data#0x18000000###read data# - #add_info($tview," $results \n"); - #add_info($tview," $hex \n"); - return $hex; + my ($self,$addr,$tview)=@_; + add_info($tview,"Read addr: $addr\n"); + my $intfc = get_jtag_intfc_cmd($self); + $addr=($addr>>2); + $addr=sprintf("%x",$addr); + my $cmd = "$intfc -d I:${\JTAG_UPDATE_WB_RD_DATA},R:32:$addr,I:0\""; + add_info($tview,"$cmd\n"); + my $results =run_cmd_textview_errors($cmd,$tview); + return 1 if(!defined $results); + my ($hex)= sscanf("###read data#0x%s###read data#", $results); + ###read data#0x18000000###read data# + #add_info($tview," $results \n"); + #add_info($tview," $hex \n"); + return $hex; } - sub write_mem_specefic_addr { - my ($self,$addr,$value,$tview)=@_; - my $intfc = get_jtag_intfc_cmd($self); - $addr=($addr>>2); - $addr=sprintf("%x",$addr); - my $cmd = "$intfc -d I:${\JTAG_UPDATE_WB_ADDR},D:32:$addr,I:${\JTAG_UPDATE_WB_WR_DATA},D:32:$value,I:0\""; - add_info($tview,"$cmd\n"); - my $results =run_cmd_textview_errors($cmd,$tview); - return 1 if(!defined $results); -} + my ($self,$addr,$value,$tview)=@_; + my $intfc = get_jtag_intfc_cmd($self); + $addr=($addr>>2); + $addr=sprintf("%x",$addr); + my $cmd = "$intfc -d I:${\JTAG_UPDATE_WB_ADDR},D:32:$addr,I:${\JTAG_UPDATE_WB_WR_DATA},D:32:$value,I:0\""; + add_info($tview,"$cmd\n"); + my $results =run_cmd_textview_errors($cmd,$tview); + return 1 if(!defined $results); +} sub soure_probe_widgets { - my ($self,$tview)=@_; - my $table= def_table(2,10,FALSE); - my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); - add_widget_to_scrolled_win($table,$scrolled_win); - my $num = $self->object_get_attribute('CTRL','SP_NUM'); - $num = 1 if (!defined $num); - my $y= 0; - my $x= 0; - - - - - - $table->attach (gen_label_in_center(" Address (in byte)"), 0, 1 , $y, $y+1,'shrink','shrink',2,2); - $table->attach (gen_label_in_center(" Memory Content "), 2, 3 , $y, $y+1,'shrink','shrink',2,2); - $table->attach (gen_label_in_center(" Action "), 4, 6 , $y, $y+1,'shrink','shrink',2,2); - $y++; - - $table->attach ( gen_Hsep(), 0, 6 , $y, $y+1, 'fill','shrink',2,2); - - $y++; - $x= 0; - - for (my $i=0; $i<$num; $i+=1){ - my $n=$i+1; - my $status=0; - #$table->attach (gen_label_in_left(" $n-address "), $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - # ($y,$x,$addr)=add_param_widget ($self,"$n-", "$n-address", 0, "Spin-button", "0,99999999,1", undef, $table,$y,$x,1, "JTAG_WB", undef, undef, 'horizontal'); - # ($y,$x,$entry)=add_param_widget ($self,undef, "$n-value", 0, "Entry", undef, undef, $table,$y,$x,1, "JTAG_WB", undef, undef, 'horizontal'); - - my $addr = gen_entry(0); - my $entry =gen_entry('xxxxxxxx'); - my $read=def_image_button($path."icons/simulator.png","Read"); - my $write=def_image_button($path."icons/write.png","Write"); - - - $entry->set_max_length (8); - $entry->set_width_chars(8); - - $table->attach ($addr, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x+=2; - $table->attach ($entry, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x+=2; - $table->attach ($read, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - $table->attach ($write, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; - my $sy= $y; - my $sx=7; - - $y++; $x=0; - $table->attach ( gen_Hsep(), 0, $sx , $y, $y+1, 'fill','shrink',2,2); - $y++; - - - - $read-> signal_connect("clicked" => sub{ - my $address=$addr->get_text(); - my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); - $format= 'Decimal' if (!defined $format); - $address = hex($address) unless($format eq 'Decimal'); - my $load= show_gif("icons/load.gif"); - $table->attach ($load,$sx, $sx+1 , $sy, $sy+1,'shrink','shrink',0,0); - $table->show_all(); - my $val =read_mem_specefic_addr($self,$address,$tview); - $entry->set_text($val) if (defined $val); - $status =1; - entry_set_text_color($entry,-1); - $load->destroy; - }); - - $write-> signal_connect("clicked" => sub{ - my $value = $entry->get_text(); - my $address=$addr->get_text(); - my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); - $format= 'Decimal' if (!defined $format); - $address = hex($address) unless($format eq 'Decimal'); - my $load= show_gif("icons/load.gif"); - $table->attach ($load,$sx, $sx+1 , $sy, $sy+1,'shrink','shrink',0,0); - $table->show_all(); - write_mem_specefic_addr($self,$address,$value,$tview); - $status =1; - entry_set_text_color($entry,-1); - $load->destroy; - - }); - - $entry->signal_connect("changed" => sub{ - if($status==0 || $status==1 ){ - $status =2;#modified - #change color to red - entry_set_text_color($entry,11); - - } - my $in = $entry->get_text(); - $entry->set_text(remove_not_hex($in)); - - }); - - - $addr->signal_connect("changed" => sub{ - my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); - $format= 'Decimal' if (!defined $format); - my $in = $addr->get_text(); - $addr->set_text(remove_not_hex($in)) if ($format ne 'Decimal' ); - $addr->set_text(remove_not_number($in)) if ($format eq 'Decimal' ); - }); - - } - - $table->attach ( gen_Vsep(), 1, 2 , 0, $y+1,'fill','fill',2,2); - $table->attach ( gen_Vsep(), 3, 4 , 0, $y+1,'fill','fill',2,2); - $table->attach ( gen_Vsep(), 6, 7 , 0, $y+1,'fill','fill',2,2); - - return $scrolled_win; + my ($self,$tview)=@_; + my $table= def_table(2,10,FALSE); + my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); + add_widget_to_scrolled_win($table,$scrolled_win); + my $num = $self->object_get_attribute('CTRL','SP_NUM'); + $num = 1 if (!defined $num); + my $y= 0; + my $x= 0; + $table->attach (gen_label_in_center(" Address (in byte)"), 0, 1 , $y, $y+1,'shrink','shrink',2,2); + $table->attach (gen_label_in_center(" Memory Content "), 2, 3 , $y, $y+1,'shrink','shrink',2,2); + $table->attach (gen_label_in_center(" Action "), 4, 6 , $y, $y+1,'shrink','shrink',2,2); + $y++; + $table->attach ( gen_Hsep(), 0, 6 , $y, $y+1, 'fill','shrink',2,2); + $y++; + $x= 0; + for (my $i=0; $i<$num; $i+=1){ + my $n=$i+1; + my $status=0; + #$table->attach (gen_label_in_left(" $n-address "), $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + # ($y,$x,$addr)=add_param_widget ($self,"$n-", "$n-address", 0, "Spin-button", "0,99999999,1", undef, $table,$y,$x,1, "JTAG_WB", undef, undef, 'horizontal'); + # ($y,$x,$entry)=add_param_widget ($self,undef, "$n-value", 0, "Entry", undef, undef, $table,$y,$x,1, "JTAG_WB", undef, undef, 'horizontal'); + my $addr = gen_entry(0); + my $entry =gen_entry('xxxxxxxx'); + my $read=def_image_button($path."icons/simulator.png","Read"); + my $write=def_image_button($path."icons/write.png","Write"); + $entry->set_max_length (8); + $entry->set_width_chars(8); + $table->attach ($addr, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x+=2; + $table->attach ($entry, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x+=2; + $table->attach ($read, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + $table->attach ($write, $x, $x+1 , $y, $y+1,'shrink','shrink',2,2); $x++; + my $sy= $y; + my $sx=7; + $y++; $x=0; + $table->attach ( gen_Hsep(), 0, $sx , $y, $y+1, 'fill','shrink',2,2); + $y++; + $read-> signal_connect("clicked" => sub{ + my $address=$addr->get_text(); + my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); + $format= 'Decimal' if (!defined $format); + $address = hex($address) unless($format eq 'Decimal'); + my $load= show_gif("icons/load.gif"); + $table->attach ($load,$sx, $sx+1 , $sy, $sy+1,'shrink','shrink',0,0); + $table->show_all(); + my $val =read_mem_specefic_addr($self,$address,$tview); + $entry->set_text($val) if (defined $val); + $status =1; + entry_set_text_color($entry,-1); + $load->destroy; + }); + $write-> signal_connect("clicked" => sub{ + my $value = $entry->get_text(); + my $address=$addr->get_text(); + my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); + $format= 'Decimal' if (!defined $format); + $address = hex($address) unless($format eq 'Decimal'); + my $load= show_gif("icons/load.gif"); + $table->attach ($load,$sx, $sx+1 , $sy, $sy+1,'shrink','shrink',0,0); + $table->show_all(); + write_mem_specefic_addr($self,$address,$value,$tview); + $status =1; + entry_set_text_color($entry,-1); + $load->destroy; + }); + $entry->signal_connect("changed" => sub{ + if($status==0 || $status==1 ){ + $status =2;#modified + #change color to red + entry_set_text_color($entry,11); + } + my $in = $entry->get_text(); + $entry->set_text(remove_not_hex($in)); + }); + $addr->signal_connect("changed" => sub{ + my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); + $format= 'Decimal' if (!defined $format); + my $in = $addr->get_text(); + $addr->set_text(remove_not_hex($in)) if ($format ne 'Decimal' ); + $addr->set_text(remove_not_number($in)) if ($format eq 'Decimal' ); + }); + } + $table->attach ( gen_Vsep(), 1, 2 , 0, $y+1,'fill','fill',2,2); + $table->attach ( gen_Vsep(), 3, 4 , 0, $y+1,'fill','fill',2,2); + $table->attach ( gen_Vsep(), 6, 7 , 0, $y+1,'fill','fill',2,2); + return $scrolled_win; } sub get_file_b_setting{ - my($self)=@_; - my $window = def_popwin_size (30,30,'Source Probe','percent'); - my $table= def_table(2,10,FALSE); + my($self)=@_; + my $window = def_popwin_size (30,30,'Source Probe','percent'); + my $table= def_table(2,10,FALSE); my @info = ( - #{ label=>" Address format: ", param_name=>'R_ADDR_FORMAT', type=>"Combo-box", default_val=>'Decimal', content=>"Decimal,Hexadecimal", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'}, - { label=>" Page row number: ", param_name=>'PAGE_MAX_X', type=>"Spin-button", default_val=>10, content=>"0,128,1", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'}, - { label=>" Page column number:", param_name=>'PAGE_MAX_Y', type=>"Spin-button", default_val=>10, content=>"1,128,1", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'} - ); - my $row=0; - my $col=0; - foreach my $d (@info) { - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); - } - $table->attach (gen_label_in_center(' '), 2, 3,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach (gen_label_in_center(' '), 2, 3,$row,$row+1,'shrink','shrink',2,2); $row++; - $table->attach (gen_label_in_center(' '), 2, 3,$row,$row+1,'shrink','shrink',2,2); $row++; - - - my $ok=def_image_button($path."icons/select.png",'OK'); - $table->attach ($ok, 2, 3,$row,$row+1,'shrink','shrink',2,2); - $ok-> signal_connect("clicked" => sub{ - $window->destroy(); - }); - - $window->add(add_widget_to_scrolled_win($table)); - $window->show_all; - + #{ label=>" Address format: ", param_name=>'R_ADDR_FORMAT', type=>"Combo-box", default_val=>'Decimal', content=>"Decimal,Hexadecimal", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'}, + { label=>" Page row number: ", param_name=>'PAGE_MAX_X', type=>"Spin-button", default_val=>10, content=>"0,128,1", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'}, + { label=>" Page column number:", param_name=>'PAGE_MAX_Y', type=>"Spin-button", default_val=>10, content=>"1,128,1", info=>undef, param_parent=>'FILE_VIEW', ref_delay=> 1, new_status=>'ref_file_view', loc=>'vertical'} + ); + my $row=0; + my $col=0; + foreach my $d (@info) { + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); + } + $table->attach (gen_label_in_center(' '), 2, 3,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach (gen_label_in_center(' '), 2, 3,$row,$row+1,'shrink','shrink',2,2); $row++; + $table->attach (gen_label_in_center(' '), 2, 3,$row,$row+1,'shrink','shrink',2,2); $row++; + my $ok=def_image_button($path."icons/select.png",'OK'); + $table->attach ($ok, 2, 3,$row,$row+1,'shrink','shrink',2,2); + $ok-> signal_connect("clicked" => sub{ + $window->destroy(); + }); + $window->add(add_widget_to_scrolled_win($table)); + $window->show_all; } sub fill_memory_array_from_file{ - my ($self,$fname,$tview)=@_; - - my $offset = $self->object_get_attribute('FILE_VIEW','IN_FILE_OFFSET'); - my $BLOCK_SIZE =4; - - open(F,"<$fname") or die("Unable to open file $fname, $!"); - binmode(F); - my $buf; - my $ct=($offset>>2); - - my $start = ($offset>>2); - my $r=read(F,$buf,$BLOCK_SIZE); - while($r){ - my $v=''; - foreach(split(//, $buf)){ - $v.=sprintf("%02x",ord($_)); - } - if($r!=4){ - $v.='0'x(( 4 - $r)*2); - } - $memory{$ct}= $v; - $status{$ct}=2; - $ct++; - $r=read(F,$buf,$BLOCK_SIZE); - } - close(F); - - add_info($tview,"Load $fname\n"); - $ct=($ct << 2); - add_info($tview,"address $offset to $ct\n"); + my ($self,$fname,$tview)=@_; + my $offset = $self->object_get_attribute('FILE_VIEW','IN_FILE_OFFSET'); + my $BLOCK_SIZE =4; + open(F,"<$fname") or die("Unable to open file $fname, $!"); + binmode(F); + my $buf; + my $ct=($offset>>2); + my $start = ($offset>>2); + my $r=read(F,$buf,$BLOCK_SIZE); + while($r){ + my $v=''; + foreach(split(//, $buf)){ + $v.=sprintf("%02x",ord($_)); + } + if($r!=4){ + $v.='0'x(( 4 - $r)*2); + } + $memory{$ct}= $v; + $status{$ct}=2; + $ct++; + $r=read(F,$buf,$BLOCK_SIZE); + } + close(F); + add_info($tview,"Load $fname\n"); + $ct=($ct << 2); + add_info($tview,"address $offset to $ct\n"); } sub get_file_in_name{ - my ($self,$tview)=@_; - - my $file; - my $title ='select bin file'; - my $dialog = gen_file_dialog ($title); - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - $dialog->destroy; - $self->object_add_attribute('FILE_VIEW','IN_FILE',$file); - - #get offset address; - my $window = def_popwin_size (30,20,'Get Offset Address','percent'); - my $table= def_table(2,10,FALSE); - my $d= - { label=>" Offset address (in byte): ", param_name=>'IN_FILE_OFFSET', type=>"Spin-button", default_val=>0, content=>'0,9999999999,1', info=>'The Wishbone bus offset address where the beginning of the memory bin file is written there (It can be the base address of the peripheral device where the memory file is intended to be written to.) ', param_parent=>'FILE_VIEW', ref_delay=> undef, new_status=>undef, loc=>'vertical'}; - my $row=0; - my $col=0; - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); - my $ok=def_image_button($path."icons/select.png",'OK'); - $table->attach ($ok, 2, 3,$row,$row+1,'shrink','shrink',2,2); - $ok-> signal_connect("clicked" => sub{ - fill_memory_array_from_file ($self,$file,$tview); - set_gui_status($self,'ref_file_view',1); - $window->destroy(); - }); - $window->add(add_widget_to_scrolled_win($table)); - $window->show_all; - - - } - - - + my ($self,$tview)=@_; + my $file; + my $title ='select bin file'; + my $dialog = gen_file_dialog ($title); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + $dialog->destroy; + $self->object_add_attribute('FILE_VIEW','IN_FILE',$file); + #get offset address; + my $window = def_popwin_size (30,20,'Get Offset Address','percent'); + my $table= def_table(2,10,FALSE); + my $d= + { label=>" Offset address (in byte): ", param_name=>'IN_FILE_OFFSET', type=>"Spin-button", default_val=>0, content=>'0,9999999999,1', info=>'The Wishbone bus offset address where the beginning of the memory bin file is written there (It can be the base address of the peripheral device where the memory file is intended to be written to.) ', param_parent=>'FILE_VIEW', ref_delay=> undef, new_status=>undef, loc=>'vertical'}; + my $row=0; + my $col=0; + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); + my $ok=def_image_button($path."icons/select.png",'OK'); + $table->attach ($ok, 2, 3,$row,$row+1,'shrink','shrink',2,2); + $ok-> signal_connect("clicked" => sub{ + fill_memory_array_from_file ($self,$file,$tview); + set_gui_status($self,'ref_file_view',1); + $window->destroy(); + }); + $window->add(add_widget_to_scrolled_win($table)); + $window->show_all; + } } - - - sub get_jtag_intfc_cmd { - my $self=shift; - - my $vendor = $self->object_get_attribute('CTRL','VENDOR'); - my $board = $self->object_get_attribute('CTRL','Board_Name'); - my $chain = $self->object_get_attribute('CTRL','JTAG_CHAIN'); - my $index = $self->object_get_attribute('CTRL','JTAG_INDEX'); - my $pronoc = get_project_dir(); - my $intfc = "$pronoc/mpsoc/boards/$vendor/$board/jtag_intfc.sh"; - #my $script = "$ENV{'PRONOC_WORK'}/tmp/script.bash"; - - my $t = ($vendor eq 'Xilinx') ? "-t $chain " : ""; - - my $cmd = "bash -c \"source $intfc; \\\$JTAG_INTFC $t -n $index"; - return $cmd; - + my $self=shift; + my $vendor = $self->object_get_attribute('CTRL','VENDOR'); + my $board = $self->object_get_attribute('CTRL','Board_Name'); + my $chain = $self->object_get_attribute('CTRL','JTAG_CHAIN'); + my $index = $self->object_get_attribute('CTRL','JTAG_INDEX'); + my $pronoc = get_project_dir(); + my $intfc = "$pronoc/mpsoc/boards/$vendor/$board/jtag_intfc.sh"; + #my $script = "$ENV{'PRONOC_WORK'}/tmp/script.bash"; + my $t = ($vendor eq 'Xilinx') ? "-t $chain " : ""; + my $cmd = "bash -c \"source $intfc; \\\$JTAG_INTFC $t -n $index"; + return $cmd; } - sub read_memory_array_from_device { - my ($self,$tview)=@_; - my $lower = $self->object_get_attribute('FILE_VIEW','READ_LBA'); - my $upper = $self->object_get_attribute('FILE_VIEW','READ_UBA'); - - $lower= sprintf("0x%x",$lower); - $upper= sprintf("0x%x",$upper); - - my $intfc = get_jtag_intfc_cmd($self); - #my $comand = "#!/bin/bash\n source $intfc\n \$JTAG_INTFC $t -n $index -s \"$lower\" -e \"$upper\" -r"; - my $cmd = "$intfc -s $lower -e $upper -r\""; - - #save_file ($script,$comand); - #chmod 0755, $script; - - #my $cmd = "bash -c \" $script \""; - add_info($tview,"$cmd\n"); - my $results =run_cmd_textview_errors($cmd,$tview); - return 1 if(!defined $results); - - - - my @nn = split (/###read data#\n/,$results); - if(!defined $nn[1]){ - add_colored_info($tview,"Got an Error:$results!\n",'red'); - return 1; - } - my @nums=split (/\n/,$nn[1]); - - $lower = $self->object_get_attribute('FILE_VIEW','READ_LBA'); - $lower>>=2; #change to word - foreach my $n ( @nums) { - $n='0'x( 8 - length $n).$n; - $memory{$lower }= $n; - $status{$lower}=1; #valid - $lower++; - - } -} - + my ($self,$tview)=@_; + my $lower = $self->object_get_attribute('FILE_VIEW','READ_LBA'); + my $upper = $self->object_get_attribute('FILE_VIEW','READ_UBA'); + $lower= sprintf("0x%x",$lower); + $upper= sprintf("0x%x",$upper); + my $intfc = get_jtag_intfc_cmd($self); + #my $comand = "#!/bin/bash\n source $intfc\n \$JTAG_INTFC $t -n $index -s \"$lower\" -e \"$upper\" -r"; + my $cmd = "$intfc -s $lower -e $upper -r\""; + #save_file ($script,$comand); + #chmod 0755, $script; + #my $cmd = "bash -c \" $script \""; + add_info($tview,"$cmd\n"); + my $results =run_cmd_textview_errors($cmd,$tview); + return 1 if(!defined $results); + my @nn = split (/###read data#\n/,$results); + if(!defined $nn[1]){ + add_colored_info($tview,"Got an Error:$results!\n",'red'); + return 1; + } + my @nums=split (/\n/,$nn[1]); + $lower = $self->object_get_attribute('FILE_VIEW','READ_LBA'); + $lower>>=2; #change to word + foreach my $n ( @nums) { + $n='0'x( 8 - length $n).$n; + $memory{$lower }= $n; + $status{$lower}=1; #valid + $lower++; + } +} sub print_32_bit_val { - my ($file,$v)=@_; - for (my $i= 24; $i >=0 ; $i-=8) { - my $byte= ($v >> $i ) & 0xFF; - print $file pack('C*',$byte); - #printf ("%02x\t",$byte); - } + my ($file,$v)=@_; + for (my $i= 24; $i >=0 ; $i-=8) { + my $byte= ($v >> $i ) & 0xFF; + print $file pack('C*',$byte); + #printf ("%02x\t",$byte); + } } - sub write_memory_array_from_device { - my ($self,$tview)=@_; - my $lower = $self->object_get_attribute('FILE_VIEW','READ_LBA'); - my $upper = $self->object_get_attribute('FILE_VIEW','READ_UBA'); - - my $tmp_bin= "$ENV{'PRONOC_WORK'}/tmp/tmp.bin"; - - - #create binfile - unlink $tmp_bin; - open(my $F,">$tmp_bin") or die("Unable to open file $tmp_bin, $!"); - #binmode($F); - my $warning; - my $n; - for (my $i=($lower>>2); $i< ($upper>>2); $i++){ - my $s =(defined $status{$i}) ? $status{$i} : 0; - if( $s==0) { - $n= 0; - $warning=$i; - } - else{ - $n= $memory{$i}; - $status{$i}=1; - } - print_32_bit_val ($F, hex($n)); - } - close ($F); - - - - - $lower= sprintf("0x%x",$lower); - $upper= sprintf("0x%x",$upper); - - - #my $comand = "#!/bin/bash\n source $intfc\n \$JTAG_INTFC $t -n $index -s \"$lower\" -e \"$upper\" -i $tmp_bin -c"; - - #save_file ($script,$comand); - #chmod 0755, $script; - - #my $cmd = "bash -c \" $script \""; - my $intfc = get_jtag_intfc_cmd($self); - my $cmd = "$intfc -s $lower -e $upper -i $tmp_bin -c\""; - - add_info($tview,"$cmd\n"); - my $results =run_cmd_textview_errors($cmd,$tview); - return 1 if(!defined $results); - - my @lines = split (/\n/, $results); - foreach my $line (@lines) { - add_colored_info($tview,"$line\n",'red') if ($line =~ /Error/); - } -} - - - - - - - - + my ($self,$tview)=@_; + my $lower = $self->object_get_attribute('FILE_VIEW','READ_LBA'); + my $upper = $self->object_get_attribute('FILE_VIEW','READ_UBA'); + my $tmp_bin= "$ENV{'PRONOC_WORK'}/tmp/tmp.bin"; + #create binfile + unlink $tmp_bin; + open(my $F,">$tmp_bin") or die("Unable to open file $tmp_bin, $!"); + #binmode($F); + my $warning; + my $n; + for (my $i=($lower>>2); $i< ($upper>>2); $i++){ + my $s =(defined $status{$i}) ? $status{$i} : 0; + if( $s==0) { + $n= 0; + $warning=$i; + } + else{ + $n= $memory{$i}; + $status{$i}=1; + } + print_32_bit_val ($F, hex($n)); + } + close ($F); + $lower= sprintf("0x%x",$lower); + $upper= sprintf("0x%x",$upper); + #my $comand = "#!/bin/bash\n source $intfc\n \$JTAG_INTFC $t -n $index -s \"$lower\" -e \"$upper\" -i $tmp_bin -c"; + #save_file ($script,$comand); + #chmod 0755, $script; + #my $cmd = "bash -c \" $script \""; + my $intfc = get_jtag_intfc_cmd($self); + my $cmd = "$intfc -s $lower -e $upper -i $tmp_bin -c\""; + add_info($tview,"$cmd\n"); + my $results =run_cmd_textview_errors($cmd,$tview); + return 1 if(!defined $results); + my @lines = split (/\n/, $results); + foreach my $line (@lines) { + add_colored_info($tview,"$line\n",'red') if ($line =~ /Error/); + } +} sub read_write_widget { - my ($self,$tview,$rw)=@_; - #get start & end addresses; - my $window = def_popwin_size (30,20,'Select Memory Boundary Addresses','percent'); - my $table= def_table(2,10,FALSE); - my $l ={ label=>" Lower-bound address (in byte): ", param_name=>'READ_LBA', type=>"Spin-button", default_val=>0, content=>'0,9999999999,1', info=>'The Wishbone bus offset address where the beginning of the memory bin file is written there (It can be the base address of the peripheral device where the memory file is intended to be written to.) ', param_parent=>'FILE_VIEW', ref_delay=> undef, new_status=>undef, loc=>'vertical'}; - my $u ={ label=>" Upper-bound address (in byte): ", param_name=>'READ_UBA', type=>"Spin-button", default_val=>0, content=>'0,9999999999,1', info=>'The Wishbone bus offset address where the end of the memory bin file is written there (It can be the base address of the peripheral device where the memory file is intended to be written to plus bin file size in byte.) ', param_parent=>'FILE_VIEW', ref_delay=> undef, new_status=>undef, loc=>'vertical'}; - my ($l_spin,$u_spin); - my $row=0; - my $col=0; - ($row,$col,$l_spin)=add_param_widget ($self, $l->{label}, $l->{param_name}, $l->{default_val}, $l->{type}, $l->{content}, $l->{info}, $table,$row,$col,1, $l->{param_parent}, $l->{ref_delay}, $l->{new_status}, $l->{loc}); - ($row,$col,$u_spin)=add_param_widget ($self, $u->{label}, $u->{param_name}, $u->{default_val}, $u->{type}, $u->{content}, $u->{info}, $table,$row,$col,1, $u->{param_parent}, $u->{ref_delay}, $l->{new_status}, $u->{loc}); - - $l_spin-> signal_connect("value_changed" => sub{ - my $lower=$l_spin->get_value(); - $u_spin->set_range ($lower, 9999999999); - - }); - - $u_spin-> signal_connect("value_changed" => sub{ - my $upper=$u_spin->get_value(); - $l_spin->set_range (0,$upper); - - }); - - - - - my $ok=def_image_button($path."icons/select.png",'OK'); - $table->attach ($ok, 2, 3,$row,$row+1,'shrink','shrink',2,2); - $ok-> signal_connect("clicked" => sub{ - my $vendor= $self->object_get_attribute('CTRL','VENDOR'); - my $load= show_gif("icons/load.gif"); - $table->attach ($load,1, 2, $row,$row+ 1,'shrink','shrink',0,0); - $table->show_all(); - read_memory_array_from_device ($self,$tview) if ($rw eq 'READ'); - write_memory_array_from_device ($self,$tview) if ($rw eq 'WRITE'); - set_gui_status($self,'ref_file_view',1); - $window->destroy(); - }); - $window->add(add_widget_to_scrolled_win($table)); - $window->show_all; -} - - - - - - + my ($self,$tview,$rw)=@_; + #get start & end addresses; + my $window = def_popwin_size (30,20,'Select Memory Boundary Addresses','percent'); + my $table= def_table(2,10,FALSE); + my $l ={ label=>" Lower-bound address (in byte): ", param_name=>'READ_LBA', type=>"Spin-button", default_val=>0, content=>'0,9999999999,1', info=>'The Wishbone bus offset address where the beginning of the memory bin file is written there (It can be the base address of the peripheral device where the memory file is intended to be written to.) ', param_parent=>'FILE_VIEW', ref_delay=> undef, new_status=>undef, loc=>'vertical'}; + my $u ={ label=>" Upper-bound address (in byte): ", param_name=>'READ_UBA', type=>"Spin-button", default_val=>0, content=>'0,9999999999,1', info=>'The Wishbone bus offset address where the end of the memory bin file is written there (It can be the base address of the peripheral device where the memory file is intended to be written to plus bin file size in byte.) ', param_parent=>'FILE_VIEW', ref_delay=> undef, new_status=>undef, loc=>'vertical'}; + my ($l_spin,$u_spin); + my $row=0; + my $col=0; + ($row,$col,$l_spin)=add_param_widget ($self, $l->{label}, $l->{param_name}, $l->{default_val}, $l->{type}, $l->{content}, $l->{info}, $table,$row,$col,1, $l->{param_parent}, $l->{ref_delay}, $l->{new_status}, $l->{loc}); + ($row,$col,$u_spin)=add_param_widget ($self, $u->{label}, $u->{param_name}, $u->{default_val}, $u->{type}, $u->{content}, $u->{info}, $table,$row,$col,1, $u->{param_parent}, $u->{ref_delay}, $l->{new_status}, $u->{loc}); + $l_spin-> signal_connect("value_changed" => sub{ + my $lower=$l_spin->get_value(); + $u_spin->set_range ($lower, 9999999999); + }); + $u_spin-> signal_connect("value_changed" => sub{ + my $upper=$u_spin->get_value(); + $l_spin->set_range (0,$upper); + }); + my $ok=def_image_button($path."icons/select.png",'OK'); + $table->attach ($ok, 2, 3,$row,$row+1,'shrink','shrink',2,2); + $ok-> signal_connect("clicked" => sub{ + my $vendor= $self->object_get_attribute('CTRL','VENDOR'); + my $load= show_gif("icons/load.gif"); + $table->attach ($load,1, 2, $row,$row+ 1,'shrink','shrink',0,0); + $table->show_all(); + read_memory_array_from_device ($self,$tview) if ($rw eq 'READ'); + write_memory_array_from_device ($self,$tview) if ($rw eq 'WRITE'); + set_gui_status($self,'ref_file_view',1); + $window->destroy(); + }); + $window->add(add_widget_to_scrolled_win($table)); + $window->show_all; +} sub read_write_bin_file { - my ($self,$tview)=@_; - my $table= def_table(2,10,FALSE); - my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); - add_widget_to_scrolled_win($table,$scrolled_win); - my @data; - - - my $MAX_X=$self-> object_get_attribute('FILE_VIEW','PAGE_MAX_X'); - $MAX_X=10 if (!defined $MAX_X); - my $MAX_Y=$self-> object_get_attribute('FILE_VIEW','PAGE_MAX_Y'); - $MAX_Y=10 if (!defined $MAX_Y); - my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); - $format= 'Decimal' if (!defined $format); - - - my $OFFSET=0; - - my $table1= def_table(2,10,FALSE); - - #$page_num= 0 if(!defined $page_num); - - - - - my $setting=def_image_button("icons/setting.png","setting"); - my $load=def_image_button("icons/download.png","Load File"); - my $read=def_image_button($path."icons/simulator.png","Read Memory"); - my $write=def_image_button($path."icons/write.png","Write Memory"); - my $clear=def_image_button($path."icons/clear.png"); - my $x=0; - - - $table->attach ($setting, $x, $x+1, 0, 1,'fill','fill',2,2);$x++; - $table->attach ($load, $x, $x+1 , 0, 1,'fill','fill',2,2);$x++; - $table->attach ($read, $x, $x+1 , 0, 1,'shrink','shrink',2,2); $x++; - $table->attach ($write, $x, $x+1 , 0, 1,'shrink','shrink',2,2); $x++; - $table->attach ($clear, $x, $x+1 , 0, 1,'shrink','shrink',2,2); $x++; - - add_param_widget ($self,"Page_num", 'FILE_VIEW', 0, "Spin-button", "0,999999,1", undef, $table,0, $x, 1, "R_PAGE_NUM",1,'ref_file_view'); - - my $page_num =$self->object_get_attribute("R_PAGE_NUM",'FILE_VIEW'); - - - - - $setting-> signal_connect("clicked" => sub{ - get_file_b_setting($self); - }); - - $load-> signal_connect("clicked" => sub{ - get_file_in_name($self,$tview); - }); - - $clear-> signal_connect("clicked" => sub{ - undef %memory; - undef %status; - set_gui_status($self,'ref_file_view',1); - }); - - $read-> signal_connect("clicked" => sub{ - read_write_widget($self,$tview,'READ'); - }); - - $write->signal_connect("clicked" => sub{ - read_write_widget($self,$tview,'WRITE'); - }); - - my $base_addr=$page_num*$MAX_X*$MAX_Y+$OFFSET; - - - #column address labels - for (my $y=1; $y<=$MAX_Y; $y++){ - my $addr=(($y-1) << 2); - $addr =($format eq 'Hexadecimal')? sprintf("%x", $addr) : $addr; - - my $l=gen_label_in_center (" $addr "); - $table1->attach ( $l, $y, $y+1 , 0, 1,'fill','fill',2,2); - } - - - #row address labels - for (my $x=1; $x<=$MAX_X; $x++){ - my $addr=$base_addr+($x-1) * $MAX_Y; - - $addr = ($format eq 'Hexadecimal')? sprintf("%x",($addr << 2)) : ($addr << 2); - - - my $l=gen_label_in_left (" $addr "); - $table1->attach ( $l, 0, 1 , $x, $x+1,'fill','fill',2,2); - } - - #entries - for (my $x=1; $x<=$MAX_X; $x++){ - for (my $y=1; $y<=$MAX_Y; $y++){ - - - my $state=0;# not modified - - my $addr =$base_addr+ (($x-1) * $MAX_Y ) + $y-1; - my $addr_tip=($format eq 'Hexadecimal')? sprintf("0x%x",($addr << 2)) : ($addr << 2); - - my $v= $memory{$addr}; - my $s = $status{$addr}; - - $v= "xxxxxxxx" if (!defined $v); - $s = 0 if (!defined $s); #0 dontcare - - - my $entry =gen_entry($v ); - - $entry->set_max_length (8); - $entry->set_width_chars(8); - set_tip($entry,"$addr_tip"); - $table1->attach ( $entry, $y, $y+1 , $x, $x+1,'fill','fill',2,2); - - if($s==2 ){ - #change color to red - entry_set_text_color($entry,11); - } - - $entry->signal_connect("changed" => sub{ - if($s==0 || $s==1 ){ - $status{$addr} =2;#modified - #change color to red - entry_set_text_color($entry,11); - - } - my $in = $entry->get_text(); - $memory{$addr}=$in; - $entry->set_text(remove_not_hex($in)); - - }); - - } - } - - - - - $table->attach ( $table1, 0, 20 , 1, 10,'fill','fill',2,2); - - $scrolled_win->show_all; - return $scrolled_win; - + my ($self,$tview)=@_; + my $table= def_table(2,10,FALSE); + my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); + add_widget_to_scrolled_win($table,$scrolled_win); + my @data; + my $MAX_X=$self-> object_get_attribute('FILE_VIEW','PAGE_MAX_X'); + $MAX_X=10 if (!defined $MAX_X); + my $MAX_Y=$self-> object_get_attribute('FILE_VIEW','PAGE_MAX_Y'); + $MAX_Y=10 if (!defined $MAX_Y); + my $format =$self-> object_get_attribute('FILE_VIEW','R_ADDR_FORMAT'); + $format= 'Decimal' if (!defined $format); + my $OFFSET=0; + my $table1= def_table(2,10,FALSE); + #$page_num= 0 if(!defined $page_num); + my $setting=def_image_button("icons/setting.png","setting"); + my $load=def_image_button("icons/download.png","Load File"); + my $read=def_image_button($path."icons/simulator.png","Read Memory"); + my $write=def_image_button($path."icons/write.png","Write Memory"); + my $clear=def_image_button($path."icons/clear.png"); + my $x=0; + $table->attach ($setting, $x, $x+1, 0, 1,'fill','fill',2,2);$x++; + $table->attach ($load, $x, $x+1 , 0, 1,'fill','fill',2,2);$x++; + $table->attach ($read, $x, $x+1 , 0, 1,'shrink','shrink',2,2); $x++; + $table->attach ($write, $x, $x+1 , 0, 1,'shrink','shrink',2,2); $x++; + $table->attach ($clear, $x, $x+1 , 0, 1,'shrink','shrink',2,2); $x++; + add_param_widget ($self,"Page_num", 'FILE_VIEW', 0, "Spin-button", "0,999999,1", undef, $table,0, $x, 1, "R_PAGE_NUM",1,'ref_file_view'); + my $page_num =$self->object_get_attribute("R_PAGE_NUM",'FILE_VIEW'); + $setting-> signal_connect("clicked" => sub{ + get_file_b_setting($self); + }); + $load-> signal_connect("clicked" => sub{ + get_file_in_name($self,$tview); + }); + $clear-> signal_connect("clicked" => sub{ + undef %memory; + undef %status; + set_gui_status($self,'ref_file_view',1); + }); + $read-> signal_connect("clicked" => sub{ + read_write_widget($self,$tview,'READ'); + }); + $write->signal_connect("clicked" => sub{ + read_write_widget($self,$tview,'WRITE'); + }); + my $base_addr=$page_num*$MAX_X*$MAX_Y+$OFFSET; + #column address labels + for (my $y=1; $y<=$MAX_Y; $y++){ + my $addr=(($y-1) << 2); + $addr =($format eq 'Hexadecimal')? sprintf("%x", $addr) : $addr; + my $l=gen_label_in_center (" $addr "); + $table1->attach ( $l, $y, $y+1 , 0, 1,'fill','fill',2,2); + } + #row address labels + for (my $x=1; $x<=$MAX_X; $x++){ + my $addr=$base_addr+($x-1) * $MAX_Y; + $addr = ($format eq 'Hexadecimal')? sprintf("%x",($addr << 2)) : ($addr << 2); + my $l=gen_label_in_left (" $addr "); + $table1->attach ( $l, 0, 1 , $x, $x+1,'fill','fill',2,2); + } + #entries + for (my $x=1; $x<=$MAX_X; $x++){ + for (my $y=1; $y<=$MAX_Y; $y++){ + my $state=0;# not modified + my $addr =$base_addr+ (($x-1) * $MAX_Y ) + $y-1; + my $addr_tip=($format eq 'Hexadecimal')? sprintf("0x%x",($addr << 2)) : ($addr << 2); + my $v= $memory{$addr}; + my $s = $status{$addr}; + $v= "xxxxxxxx" if (!defined $v); + $s = 0 if (!defined $s); #0 dontcare + my $entry =gen_entry($v ); + $entry->set_max_length (8); + $entry->set_width_chars(8); + set_tip($entry,"$addr_tip"); + $table1->attach ( $entry, $y, $y+1 , $x, $x+1,'fill','fill',2,2); + if($s==2 ){ + #change color to red + entry_set_text_color($entry,11); + } + $entry->signal_connect("changed" => sub{ + if($s==0 || $s==1 ){ + $status{$addr} =2;#modified + #change color to red + entry_set_text_color($entry,11); + } + my $in = $entry->get_text(); + $memory{$addr}=$in; + $entry->set_text(remove_not_hex($in)); + }); + } + } + $table->attach ( $table1, 0, 20 , 1, 10,'fill','fill',2,2); + $scrolled_win->show_all; + return $scrolled_win; } - - ############ -# main +# main ############ - - - sub source_probe_main { - my $self = __PACKAGE__->new(); - - - - set_gui_status($self,"ideal",0); - my $window = def_popwin_size (85,85,'Run time JTAG debug','percent'); - my ($sw,$tview) =create_txview();# a textveiw for showing the info, erro messages etc - my $ctrl = source_probe_ctrl($self,$tview); - my $sp= soure_probe_widgets ($self,$tview); - my $bin_f = read_write_bin_file($self,$tview); - #my $bin_ctrl = file_bin_ctrl($self,$tview); - - - my $h1 = gen_hpaned ($sp,0.35,$ctrl); - #my $h2 = gen_hpaned ($bin_f,0.55,$bin_ctrl); - my $v1 = gen_vpaned ($h1,0.2,$bin_f); - my $v2 = gen_vpaned ($v1,0.65,$sw); - - - - - - #check soc status every ? second. referesh device table if there is any changes - Glib::Timeout->add (100, sub{ + my $self = __PACKAGE__->new(); + set_gui_status($self,"ideal",0); + my $window = def_popwin_size (85,85,'Run time JTAG debug','percent'); + my ($sw,$tview) =create_txview();# a textveiw for showing the info, erro messages etc + my $ctrl = source_probe_ctrl($self,$tview); + my $sp= soure_probe_widgets ($self,$tview); + my $bin_f = read_write_bin_file($self,$tview); + #my $bin_ctrl = file_bin_ctrl($self,$tview); + my $h1 = gen_hpaned ($sp,0.35,$ctrl); + #my $h2 = gen_hpaned ($bin_f,0.55,$bin_ctrl); + my $v1 = gen_vpaned ($h1,0.2,$bin_f); + my $v2 = gen_vpaned ($v1,0.65,$sw); + #check soc status every ? second. referesh device table if there is any changes + Glib::Timeout->add (100, sub{ my ($state,$timeout)= get_gui_status($self); - if ($timeout>0){ $timeout--; - set_gui_status($self,$state,$timeout); + set_gui_status($self,$state,$timeout); } - elsif( $state ne "ideal" ){ + elsif( $state ne "ideal" ){ if($state eq 'ref_all') { - $sp->destroy(); - $sp= soure_probe_widgets ($self,$tview); - $bin_f->destroy(); - $bin_f = read_write_bin_file($self,$tview); - $h1-> pack1($sp, TRUE, TRUE); - $v1-> pack2($bin_f, TRUE, TRUE); - $v2-> show_all(); + $sp->destroy(); + $sp= soure_probe_widgets ($self,$tview); + $bin_f->destroy(); + $bin_f = read_write_bin_file($self,$tview); + $h1-> pack1($sp, TRUE, TRUE); + $v1-> pack2($bin_f, TRUE, TRUE); + $v2-> show_all(); } elsif ($state eq 'ref_file_view'){ - $bin_f->destroy(); - $bin_f = read_write_bin_file($self,$tview); - $v1-> pack2($bin_f, TRUE, TRUE); - $v2-> show_all(); - - - } - + $bin_f->destroy(); + $bin_f = read_write_bin_file($self,$tview); + $v1-> pack2($bin_f, TRUE, TRUE); + $v2-> show_all(); + } $ctrl->destroy(); $ctrl = source_probe_ctrl($self,$tview); $h1-> pack2($ctrl, TRUE, TRUE); - $v2-> show_all(); - set_gui_status($self,"ideal",0); - - - } - - return TRUE; - + $v2-> show_all(); + set_gui_status($self,"ideal",0); + } + return TRUE; } ); - - - - $window->add($v2); - $window->show_all(); - return $window; -} - - - + $window->add($v2); + $window->show_all(); + return $window; +} \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/soc_gen.pl b/mpsoc/perl_gui/lib/perl/soc_gen.pl index a89a0bc..f298e68 100755 --- a/mpsoc/perl_gui/lib/perl/soc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/soc_gen.pl @@ -8,15 +8,12 @@ use ip; use interface; use POSIX 'strtol'; - use File::Path; #use File::Find; use File::Copy; use File::Copy::Recursive qw(dircopy); use Cwd 'abs_path'; - - -require "widget.pl"; +require "widget.pl"; require "verilog_gen.pl"; require "readme_gen.pl"; require "hdr_file_gen.pl"; @@ -24,1980 +21,1501 @@ require "compile.pl"; require "software_editor.pl"; - - sub is_hex { local $!; return ! (POSIX::strtol($_[0], 16))[1]; - } - +} ############### # get_instance_id -# return an instance id which is the module name with a unique number +# return an instance id which is the module name with a unique number ############# sub get_instance_id{ - my ($soc,$category,$module)=@_; - my @id_list= $soc->soc_get_all_instances_of_module($category,$module); - my $id=0; - my $instance_id="$module$id"; - do { - $instance_id = "$module$id"; - $id++; - }while ((grep {$_ eq $instance_id} @id_list) ) ; - #print "$instance_id\n"; - return ($instance_id,$id); - + my ($soc,$category,$module)=@_; + my @id_list= $soc->soc_get_all_instances_of_module($category,$module); + my $id=0; + my $instance_id="$module$id"; + do { + $instance_id = "$module$id"; + $id++; + }while ((grep {$_ eq $instance_id} @id_list) ) ; + #print "$instance_id\n"; + return ($instance_id,$id); } - - ################# # add_module_to_soc ############### sub add_module_to_soc{ - my ($soc,$category,$module,$info)=@_; - my $ip = ip->lib_new (); - my ($instance_id,$id)= get_instance_id($soc,$category,$module); - - #add module instanance - my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); - - if($result == 0){ - my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; - show_info($info,$info_text); - return; - } - $soc->soc_add_instance_order($instance_id); - # Add IP version - my $v=$ip->ip_get($category,$module,"version"); - $v = 0 if(!defined $v); - #print "$v\n"; - $soc->object_add_attribute($instance_id,"version",$v); - # Read default parameter from lib and add them to soc - my %param_default= $ip->get_param_default($category,$module); - - my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); - if($rr == 0){ - my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist exist."; - show_info($info,$info_text); - return; - } - my @r=$ip->ip_get_param_order($category,$module); - $soc->soc_add_instance_param_order($instance_id,\@r); - - get_module_parameter($soc,$ip,$instance_id); - undef $ip; - set_gui_status($soc,"refresh_soc",0); -} + my ($soc,$category,$module,$info)=@_; + my $ip = ip->lib_new (); + my ($instance_id,$id)= get_instance_id($soc,$category,$module); + #add module instanance + my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); + if($result == 0){ + my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; + show_info($info,$info_text); + return; + } + $soc->soc_add_instance_order($instance_id); + # Add IP version + my $v=$ip->ip_get($category,$module,"version"); + $v = 0 if(!defined $v); + #print "$v\n"; + $soc->object_add_attribute($instance_id,"version",$v); + # Read default parameter from lib and add them to soc + my %param_default= $ip->get_param_default($category,$module); + my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); + if($rr == 0){ + my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist exist."; + show_info($info,$info_text); + return; + } + my @r=$ip->ip_get_param_order($category,$module); + $soc->soc_add_instance_param_order($instance_id,\@r); + get_module_parameter($soc,$ip,$instance_id); + undef $ip; + set_gui_status($soc,"refresh_soc",0); +} + ################ -# remove_instance_from_soc +# remove_instance_from_soc ################ sub remove_instance_from_soc{ - my ($soc,$instance_id)=@_; - $soc->soc_remove_instance($instance_id); - $soc->soc_remove_from_instance_order($instance_id); - set_gui_status($soc,"refresh_soc",0); -} - - + my ($soc,$instance_id)=@_; + $soc->soc_remove_instance($instance_id); + $soc->soc_remove_from_instance_order($instance_id); + set_gui_status($soc,"refresh_soc",0); +} ############### # get module_parameter ############## - sub get_module_parameter{ - my ($soc,$ip,$instance_id)=@_; - - #read module parameters from lib - my $module=$soc->soc_get_module($instance_id); - my $category=$soc->soc_get_category($instance_id); - my @parameters=$ip->ip_get_param_order($category,$module); - my $param_num = @parameters; - - #read soc parameters - my %param_value= $soc->soc_get_module_param($instance_id); - my %param_type= $soc->soc_get_module_param_type($instance_id); - my %new_param_value=%param_value; - - - - #gui - my $table_size = ($param_num<10) ? 10 : $param_num; - my $window = def_popwin_size(40,60, "Parameter setting for $module ",'percent'); - my $table = def_table($table_size, 7, FALSE); - - my $scrolled_win = add_widget_to_scrolled_win($table); - - my $row=0; - my $column=0; - - my $ok = def_image_button('icons/select.png','OK'); - - my $at0= 'shrink'; - my $at1= 'shrink'; - - $table->attach (gen_label_in_left("Parameter name"),0, 2, $row, $row+1,$at0,$at1,2,2); - $table->attach (gen_label_in_left("Value"),2, 3, $row, $row+1,$at0,$at1,2,2); - my $param_info='Define how parameter will be included in the SoC/Tile top module containing this IP core. If you define it as "Parameter", its value can be changed at SoC/tile instantiation time. So multiple different instancitaions of single SoC/tile can be used in MPSoC where each has its own parameter value'; - $table->attach (gen_label_help($param_info,"Type"),3, 4, $row, $row+1,$at0,$at1,2,2); - - $row++; - foreach my $p (@parameters){ - my ($default,$type,$content,$info,$vfile_param_type)= $ip->ip_get_parameter($category,$module,$p); - my $show = ($type ne "Fixed"); - if ($show){ - my $default_type= "Localparam"; - $default_type=$param_type{$p} if(defined $param_type{$p}); - my $combo = gen_combobox_object($soc,'current_module_param_type',$p,"Parameter,Localparam",$default_type,undef,undef); - $table->attach ($combo,3, 4, $row, $row+1,$at0,$at1,2,2) if($vfile_param_type ne 'Parameter' && $category ne 'NoC' && $p ne 'WB_Aw' ); - } - $default= $param_value{$p} if(defined $param_value{$p}); - ($row,$column)=add_param_widget($soc,$p,$p, $default,$type,$content,$info, $table,$row,$column,$show,'current_module_param',undef,undef,'vertical'); - - } - - - - - my $mtable = def_table(10, 1, FALSE); - - $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable->attach($ok,0,1,9,10,'expand','fill',2,2); - - $window->add ($mtable); - $window->show_all(); - - $ok-> signal_connect("clicked" => sub{ - $window->destroy; - #save new values - my $ref=$soc->object_get_attribute('current_module_param'); - if(defined $ref){ - %new_param_value=%{$ref} ; - $soc->soc_add_instance_param($instance_id,\%new_param_value); - } - $ref=$soc->object_get_attribute('current_module_param_type'); - if(defined $ref){ - %new_param_value=%{$ref} ; - $soc->soc_add_instance_param_type($instance_id,\%new_param_value); - } - - - - #check if wishbone address bus is parameterizable regenerate the addresses again - my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); - foreach my $plug (@plugs){ - if ($plug eq 'wb_slave'){ - my @nums=$soc->soc_list_plug_nums($instance_id,$plug); - foreach my $plug_num (@nums){ - my ($addr_connect,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$plug_num); - if($connect_id ne 'IO' && $connect_id ne 'NC'){ - #print "$connect_id : soc_get_plug_addr ($instance_id,$plug,$plug_num)\n"; - #remove old wb addr - $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,undef,undef); - #get base and address width - my ($addr , $width)=$soc->soc_get_plug_addr ($instance_id,$plug,$plug_num); - #check if width is a parameter - my $val= get_parameter_final_value($soc,$instance_id,$width); - $width= $val if(defined $val); - #allocate new address in $connect_id - my ($base,$end)=get_wb_address($soc,$connect_id,$addr,$width); - if(defined $base){#save it - $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,$base,$end); - } - } - }#plug_num - }#if - }#plugs - $soc->object_add_attribute('current_module_param',undef,undef); - $soc->object_add_attribute('current_module_param_type',undef,undef); - set_gui_status($soc,"refresh_soc",0); - - }); + my ($soc,$ip,$instance_id)=@_; + #read module parameters from lib + my $module=$soc->soc_get_module($instance_id); + my $category=$soc->soc_get_category($instance_id); + my @parameters=$ip->ip_get_param_order($category,$module); + my $param_num = @parameters; + #read soc parameters + my %param_value= $soc->soc_get_module_param($instance_id); + my %param_type= $soc->soc_get_module_param_type($instance_id); + my %new_param_value=%param_value; + #gui + my $table_size = ($param_num<10) ? 10 : $param_num; + my $window = def_popwin_size(40,60, "Parameter setting for $module ",'percent'); + my $table = def_table($table_size, 7, FALSE); + my $scrolled_win = add_widget_to_scrolled_win($table); + my $row=0; + my $column=0; + my $ok = def_image_button('icons/select.png','OK'); + my $at0= 'shrink'; + my $at1= 'shrink'; + $table->attach (gen_label_in_left("Parameter name"),0, 2, $row, $row+1,$at0,$at1,2,2); + $table->attach (gen_label_in_left("Value"),2, 3, $row, $row+1,$at0,$at1,2,2); + my $param_info='Define how parameter will be included in the SoC/Tile top module containing this IP core. If you define it as "Parameter", its value can be changed at SoC/tile instantiation time. So multiple different instancitaions of single SoC/tile can be used in MPSoC where each has its own parameter value'; + $table->attach (gen_label_help($param_info,"Type"),3, 4, $row, $row+1,$at0,$at1,2,2); + $row++; + foreach my $p (@parameters){ + my ($default,$type,$content,$info,$vfile_param_type)= $ip->ip_get_parameter($category,$module,$p); + my $show = ($type ne "Fixed"); + if ($show){ + my $default_type= "Localparam"; + $default_type=$param_type{$p} if(defined $param_type{$p}); + my $combo = gen_combobox_object($soc,'current_module_param_type',$p,"Parameter,Localparam",$default_type,undef,undef); + $table->attach ($combo,3, 4, $row, $row+1,$at0,$at1,2,2) if($vfile_param_type ne 'Parameter' && $category ne 'NoC' && $p ne 'WB_Aw' ); + } + $default= $param_value{$p} if(defined $param_value{$p}); + ($row,$column)=add_param_widget($soc,$p,$p, $default,$type,$content,$info, $table,$row,$column,$show,'current_module_param',undef,undef,'vertical'); + } + my $mtable = def_table(10, 1, FALSE); + $mtable->attach_defaults($scrolled_win,0,1,0,9); + $mtable->attach($ok,0,1,9,10,'expand','fill',2,2); + $window->add ($mtable); + $window->show_all(); + $ok-> signal_connect("clicked" => sub{ + $window->destroy; + #save new values + my $ref=$soc->object_get_attribute('current_module_param'); + if(defined $ref){ + %new_param_value=%{$ref} ; + $soc->soc_add_instance_param($instance_id,\%new_param_value); + } + $ref=$soc->object_get_attribute('current_module_param_type'); + if(defined $ref){ + %new_param_value=%{$ref} ; + $soc->soc_add_instance_param_type($instance_id,\%new_param_value); + } + #check if wishbone address bus is parameterizable regenerate the addresses again + my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); + foreach my $plug (@plugs){ + if ($plug eq 'wb_slave'){ + my @nums=$soc->soc_list_plug_nums($instance_id,$plug); + foreach my $plug_num (@nums){ + my ($addr_connect,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$plug_num); + if($connect_id ne 'IO' && $connect_id ne 'NC'){ + #print "$connect_id : soc_get_plug_addr ($instance_id,$plug,$plug_num)\n"; + #remove old wb addr + $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,undef,undef); + #get base and address width + my ($addr , $width)=$soc->soc_get_plug_addr ($instance_id,$plug,$plug_num); + #check if width is a parameter + my $val= get_parameter_final_value($soc,$instance_id,$width); + $width= $val if(defined $val); + #allocate new address in $connect_id + my ($base,$end)=get_wb_address($soc,$connect_id,$addr,$width); + if(defined $base){#save it + $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,$base,$end); + } + } + }#plug_num + }#if + }#plugs + $soc->object_add_attribute('current_module_param',undef,undef); + $soc->object_add_attribute('current_module_param_type',undef,undef); + set_gui_status($soc,"refresh_soc",0); + }); } - - ############ # param_box # ############ - - - sub param_box{ - my ($param, $default,$type,$content,$info, $value)=@_; - my $box=def_hbox(TRUE,0); - my $label =gen_label_in_left($param); - $box->pack_start($label,FALSE,FALSE,3); - - if ($type eq "Entry"){ - my $entry=gen_entry($default); - $box->pack_start($entry,FALSE,FALSE,3); - - } - elsif ($type eq "Combo-box"){ - my @combo_list=split(/\s*,\s*/,$content); - my $pos=get_item_pos($default, @combo_list); - my $combo=gen_combo(\@combo_list, $pos); - $box->pack_start($combo,FALSE,FALSE,3); - } - elsif ($type eq "Spin-button"){ - my ($min,$max,$step)=split(/\s*,\s*/,$content); - $default=~ s/\D//g; - $min=~ s/\D//g; - $max=~ s/\D//g; - $step=~ s/\D//g; - my $spin=gen_spin($min,$max,$step); - $box->pack_start($spin,FALSE,FALSE,3); - # $box=def_label_spin_help_box ($param,$info, $value,$min,$max,$step, 2); - } - - return $box; +sub param_box{ + my ($param, $default,$type,$content,$info, $value)=@_; + my $box=def_hbox(TRUE,0); + my $label =gen_label_in_left($param); + $box->pack_start($label,FALSE,FALSE,3); + if ($type eq "Entry"){ + my $entry=gen_entry($default); + $box->pack_start($entry,FALSE,FALSE,3); + } + elsif ($type eq "Combo-box"){ + my @combo_list=split(/\s*,\s*/,$content); + my $pos=get_item_pos($default, @combo_list); + my $combo=gen_combo(\@combo_list, $pos); + $box->pack_start($combo,FALSE,FALSE,3); + } + elsif ($type eq "Spin-button"){ + my ($min,$max,$step)=split(/\s*,\s*/,$content); + $default=~ s/\D//g; + $min=~ s/\D//g; + $max=~ s/\D//g; + $step=~ s/\D//g; + my $spin=gen_spin($min,$max,$step); + $box->pack_start($spin,FALSE,FALSE,3); + # $box=def_label_spin_help_box ($param,$info, $value,$min,$max,$step, 2); + } + return $box; } - ############### # get_mathced_socket_pos ############### - - sub get_mathced_socket_pos{ - my ($soc,$instance_id,$plug,$plug_num,@connettions)=@_; - my ($id,$socket,$num)=$soc->soc_get_module_plug_conection($instance_id,$plug,$plug_num); - my $pos=($id eq "IO")? 0: (scalar @connettions)-1; - if($id ne "IO" && $id ne 'NC'){ - my $name= $soc->soc_get_instance_name($id); - if (defined $name){ - my $connect="$name\:$socket\[$num]"; - if( grep {$_ eq $connect} @connettions){$pos = get_scolar_pos($connect,@connettions);} - } - else { - $soc->soc_add_instance_plug_conection($instance_id,$plug,$plug_num,"IO"); - - } - } - return $pos; + my ($soc,$instance_id,$plug,$plug_num,@connettions)=@_; + my ($id,$socket,$num)=$soc->soc_get_module_plug_conection($instance_id,$plug,$plug_num); + my $pos=($id eq "IO")? 0: (scalar @connettions)-1; + if($id ne "IO" && $id ne 'NC'){ + my $name= $soc->soc_get_instance_name($id); + if (defined $name){ + my $connect="$name\:$socket\[$num]"; + if( grep {$_ eq $connect} @connettions){$pos = get_scolar_pos($connect,@connettions);} + } + else { + $soc->soc_add_instance_plug_conection($instance_id,$plug,$plug_num,"IO"); + } + } + return $pos; } - ############## -# gen_dev_box +# gen_dev_box ############## - sub gen_instance{ - my ($soc,$ip,$infc,$instance_id,$info,$table,$offset)=@_; - - - -# my $box= def_vbox (FALSE,0); - -# my $table = def_table(3,5,TRUE); - my $data_in; - -#column 1 - #module name - my $module=$soc->soc_get_module($instance_id); - my $category=$soc->soc_get_category($instance_id); - my $module_name_label=box_label(FALSE,0,$module); - my $box0=def_hbox(FALSE,5); - $box0->pack_start( $module_name_label, FALSE, FALSE, 3); - - #module pdf - my $pdf=$soc->soc_get_description_pdf($instance_id); - if(defined $pdf){ - my $b=def_image_button('icons/evince-icon.png'); - $box0->pack_start( $b, FALSE, FALSE, 3); - $b->signal_connect ("clicked" => sub{ - my $dir = Cwd::getcwd(); - my $project_dir = abs_path("$dir/../../"); #mpsoc directory address - #print "path ${project_dir}$pdf\n"; - if (-f "${project_dir}$pdf"){ - system qq (xdg-open ${project_dir}$pdf); - }elsif (-f "$pdf"){ - system qq (xdg-open $pdf); - }else{ - message_dialog("Error! $pdf or ${project_dir}$pdf did not find!\n",'error'); - } - - }); - - } - $table->attach ($box0,0,1,$offset+0,$offset+1,'expand','shrink',2,2); - - #parameter setting button - my $param_button = def_image_button('icons/setting.png','Setting'); - my $box1=def_hbox(FALSE,5); - my $up=def_image_button("icons/up_sim.png"); - $box1->pack_start( $up, FALSE, FALSE, 3); - $box1->pack_start($param_button, FALSE, FALSE,3); - $table->attach ($box1 ,0,1,$offset+1,$offset+2,'expand','shrink',2,2); - $param_button->signal_connect (clicked => sub{ - get_module_parameter($soc,$ip,$instance_id); - - }); - $up->signal_connect (clicked => sub{ - $soc->soc_decrease_instance_order($instance_id); - set_gui_status($soc,"refresh_soc",0); - - }); - - #remove button - #my ($box2,$cancel_button) = button_box("Remove"); - - my $cancel_button=def_image_button('icons/cancel.png','Remove'); - my $box2=def_hbox(FALSE,5); - - my $dwn=def_image_button("icons/down_sim.png"); - $box2->pack_start( $dwn, FALSE, FALSE, 3); - $box2->pack_start($cancel_button, FALSE, FALSE,3) ; - $table->attach ($box2,0,1,$offset+2,$offset+3,'expand','shrink',2,2); - $cancel_button->signal_connect (clicked => sub{ - remove_instance_from_soc($soc,$instance_id); - }); - - $dwn->signal_connect (clicked => sub{ - $soc->soc_increase_instance_order($instance_id); - set_gui_status($soc,"refresh_soc",0); - - }); - - #instance name - my $instance_name=$soc->soc_get_instance_name($instance_id); - my $instance_label=gen_label_in_left(" Instance name"); - my $instance_entry = gen_entry($instance_name); - - $table->attach ($instance_label,1,2,$offset+0,$offset+1,'expand','shrink',2,2); - #$table->attach_defaults ($instance_entry,1,2,$offset+1,$offset+2); - - - my $enter= def_image_button("icons/enter.png"); - - my $box=def_pack_hbox(FALSE,0,$instance_entry ); - $table->attach ($box,1,2,$offset+1,$offset+2,'expand','shrink',2,2); - - my ($old_v,$new_v)= get_old_new_ip_version ($soc,$ip,$instance_id); - if($old_v != $new_v){ - my $warn=def_image_button("icons/warning.png"); - $table->attach ($warn,1,2,$offset+2,$offset+3,'expand','shrink',2,2); #$box2->pack_start($warn, FALSE, FALSE, 3); - $warn->signal_connect (clicked => sub{ - message_dialog("Warning: ${module}'s version (V.$old_v) mismatches with the one existing in library (V.$new_v). The generated system may not work correctly. Please remove and then add $module again to update it with current version") - - }); - - - } - - - $instance_entry->signal_connect ("activate" => sub{ - #print "changed\n"; - my $new_name=$instance_entry->get_text(); - #check if instance name exist in soc - set_gui_status($soc,"refresh_soc",1) if($instance_name eq $new_name ); - my @instance_names= $soc->soc_get_all_instance_name(); - if( grep {$_ eq $new_name} @instance_names){ - print "$new_name exist\n"; - } - else { - #add instance name to soc - $soc->soc_set_instance_name($instance_id,$new_name); - - set_gui_status($soc,"refresh_soc",1); - - } - }); - my $change=0; - $instance_entry->signal_connect ("changed" => sub{ - if($change ==0){ - $box->pack_start( $enter, FALSE, FALSE, 0); - $box->show_all; - $change=1; - } - - }); - - $enter->signal_connect ("clicked" => sub{ - my $new_name=$instance_entry->get_text(); - #check if instance name exist in soc - set_gui_status($soc,"refresh_soc",1) if($instance_name eq $new_name ); - my @instance_names= $soc->soc_get_all_instance_name(); - if( grep {$_ eq $new_name} @instance_names){ - print "$new_name exist\n"; - } - else { - #add instance name to soc - $soc->soc_set_instance_name($instance_id,$new_name); - - set_gui_status($soc,"refresh_soc",1); - - } - - - }); - - - - #interface_pluges - my %plugs = $ip->get_module_plugs_value($category,$module); - - ##print "******* %plug=get_module_plugs_value($category,$module)*************\n"; - #print Dumper (\%$ip); - my $row=0; - foreach my $plug (sort keys %plugs) { - #print "******* $plug *************\n"; - my $plug_num= $plugs{$plug}; - for (my $k=0;$k<$plug_num;$k++){ - - my @connettions=("IO"); - my @connettions_name=("IO"); - - my ($connection_num,$matched_soket)= $infc->get_plug($plug); - - - - my %connect_list= $soc->get_modules_have_this_socket($matched_soket); - foreach my $id(sort keys %connect_list ){ - if($instance_id ne $id){ # assume its forbidden to connect the socket and plug of same ip to each other - #generate socket list - my $name=$soc->soc_get_instance_name($id); - #check if its a number or parameter - my $param=$connect_list{$id}; - my $value=$soc->soc_get_module_param_value($id,$param); - my $array_name=0; - if ( !length( $value || '' )) { - $value=$param; - $array_name=1; - - - }; - for(my $i=0; $i<$value; $i++){ - my $s= "$name\:$matched_soket\[$i]"; - push (@connettions,$s); - - # show sockets with their connected plugs - my ($type_t,$value_t,$connection_num_t)=$soc->soc_get_socket_of_instance($id,$matched_soket); - - my $cc=find_connection($soc,$id,$matched_soket,$i); - $cc= (!defined $cc )? '': - ($cc eq "$instance_id:$plug\[$k\]" || $connection_num_t eq 'multi connection')? '': "->$cc"; - - if($array_name eq 0){ - my $n= $soc->soc_get_socket_name($id,$matched_soket, 0); - - $n = (!defined $n)? $s:"$name\:$n\[$i]"; - $n = "$n$cc"; - push (@connettions_name,"$n"); - - }else{ - my $n= $soc->soc_get_socket_name($id,$matched_soket, $i); - - $n = (!defined $n)? $s:"$name\:$n"; - $n = "$n$cc"; - push (@connettions_name,"$n"); - - } - - } - - } - - - } - push (@connettions,"NC"); - push (@connettions_name,"NC"); - - #print "connection is $connect for $p\n"; - #my @socket_list= $soc_get_sockets(); - - - my $pos= get_mathced_socket_pos($soc,$instance_id,$plug,$k,@connettions); - - #plug name - my $plug_name= $soc->soc_get_plug_name($instance_id,$plug,$k); - if(! defined $plug_name ){$plug_name=($plug_num>1)?"$plug\[$k\]":$plug} - $plug_name=" $plug_name "; - my($plug_box, $plug_combo)= def_h_labeled_combo_scaled($plug_name,\@connettions_name,$pos,1,2); - - #if($row>2){$table->resize ($row, 2);} - $table->attach ($plug_box,2,5,$row+$offset,$row+$offset+1,'fill','fill',2,2); $row++; - - my $plug_num=$k; - my @ll=($soc,$instance_id,$plug,$info,$plug_num); - $plug_combo->signal_connect (changed => sub{ - my $self=shift; - my $ref= shift; - my($soc,$instance_id,$plug,$info,$plug_num) = @{$ref}; - my $connect_name=$plug_combo->get_active_text(); - my $pos=get_item_pos($connect_name, @connettions_name); - my $connect=$connettions[$pos]; - - - - my($intance_name,$socket,$num)= split("[:\[ \\]]", $connect); - my $id=$intance_name;# default IO or NC - if(($intance_name ne 'IO') && ($intance_name ne 'NC')){ - - $id=$soc->soc_get_instance_id($intance_name); - my ($type,$value,$connection_num)=$soc->soc_get_socket_of_instance($id,$socket); - #print "\$$connection_num=$connection_num\n"; - if($connection_num eq 'single connection'){# disconnect other plug from this soket - my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$socket,$num); - my %connected_plugs=%$ref1; - my %connected_plug_nums=%$ref2; - foreach my $p (sort keys %connected_plugs) { - #%pp{$instance_id}=$plug - $soc->soc_add_instance_plug_conection($p,$connected_plugs{$p},$connected_plug_nums{$p},'IO'); - my $info_text="$id\:$socket\[$num\] support only single connection. The previous connection to $p:$connected_plugs{$p}\[$connected_plug_nums{$p}] has been removed."; - show_info($info, $info_text); - } - - } - } - #print "$id \n $connect \n$num\n"; - #my @rr=$soc->soc_get_all_plugs_of_an_instance($id); - - - - - $soc->soc_add_instance_plug_conection($instance_id,$plug,$plug_num,$id,$socket,$num); - - #get address for wishbone slave port - if ($plug eq 'wb_slave'){ - #remove old wb addr - $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,undef,undef); - - #get base and address width - my ($addr , $width)=$soc->soc_get_plug_addr ($instance_id,$plug,$plug_num); - - #check if width is a parameter - my $val= get_parameter_final_value($soc,$instance_id,$width); - #print "my $val= get_parameter_final_value($soc,$instance_id,$width);\n"; - $width= $val if(defined $val); - - - #allocate new address in $id - my ($base,$end)=get_wb_address($soc,$id,$addr,$width); - if(defined $base){#save it - #print "($base,$end)\n"; - $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,$base,$end); - } - - - #$id - } - # "$name\:$connect\[$i]"; - - - - set_gui_status($soc,"refresh_soc",0); - },\@ll); - - - }#for $plug_num - - }#foreach plug - - - if($row<3) {$row=3;} - add_Hsep_to_table ($table,0,5,$row+$offset);$row++; - - return ($offset+$row); -} - + my ($soc,$ip,$infc,$instance_id,$info,$table,$offset)=@_; +# my $box= def_vbox (FALSE,0); +# my $table = def_table(3,5,TRUE); + my $data_in; +#column 1 + #module name + my $module=$soc->soc_get_module($instance_id); + my $category=$soc->soc_get_category($instance_id); + my $module_name_label=box_label(FALSE,0,$module); + my $box0=def_hbox(FALSE,5); + $box0->pack_start( $module_name_label, FALSE, FALSE, 3); + #module pdf + my $pdf=$soc->soc_get_description_pdf($instance_id); + if(defined $pdf){ + my $b=def_image_button('icons/evince-icon.png'); + $box0->pack_start( $b, FALSE, FALSE, 3); + $b->signal_connect ("clicked" => sub{ + my $dir = Cwd::getcwd(); + my $project_dir = abs_path("$dir/../../"); #mpsoc directory address + #print "path ${project_dir}$pdf\n"; + if (-f "${project_dir}$pdf"){ + system qq (xdg-open ${project_dir}$pdf); + }elsif (-f "$pdf"){ + system qq (xdg-open $pdf); + }else{ + message_dialog("Error! $pdf or ${project_dir}$pdf did not find!\n",'error'); + } + }); + } + $table->attach ($box0,0,1,$offset+0,$offset+1,'expand','shrink',2,2); + #parameter setting button + my $param_button = def_image_button('icons/setting.png','Setting'); + my $box1=def_hbox(FALSE,5); + my $up=def_image_button("icons/up_sim.png"); + $box1->pack_start( $up, FALSE, FALSE, 3); + $box1->pack_start($param_button, FALSE, FALSE,3); + $table->attach ($box1 ,0,1,$offset+1,$offset+2,'expand','shrink',2,2); + $param_button->signal_connect (clicked => sub{ + get_module_parameter($soc,$ip,$instance_id); + }); + $up->signal_connect (clicked => sub{ + $soc->soc_decrease_instance_order($instance_id); + set_gui_status($soc,"refresh_soc",0); + }); + #remove button + #my ($box2,$cancel_button) = button_box("Remove"); + my $cancel_button=def_image_button('icons/cancel.png','Remove'); + my $box2=def_hbox(FALSE,5); + my $dwn=def_image_button("icons/down_sim.png"); + $box2->pack_start( $dwn, FALSE, FALSE, 3); + $box2->pack_start($cancel_button, FALSE, FALSE,3) ; + $table->attach ($box2,0,1,$offset+2,$offset+3,'expand','shrink',2,2); + $cancel_button->signal_connect (clicked => sub{ + remove_instance_from_soc($soc,$instance_id); + }); + $dwn->signal_connect (clicked => sub{ + $soc->soc_increase_instance_order($instance_id); + set_gui_status($soc,"refresh_soc",0); + }); + #instance name + my $instance_name=$soc->soc_get_instance_name($instance_id); + my $instance_label=gen_label_in_left(" Instance name"); + my $instance_entry = gen_entry($instance_name); + $table->attach ($instance_label,1,2,$offset+0,$offset+1,'expand','shrink',2,2); + #$table->attach_defaults ($instance_entry,1,2,$offset+1,$offset+2); + my $enter= def_image_button("icons/enter.png"); + my $box=def_pack_hbox(FALSE,0,$instance_entry ); + $table->attach ($box,1,2,$offset+1,$offset+2,'expand','shrink',2,2); + my ($old_v,$new_v)= get_old_new_ip_version ($soc,$ip,$instance_id); + if($old_v != $new_v){ + my $warn=def_image_button("icons/warning.png"); + $table->attach ($warn,1,2,$offset+2,$offset+3,'expand','shrink',2,2); #$box2->pack_start($warn, FALSE, FALSE, 3); + $warn->signal_connect (clicked => sub{ + message_dialog("Warning: ${module}'s version (V.$old_v) mismatches with the one existing in library (V.$new_v). The generated system may not work correctly. Please remove and then add $module again to update it with current version") + }); + } + $instance_entry->signal_connect ("activate" => sub{ + #print "changed\n"; + my $new_name=$instance_entry->get_text(); + #check if instance name exist in soc + set_gui_status($soc,"refresh_soc",1) if($instance_name eq $new_name ); + my @instance_names= $soc->soc_get_all_instance_name(); + if( grep {$_ eq $new_name} @instance_names){ + print "$new_name exist\n"; + } + else { + #add instance name to soc + $soc->soc_set_instance_name($instance_id,$new_name); + set_gui_status($soc,"refresh_soc",1); + } + }); + my $change=0; + $instance_entry->signal_connect ("changed" => sub{ + if($change ==0){ + $box->pack_start( $enter, FALSE, FALSE, 0); + $box->show_all; + $change=1; + } + }); + $enter->signal_connect ("clicked" => sub{ + my $new_name=$instance_entry->get_text(); + #check if instance name exist in soc + set_gui_status($soc,"refresh_soc",1) if($instance_name eq $new_name ); + my @instance_names= $soc->soc_get_all_instance_name(); + if( grep {$_ eq $new_name} @instance_names){ + print "$new_name exist\n"; + } + else { + #add instance name to soc + $soc->soc_set_instance_name($instance_id,$new_name); + set_gui_status($soc,"refresh_soc",1); + } + }); + #interface_pluges + my %plugs = $ip->get_module_plugs_value($category,$module); + ##print "******* %plug=get_module_plugs_value($category,$module)*************\n"; + #print Dumper (\%$ip); + my $row=0; + foreach my $plug (sort keys %plugs) { + #print "******* $plug *************\n"; + my $plug_num= $plugs{$plug}; + for (my $k=0;$k<$plug_num;$k++){ + my @connettions=("IO"); + my @connettions_name=("IO"); + my ($connection_num,$matched_soket)= $infc->get_plug($plug); + my %connect_list= $soc->get_modules_have_this_socket($matched_soket); + foreach my $id(sort keys %connect_list ){ + if($instance_id ne $id){ # assume its forbidden to connect the socket and plug of same ip to each other + #generate socket list + my $name=$soc->soc_get_instance_name($id); + #check if its a number or parameter + my $param=$connect_list{$id}; + my $value=$soc->soc_get_module_param_value($id,$param); + my $array_name=0; + if ( !length( $value || '' )) { + $value=$param; + $array_name=1; + }; + for(my $i=0; $i<$value; $i++){ + my $s= "$name\:$matched_soket\[$i]"; + push (@connettions,$s); + # show sockets with their connected plugs + my ($type_t,$value_t,$connection_num_t)=$soc->soc_get_socket_of_instance($id,$matched_soket); + my $cc=find_connection($soc,$id,$matched_soket,$i); + $cc= (!defined $cc )? '': + ($cc eq "$instance_id:$plug\[$k\]" || $connection_num_t eq 'multi connection')? '': "->$cc"; + if($array_name eq 0){ + my $n= $soc->soc_get_socket_name($id,$matched_soket, 0); + $n = (!defined $n)? $s:"$name\:$n\[$i]"; + $n = "$n$cc"; + push (@connettions_name,"$n"); + }else{ + my $n= $soc->soc_get_socket_name($id,$matched_soket, $i); + $n = (!defined $n)? $s:"$name\:$n"; + $n = "$n$cc"; + push (@connettions_name,"$n"); + } + } + } + } + push (@connettions,"NC"); + push (@connettions_name,"NC"); + #print "connection is $connect for $p\n"; + #my @socket_list= $soc_get_sockets(); + my $pos= get_mathced_socket_pos($soc,$instance_id,$plug,$k,@connettions); + #plug name + my $plug_name= $soc->soc_get_plug_name($instance_id,$plug,$k); + if(! defined $plug_name ){$plug_name=($plug_num>1)?"$plug\[$k\]":$plug} + $plug_name=" $plug_name "; + my($plug_box, $plug_combo)= def_h_labeled_combo_scaled($plug_name,\@connettions_name,$pos,1,2); + #if($row>2){$table->resize ($row, 2);} + $table->attach ($plug_box,2,5,$row+$offset,$row+$offset+1,'fill','fill',2,2); $row++; + my $plug_num=$k; + my @ll=($soc,$instance_id,$plug,$info,$plug_num); + $plug_combo->signal_connect (changed => sub{ + my $self=shift; + my $ref= shift; + my($soc,$instance_id,$plug,$info,$plug_num) = @{$ref}; + my $connect_name=$plug_combo->get_active_text(); + my $pos=get_item_pos($connect_name, @connettions_name); + my $connect=$connettions[$pos]; + my($intance_name,$socket,$num)= split("[:\[ \\]]", $connect); + my $id=$intance_name;# default IO or NC + if(($intance_name ne 'IO') && ($intance_name ne 'NC')){ + $id=$soc->soc_get_instance_id($intance_name); + my ($type,$value,$connection_num)=$soc->soc_get_socket_of_instance($id,$socket); + #print "\$$connection_num=$connection_num\n"; + if($connection_num eq 'single connection'){# disconnect other plug from this soket + my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$socket,$num); + my %connected_plugs=%$ref1; + my %connected_plug_nums=%$ref2; + foreach my $p (sort keys %connected_plugs) { + #%pp{$instance_id}=$plug + $soc->soc_add_instance_plug_conection($p,$connected_plugs{$p},$connected_plug_nums{$p},'IO'); + my $info_text="$id\:$socket\[$num\] support only single connection. The previous connection to $p:$connected_plugs{$p}\[$connected_plug_nums{$p}] has been removed."; + show_info($info, $info_text); + } + } + } + #print "$id \n $connect \n$num\n"; + #my @rr=$soc->soc_get_all_plugs_of_an_instance($id); + $soc->soc_add_instance_plug_conection($instance_id,$plug,$plug_num,$id,$socket,$num); + #get address for wishbone slave port + if ($plug eq 'wb_slave'){ + #remove old wb addr + $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,undef,undef); + #get base and address width + my ($addr , $width)=$soc->soc_get_plug_addr ($instance_id,$plug,$plug_num); + #check if width is a parameter + my $val= get_parameter_final_value($soc,$instance_id,$width); + #print "my $val= get_parameter_final_value($soc,$instance_id,$width);\n"; + $width= $val if(defined $val); + #allocate new address in $id + my ($base,$end)=get_wb_address($soc,$id,$addr,$width); + if(defined $base){#save it + #print "($base,$end)\n"; + $soc->soc_add_plug_base_addr($instance_id,$plug,$plug_num,$base,$end); + } + #$id + } + # "$name\:$connect\[$i]"; + set_gui_status($soc,"refresh_soc",0); + },\@ll); + }#for $plug_num + }#foreach plug + if($row<3) {$row=3;} + add_Hsep_to_table ($table,0,5,$row+$offset);$row++; + return ($offset+$row); +} sub find_connection{ - my ($soc,$id,$socket,$num)=@_; - my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$socket,$num); - my %connected_plugs=%$ref1; - my %connected_plug_nums=%$ref2; - my $c; - foreach my $p (sort keys %connected_plugs) { - $c="$p:$connected_plugs{$p}\[$connected_plug_nums{$p}]" ; - #print "($instance_id,$plug,$plug_num);($p:$connected_plugs{$p}\[$connected_plug_nums{$p})\n"; - } - return $c; - + my ($soc,$id,$socket,$num)=@_; + my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$socket,$num); + my %connected_plugs=%$ref1; + my %connected_plug_nums=%$ref2; + my $c; + foreach my $p (sort keys %connected_plugs) { + $c="$p:$connected_plugs{$p}\[$connected_plug_nums{$p}]" ; + #print "($instance_id,$plug,$plug_num);($p:$connected_plugs{$p}\[$connected_plug_nums{$p})\n"; + } + return $c; } - - ############### -# generate_dev_table +# generate_dev_table ############ sub generate_dev_table{ - my($soc,$ip,$infc,$info)=@_; - - - my $table=def_table(3,25,FALSE); - my $row=0; - my @instance_list=$soc->soc_get_instance_order(); - if (scalar @instance_list ==0 ){ - @instance_list=$soc->soc_get_all_instances(); - } - my $i=0; - - - - foreach my $instanc(@instance_list){ - $row=gen_instance($soc,$ip,$infc,$instanc,$info,$table,$row); - } - if($row<20){for ($i=$row; $i<20; $i++){ - - }} - + my($soc,$ip,$infc,$info)=@_; + my $table=def_table(3,25,FALSE); + my $row=0; + my @instance_list=$soc->soc_get_instance_order(); + if (scalar @instance_list ==0 ){ + @instance_list=$soc->soc_get_all_instances(); + } + my $i=0; + foreach my $instanc(@instance_list){ + $row=gen_instance($soc,$ip,$infc,$instanc,$info,$table,$row); + } + if($row<20){for ($i=$row; $i<20; $i++){ + }} + return $table; +} - return $table; -} - - #################### # show_active_dev # -################ - +################ sub show_active_dev{ - my($soc,$ip,$infc,$info)=@_; - my $dev_table = generate_dev_table($soc,$ip,$infc,$info); - my $scrolled_win = gen_scr_win_with_adjst($soc,'device_win_adj'); - add_widget_to_scrolled_win($dev_table,$scrolled_win); - return $scrolled_win; -} - - - - - - - + my($soc,$ip,$infc,$info)=@_; + my $dev_table = generate_dev_table($soc,$ip,$infc,$info); + my $scrolled_win = gen_scr_win_with_adjst($soc,'device_win_adj'); + add_widget_to_scrolled_win($dev_table,$scrolled_win); + return $scrolled_win; +} sub show_select_ip_description { - my ($soc,$category,$module,$info)=@_; - my $ip = ip->lib_new (); - my $describ=$ip->ip_get($category,$module,"description"); - if($describ){ - show_info($info,$describ); - - } - undef $ip; + my ($soc,$category,$module,$info)=@_; + my $ip = ip->lib_new (); + my $describ=$ip->ip_get($category,$module,"description"); + if($describ){ + show_info($info,$describ); + } + undef $ip; } - - - - - sub get_all_files_list { - my ($soc,$list_name)=@_; - my @instances=$soc->soc_get_all_instances(); - my $ip = ip->lib_new (); - my @files; - my $dir = Cwd::getcwd(); - my $warnings; - #make target dir - my $project_dir = abs_path("$dir/../.."); - - foreach my $id (@instances){ - my $module =$soc->soc_get_module($id); - my $module_name =$soc->soc_get_module_name($id); - my $category =$soc->soc_get_category($id); - my $inst =$soc->soc_get_instance_name($id); - - my @new=$ip->ip_get_list( $category,$module,$list_name); - #print "@new\n"; - foreach my $f(@new){ - my $n="$project_dir$f"; - if (!(-f "$n") && !(-f "$f" ) && !(-d "$n") && !(-d "$f" ) ){ - $warnings=(defined $warnings)? "$warnings WARNING: Can not find \"$f\" which is required for \"$inst\" \n":"WARNING: Can not find \"$f\" which is required for \"$inst\"\n "; - } - } - @files=(@files,@new); - } - return \@files,$warnings; + my ($soc,$list_name)=@_; + my @instances=$soc->soc_get_all_instances(); + my $ip = ip->lib_new (); + my @files; + my $dir = Cwd::getcwd(); + my $warnings; + #make target dir + my $project_dir = abs_path("$dir/../.."); + foreach my $id (@instances){ + my $module =$soc->soc_get_module($id); + my $module_name =$soc->soc_get_module_name($id); + my $category =$soc->soc_get_category($id); + my $inst =$soc->soc_get_instance_name($id); + my @new=$ip->ip_get_list( $category,$module,$list_name); + #print "@new\n"; + foreach my $f(@new){ + my $n="$project_dir$f"; + if (!(-f "$n") && !(-f "$f" ) && !(-d "$n") && !(-d "$f" ) ){ + $warnings=(defined $warnings)? "$warnings WARNING: Can not find \"$f\" which is required for \"$inst\" \n":"WARNING: Can not find \"$f\" which is required for \"$inst\"\n "; + } + } + @files=(@files,@new); + } + return \@files,$warnings; } - sub add_to_project_file_list{ - my ($files_ref,$files_path,$list_path )=@_; - my @new_file_ref; - foreach my $f(@{$files_ref}){ - my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); - push(@new_file_ref,"$files_path/$name$suffix"); - } - my ($old_file_ref,$r,$err) = regen_object("$list_path/file_list" ); - - if (defined $old_file_ref){ - foreach my $f(@{$old_file_ref}){ - unless ( grep( /^$f$/, @new_file_ref ) ){ - push(@new_file_ref,$f); - } - - } - } - open(FILE, ">$list_path/file_list") || die "Can not open: $!"; - print FILE Data::Dumper->Dump([\@new_file_ref],['files']); - close(FILE) || die "Error closing file: $!"; + my ($files_ref,$files_path,$list_path )=@_; + my @new_file_ref; + foreach my $f(@{$files_ref}){ + my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); + push(@new_file_ref,"$files_path/$name$suffix"); + } + my ($old_file_ref,$r,$err) = regen_object("$list_path/file_list" ); + if (defined $old_file_ref){ + foreach my $f(@{$old_file_ref}){ + unless ( grep( /^$f$/, @new_file_ref ) ){ + push(@new_file_ref,$f); + } + } + } + open(FILE, ">$list_path/file_list") || die "Can not open: $!"; + print FILE Data::Dumper->Dump([\@new_file_ref],['files']); + close(FILE) || die "Error closing file: $!"; } - - ################ -# generate_soc +# generate_soc ################# - sub generate_soc{ - my ($soc,$info,$target_dir,$hw_path,$sw_path,$gen_top,$gen_hw_lib,$oldfiles,$multi_core)=@_; - my $name=$soc->object_get_attribute('soc_name'); - $oldfiles = "remove" if(!defined $oldfiles); - $multi_core = 0 if(!defined $multi_core); - my ($file_v,$top_v,$readme,$prog)=soc_generate_verilog($soc,$sw_path,$info); - - # Write object file - open(FILE, ">lib/soc/$name.SOC") || die "Can not open: $!"; - print FILE perl_file_header("$name.SOC"); - print FILE Data::Dumper->Dump([\%$soc],['soc']); - close(FILE) || die "Error closing file: $!"; - - # Write verilog file - my $h=autogen_warning().get_license_header("${name}.sv")."\n"; - open(FILE, ">lib/verilog/$name.sv") || die "Can not open: $!"; - print FILE $h.$file_v; - close(FILE) || die "Error closing file: $!"; - - # Write Top module file - if($gen_top){ - my $l=autogen_warning().get_license_header("${name}_top.sv")."\n`timescale 1ns / 1ps\n"; - open(FILE, ">lib/verilog/${name}_top.sv") || die "Can not open: $!"; - print FILE "$l\n$top_v"; - close(FILE) || die "Error closing file: $!"; - } - - # Write readme file - open(FILE, ">lib/verilog/README") || die "Can not open: $!"; - print FILE $readme; - close(FILE) || die "Error closing file: $!"; - - - # Write memory prog file - open(FILE, ">lib/verilog/write_memory.sh") || die "Can not open: $!"; - print FILE $prog; - close(FILE) || die "Error closing file: $!"; - - + my ($soc,$info,$target_dir,$hw_path,$sw_path,$gen_top,$gen_hw_lib,$oldfiles,$multi_core)=@_; + my $name=$soc->object_get_attribute('soc_name'); + $oldfiles = "remove" if(!defined $oldfiles); + $multi_core = 0 if(!defined $multi_core); + my ($file_v,$top_v,$readme,$prog)=soc_generate_verilog($soc,$sw_path,$info); + # Write object file + open(FILE, ">lib/soc/$name.SOC") || die "Can not open: $!"; + print FILE perl_file_header("$name.SOC"); + print FILE Data::Dumper->Dump([\%$soc],['soc']); + close(FILE) || die "Error closing file: $!"; + # Write verilog file + my $h=autogen_warning().get_license_header("${name}.sv")."\n"; + open(FILE, ">lib/verilog/$name.sv") || die "Can not open: $!"; + print FILE $h.$file_v; + close(FILE) || die "Error closing file: $!"; + # Write Top module file + if($gen_top){ + my $l=autogen_warning().get_license_header("${name}_top.sv")."\n`timescale 1ns / 1ps\n"; + open(FILE, ">lib/verilog/${name}_top.sv") || die "Can not open: $!"; + print FILE "$l\n$top_v"; + close(FILE) || die "Error closing file: $!"; + } + # Write readme file + open(FILE, ">lib/verilog/README") || die "Can not open: $!"; + print FILE $readme; + close(FILE) || die "Error closing file: $!"; + # Write memory prog file + open(FILE, ">lib/verilog/write_memory.sh") || die "Can not open: $!"; + print FILE $prog; + close(FILE) || die "Error closing file: $!"; my $m_chain = $soc->object_get_attribute('JTAG','M_CHAIN'); - - #generate prog_mem - open(FILE, ">lib/verilog/program.sh") || die "Can not open: $!"; - print FILE soc_mem_prog($m_chain) if (defined $m_chain); - close(FILE) || die "Error closing file: $!"; - - - - my $dir = Cwd::getcwd(); - my $project_dir = abs_path("$dir/../../"); - if($gen_hw_lib){ - - #make target dir - my $hw_lib="$hw_path/lib"; - my $hw_sim="$hw_path/../src_sim"; - mkpath("$hw_lib/",1,01777); - mkpath("$sw_path/",1,01777); - mkpath("$hw_sim/",1,01777); - - if ($oldfiles eq "remove"){ - #remove old rtl files that were copied by ProNoC - my ($old_file_ref,$r,$err) = regen_object("$hw_path/file_list"); - if (defined $old_file_ref){ - remove_file_and_folders($old_file_ref,$target_dir); - } - } - - #copy hdl codes in src_verilog - my ($file_ref,$warnings)= get_all_files_list($soc,"hdl_files"); - my ($sim_ref,$warnings2)= get_all_files_list($soc,"hdl_files_ticked"); - #file_ref-sim_ref - my @n= get_diff_array($file_ref,$sim_ref); - $file_ref=\@n; - - copy_file_and_folders($file_ref,$project_dir,$hw_lib); - show_colored_info($info,$warnings,'green') if(defined $warnings); - add_to_project_file_list($file_ref,$hw_lib,$hw_path); - - - copy_file_and_folders($sim_ref,$project_dir,$hw_sim ); - show_colored_info($info,$warnings2,'green') if(defined $warnings2); - add_to_project_file_list($sim_ref,$hw_sim,$hw_path); - - - - - #copy clk setting hdl codes in src_verilog - my $sc_soc =get_source_set_top($soc,'soc'); - ($file_ref,$warnings)= get_all_files_list($sc_soc,"hdl_files"); - ($sim_ref,$warnings2)= get_all_files_list($soc,"hdl_files_ticked"); - #file_ref-sim_ref - my @m= get_diff_array($file_ref,$sim_ref); - $file_ref=\@m; - - - copy_file_and_folders($file_ref,$project_dir,$hw_lib); - show_colored_info($info,$warnings,'green') if(defined $warnings); - add_to_project_file_list($file_ref,$hw_lib,$hw_path); - - copy_file_and_folders($sim_ref,$project_dir,$hw_sim ); - show_colored_info($info,$warnings2,'green') if(defined $warnings2); - add_to_project_file_list($sim_ref,$hw_sim,$hw_path); - - #copy jtag control files - my @jtags=(("/mpsoc/rtl/src_peripheral/jtag/jtag_wb"),("jtag")); - copy_file_and_folders(\@jtags,$project_dir,$hw_lib); - add_to_project_file_list(\@jtags,$hw_lib,$hw_path); - - move ("$dir/lib/verilog/$name.sv","$hw_path/"); - move ("$dir/lib/verilog/${name}_top.sv","$hw_path/"); - move ("$dir/lib/verilog/README" ,"$sw_path/"); - move ("$dir/lib/verilog/write_memory.sh" ,"$sw_path/"); - move ("$dir/lib/verilog/program.sh" ,"$sw_path/"); - } - - #remove old software files that were copied by ProNoC - - my ($old_file_ref,$r,$err) = regen_object("$sw_path/file_list" ); - if (defined $old_file_ref){ - remove_file_and_folders($old_file_ref,$project_dir); - } - - # Copy Software files - my ($file_ref,$warnings)= get_all_files_list($soc,"sw_files"); - copy_file_and_folders($file_ref,$project_dir,$sw_path); - show_colored_info($info,$warnings,'green') if(defined $warnings); - - my @new_file_ref; - foreach my $f(@{$file_ref}){ - my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); - push(@new_file_ref,"$sw_path/$name$suffix"); - } - - push(@new_file_ref,"$sw_path/$name.h"); - open(FILE, ">$sw_path/file_list") || die "Can not open: $!"; - print FILE Data::Dumper->Dump([\@new_file_ref],['files']); - close(FILE) || die "Error closing file: $!"; - - - # Write system.h and Software gen files - generate_header_file($soc,$project_dir,$sw_path,$hw_path,$dir); - - - # Write main.c file if not exist - my $n="$sw_path/main.c"; - if (!(-f "$n")) { - # Write main.c - open(FILE, ">$n") || die "Can not open: $!"; - print FILE '#define MULTI_CORE' if($multi_core); - print FILE main_c_template($name); - close(FILE) || die "Error closing file: $!"; - - #write makefile source lib list file - open(FILE, ">$sw_path/SOURCE_LIB") || die "Can not open: $!"; - print FILE "SOURCE_LIB += $name.c "; - close(FILE) || die "Error closing file: $!"; - - - } - - #regenerate linker var file - create_linker_var_file($soc); - - - #write perl_object_file - mkpath("$target_dir/perl_lib/",1,01777); - open(FILE, ">$target_dir/perl_lib/$name.SOC") || die "Can not open: $!"; - print FILE perl_file_header("$name.SOC"); - print FILE Data::Dumper->Dump([\%$soc],['soc']); - - -} - + #generate prog_mem + open(FILE, ">lib/verilog/program.sh") || die "Can not open: $!"; + print FILE soc_mem_prog($m_chain) if (defined $m_chain); + close(FILE) || die "Error closing file: $!"; + my $dir = Cwd::getcwd(); + my $project_dir = abs_path("$dir/../../"); + if($gen_hw_lib){ + #make target dir + my $hw_lib="$hw_path/lib"; + my $hw_sim="$hw_path/../src_sim"; + mkpath("$hw_lib/",1,01777); + mkpath("$sw_path/",1,01777); + mkpath("$hw_sim/",1,01777); + if ($oldfiles eq "remove"){ + #remove old rtl files that were copied by ProNoC + my ($old_file_ref,$r,$err) = regen_object("$hw_path/file_list"); + if (defined $old_file_ref){ + remove_file_and_folders($old_file_ref,$target_dir); + } + } + #copy hdl codes in src_verilog + my ($file_ref,$warnings)= get_all_files_list($soc,"hdl_files"); + my ($sim_ref,$warnings2)= get_all_files_list($soc,"hdl_files_ticked"); + #file_ref-sim_ref + my @n= get_diff_array($file_ref,$sim_ref); + $file_ref=\@n; + copy_file_and_folders($file_ref,$project_dir,$hw_lib); + show_colored_info($info,$warnings,'green') if(defined $warnings); + add_to_project_file_list($file_ref,$hw_lib,$hw_path); + copy_file_and_folders($sim_ref,$project_dir,$hw_sim ); + show_colored_info($info,$warnings2,'green') if(defined $warnings2); + add_to_project_file_list($sim_ref,$hw_sim,$hw_path); + #copy clk setting hdl codes in src_verilog + my $sc_soc =get_source_set_top($soc,'soc'); + ($file_ref,$warnings)= get_all_files_list($sc_soc,"hdl_files"); + ($sim_ref,$warnings2)= get_all_files_list($soc,"hdl_files_ticked"); + #file_ref-sim_ref + my @m= get_diff_array($file_ref,$sim_ref); + $file_ref=\@m; + copy_file_and_folders($file_ref,$project_dir,$hw_lib); + show_colored_info($info,$warnings,'green') if(defined $warnings); + add_to_project_file_list($file_ref,$hw_lib,$hw_path); + copy_file_and_folders($sim_ref,$project_dir,$hw_sim ); + show_colored_info($info,$warnings2,'green') if(defined $warnings2); + add_to_project_file_list($sim_ref,$hw_sim,$hw_path); + #copy jtag control files + my @jtags=(("/mpsoc/rtl/src_peripheral/jtag/jtag_wb"),("jtag")); + copy_file_and_folders(\@jtags,$project_dir,$hw_lib); + add_to_project_file_list(\@jtags,$hw_lib,$hw_path); + move ("$dir/lib/verilog/$name.sv","$hw_path/"); + move ("$dir/lib/verilog/${name}_top.sv","$hw_path/"); + move ("$dir/lib/verilog/README" ,"$sw_path/"); + move ("$dir/lib/verilog/write_memory.sh" ,"$sw_path/"); + move ("$dir/lib/verilog/program.sh" ,"$sw_path/"); + } + #remove old software files that were copied by ProNoC + my ($old_file_ref,$r,$err) = regen_object("$sw_path/file_list" ); + if (defined $old_file_ref){ + remove_file_and_folders($old_file_ref,$project_dir); + } + # Copy Software files + my ($file_ref,$warnings)= get_all_files_list($soc,"sw_files"); + copy_file_and_folders($file_ref,$project_dir,$sw_path); + show_colored_info($info,$warnings,'green') if(defined $warnings); + my @new_file_ref; + foreach my $f(@{$file_ref}){ + my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); + push(@new_file_ref,"$sw_path/$name$suffix"); + } + push(@new_file_ref,"$sw_path/$name.h"); + open(FILE, ">$sw_path/file_list") || die "Can not open: $!"; + print FILE Data::Dumper->Dump([\@new_file_ref],['files']); + close(FILE) || die "Error closing file: $!"; + # Write system.h and Software gen files + generate_header_file($soc,$project_dir,$sw_path,$hw_path,$dir); + # Write main.c file if not exist + my $n="$sw_path/main.c"; + if (!(-f "$n")) { + # Write main.c + open(FILE, ">$n") || die "Can not open: $!"; + print FILE '#define MULTI_CORE' if($multi_core); + print FILE main_c_template($name); + close(FILE) || die "Error closing file: $!"; + #write makefile source lib list file + open(FILE, ">$sw_path/SOURCE_LIB") || die "Can not open: $!"; + print FILE "SOURCE_LIB += $name.c "; + close(FILE) || die "Error closing file: $!"; + } + #regenerate linker var file + create_linker_var_file($soc); + #write perl_object_file + mkpath("$target_dir/perl_lib/",1,01777); + open(FILE, ">$target_dir/perl_lib/$name.SOC") || die "Can not open: $!"; + print FILE perl_file_header("$name.SOC"); + print FILE Data::Dumper->Dump([\%$soc],['soc']); +} sub main_c_template{ - my $hdr=shift; - my $text=" + my $hdr=shift; + my $text=" #include \"$hdr.h\" - - // a simple delay function void delay ( unsigned int num ){ - - while (num>0){ - num--; - nop(); // asm volatile (\"nop\"); - } - return; - + while (num>0){ + num--; + nop(); // asm volatile (\"nop\"); + } + return; } - int main(){ - while(1){ - - - - } - + while(1){ + } return 0; } - "; - -return $text; - - + return $text; } - - - -sub get_wb_address { - my ($soc,$instance_id,$addr,$width)=@_; - my ($base,$end); - my @list= split (" ",$addr); - $base= hex ($list[0]); - $end= $base+(1 << $width)-1; - #print "$addr:$base \& $end\n"; - my %taken_bases= $soc->soc_list_base_addreses($instance_id); - - my $conflict=0; - do{ - $conflict=0; - foreach my $taken_end (sort {$a<=>$b} keys %taken_bases){ - my $taken_base=$taken_bases{$taken_end}; - #print "taken:($taken_base,$taken_end)\n"; - if (($base <= $taken_base && $end >= $taken_base ) || ($base <= $taken_end && $end >= $taken_end )){ - #if (!(($base < $taken_base && $end < $taken_end ) || ($base > $taken_base && $end > $taken_end ))){ - $conflict=1; - $base+=(1 << $width)while($base<$taken_end); - # $base=$taken_end+1; - - $end= $base+(1 << $width)-1; - last; - - } - } - - }while($conflict==1 && $end<(1 << 32)); - if($conflict==0){ - #print"new ($base,$end);\n"; - return ($base,$end); - - } - - return ; - -} - - +sub get_wb_address { + my ($soc,$instance_id,$addr,$width)=@_; + my ($base,$end); + my @list= split (" ",$addr); + $base= hex ($list[0]); + $end= $base+(1 << $width)-1; + #print "$addr:$base \& $end\n"; + my %taken_bases= $soc->soc_list_base_addreses($instance_id); + my $conflict=0; + do{ + $conflict=0; + foreach my $taken_end (sort {$a<=>$b} keys %taken_bases){ + my $taken_base=$taken_bases{$taken_end}; + #print "taken:($taken_base,$taken_end)\n"; + if (($base <= $taken_base && $end >= $taken_base ) || ($base <= $taken_end && $end >= $taken_end )){ + #if (!(($base < $taken_base && $end < $taken_end ) || ($base > $taken_base && $end > $taken_end ))){ + $conflict=1; + $base+=(1 << $width)while($base<$taken_end); + # $base=$taken_end+1; + $end= $base+(1 << $width)-1; + last; + } + } + }while($conflict==1 && $end<(1 << 32)); + if($conflict==0){ + #print"new ($base,$end);\n"; + return ($base,$end); + } + return ; +} ############# # set_unset_infc ############# - sub set_unset_infc{ - my $soc =shift; - my $window = def_popwin_size(40,60,"Unconnected Socket Interfaces",'percent'); - my $table = def_table(10,4, FALSE); - my $scrolled_win = add_widget_to_scrolled_win($table); - my $row=0; - my $column=0; - - my $ip = ip->lib_new (); - my @instances=$soc->soc_get_all_instances(); - foreach my $id (@instances){ - my $module =$soc->soc_get_module($id); - my $module_name =$soc->soc_get_module_name($id); - my $category =$soc->soc_get_category($id); - my $inst = $soc->soc_get_instance_name($id); - my @ports=$ip->ip_list_ports($category,$module); - foreach my $port (@ports){ - my ($type,$range,$intfc_name,$i_port)=$ip->ip_get_port($category,$module,$port); - my($i_type,$i_name,$i_num) =split("[:\[ \\]]", $intfc_name); - if($i_type eq 'socket' && $i_name ne'wb_addr_map' && $i_name ne'jtag_to_wb'){ - my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$i_name,$i_num); - my %connected_plugs=%$ref1; - my %connected_plug_nums=%$ref2; - if(!%connected_plugs ){ - my ($s_type,$s_value,$s_connection_num)=$soc->soc_get_socket_of_instance($id,$i_name); - my $v=$soc->soc_get_module_param_value($id,$s_value); - if ( length( $v || '' ) || $category eq 'NoC' ){ } - else { - ($row,$column)=add_param_widget ($soc,"$inst->$port","$inst-$port", 'IO','Combo-box',"IO,NC",undef, $table,$row,$column,1,"Unset-intfc",undef,undef,"vertical"); - if($column == 0){ - $column = 4; - - $row= $row-1; - }else{ - $column = 0; - - - - } - - } - - } - } - } - } - - my $box1=def_hbox(FALSE, 1); - $box1->pack_start( gen_Vsep(), FALSE, FALSE, 3); - $table->attach($box1,3,4,0,$row+1,'expand','fill',2,2); - my $ok = def_image_button('icons/select.png','OK'); - $ok->signal_connect ( 'clicked'=> sub { - $window->destroy; - }); - - my $mtable = def_table(10, 1, FALSE); - $mtable->attach_defaults($scrolled_win,0,1,0,9); - $mtable->attach($ok,0,1,9,10,'expand','fill',2,2); - $window->add ($mtable); - $window->show_all; - - + my $soc =shift; + my $window = def_popwin_size(40,60,"Unconnected Socket Interfaces",'percent'); + my $table = def_table(10,4, FALSE); + my $scrolled_win = add_widget_to_scrolled_win($table); + my $row=0; + my $column=0; + my $ip = ip->lib_new (); + my @instances=$soc->soc_get_all_instances(); + foreach my $id (@instances){ + my $module =$soc->soc_get_module($id); + my $module_name =$soc->soc_get_module_name($id); + my $category =$soc->soc_get_category($id); + my $inst = $soc->soc_get_instance_name($id); + my @ports=$ip->ip_list_ports($category,$module); + foreach my $port (@ports){ + my ($type,$range,$intfc_name,$i_port)=$ip->ip_get_port($category,$module,$port); + my($i_type,$i_name,$i_num) =split("[:\[ \\]]", $intfc_name); + if($i_type eq 'socket' && $i_name ne'wb_addr_map' && $i_name ne'jtag_to_wb'){ + my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$i_name,$i_num); + my %connected_plugs=%$ref1; + my %connected_plug_nums=%$ref2; + if(!%connected_plugs ){ + my ($s_type,$s_value,$s_connection_num)=$soc->soc_get_socket_of_instance($id,$i_name); + my $v=$soc->soc_get_module_param_value($id,$s_value); + if ( length( $v || '' ) || $category eq 'NoC' ){ } + else { + ($row,$column)=add_param_widget ($soc,"$inst->$port","$inst-$port", 'IO','Combo-box',"IO,NC",undef, $table,$row,$column,1,"Unset-intfc",undef,undef,"vertical"); + if($column == 0){ + $column = 4; + $row= $row-1; + }else{ + $column = 0; + } + } + } + } + } + } + my $box1=def_hbox(FALSE, 1); + $box1->pack_start( gen_Vsep(), FALSE, FALSE, 3); + $table->attach($box1,3,4,0,$row+1,'expand','fill',2,2); + my $ok = def_image_button('icons/select.png','OK'); + $ok->signal_connect ( 'clicked'=> sub { + $window->destroy; + }); + my $mtable = def_table(10, 1, FALSE); + $mtable->attach_defaults($scrolled_win,0,1,0,9); + $mtable->attach($ok,0,1,9,10,'expand','fill',2,2); + $window->add ($mtable); + $window->show_all; } - - - - ########## -# wb address setting +# wb address setting ######### - sub wb_address_setting { - my $soc=shift; - - - my $window = def_popwin_size(80,50,"Wishbone slave port address setting",'percent'); - my $table = def_table(10, 6, FALSE); - - my $scrolled_win = add_widget_to_scrolled_win($table); - my $row=0; - - #title - $table->attach(gen_label_in_left ("Instance name"),0,1,$row,$row+1,'expand','shrink',2,2); - $table->attach(gen_label_in_left ("Interface name"),1,2,$row,$row+1,'expand','shrink',2,2); - $table->attach(gen_label_in_left ("Bus name"),2,3,$row,$row+1,'expand','shrink',2,2); - $table->attach(gen_label_in_center("Base address"),3,4,$row,$row+1,'expand','shrink',2,2); - $table->attach(gen_label_in_center("End address"),4,5,$row,$row+1,'expand','shrink',2,2); - $table->attach(gen_label_in_center("Size (Bytes)"),5,6,$row,$row+1,'expand','shrink',2,2); - - my (@newbase,@newend,@connects); - - $row++; - my @all_instances=$soc->soc_get_all_instances(); - foreach my $instance_id (@all_instances){ - my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); - foreach my $plug (@plugs){ - my @nums=$soc->soc_list_plug_nums($instance_id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); - if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ - my $number=$row-1; - $newbase[$number]=$base; - $newend[$number]=$end; - $connects[$number]=$connect_id; - $row++; - }#if - }#foreach my $num - }#foreach my $plug - }#foreach my $instance_id + my $soc=shift; + my $window = def_popwin_size(80,50,"Wishbone slave port address setting",'percent'); + my $table = def_table(10, 6, FALSE); + my $scrolled_win = add_widget_to_scrolled_win($table); + my $row=0; + #title + $table->attach(gen_label_in_left ("Instance name"),0,1,$row,$row+1,'expand','shrink',2,2); + $table->attach(gen_label_in_left ("Interface name"),1,2,$row,$row+1,'expand','shrink',2,2); + $table->attach(gen_label_in_left ("Bus name"),2,3,$row,$row+1,'expand','shrink',2,2); + $table->attach(gen_label_in_center("Base address"),3,4,$row,$row+1,'expand','shrink',2,2); + $table->attach(gen_label_in_center("End address"),4,5,$row,$row+1,'expand','shrink',2,2); + $table->attach(gen_label_in_center("Size (Bytes)"),5,6,$row,$row+1,'expand','shrink',2,2); + my (@newbase,@newend,@connects); + $row++; + my @all_instances=$soc->soc_get_all_instances(); + foreach my $instance_id (@all_instances){ + my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); + foreach my $plug (@plugs){ + my @nums=$soc->soc_list_plug_nums($instance_id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); + if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ + my $number=$row-1; + $newbase[$number]=$base; + $newend[$number]=$end; + $connects[$number]=$connect_id; + $row++; + }#if + }#foreach my $num + }#foreach my $plug + }#foreach my $instance_id + my @status_all; + $row=1; + foreach my $instance_id (@all_instances){ + my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); + foreach my $plug (@plugs){ + my @nums=$soc->soc_list_plug_nums($instance_id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); + if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ + my $instance_name=$soc->soc_get_instance_name($instance_id); + my $plug_name= + (defined $name ) ? gen_label_in_left($name): + gen_label_in_left("$plug\[$num\]"); + my $connected_instance_name= $soc->soc_get_instance_name($connect_id); + my $number=$row-1; + my $label1= gen_label_in_left("$number: $instance_name"); + my $label2= gen_label_in_left($connected_instance_name); + my $entry1= gen_entry_new_with_max_length (10,sprintf("0x%08x", $base)); + my $entry2= gen_entry_new_with_max_length (10,sprintf("0x%08x", $end)); + my ($box,$valid) =addr_box_gen(sprintf("0x%08x", $base), sprintf("0x%08x", $end),\@newbase,\@newend,\@connects,$number); + $status_all[$number]=$valid; + $table->attach($label1,0,1,$row,$row+1,'expand','shrink',2,2); + $table->attach($plug_name,1,2,$row,$row+1,'expand','shrink',2,2); + $table->attach($label2,2,3,$row,$row+1,'expand','shrink',2,2); + $table->attach($entry1,3,4,$row,$row+1,'expand','shrink',2,2); + $table->attach($entry2,4,5,$row,$row+1,'expand','shrink',2,2); + $table->attach($box,5,7,$row,$row+1,'expand','shrink',2,2); + $entry1->signal_connect('changed'=>sub{ + my $base_in=$entry1->get_text(); + if (length($base_in)<2){ $entry1->set_text('0x')}; + my $end_in=$entry2->get_text(); + my $valid; + $box->destroy; + ($box,$valid)=addr_box_gen($base_in, $end_in,\@newbase,\@newend,\@connects,$number); + $status_all[$number]=$valid; + $table->attach($box,5,7,$number+1,$number+2,'expand','shrink',2,2); + $table->show_all; + } ); + $entry2->signal_connect('changed'=>sub{ + my $base_in=$entry1->get_text(); + my $end_in=$entry2->get_text(); + if (length($end_in)<2){ $entry2->set_text('0x')}; + my $valid; + $box->destroy; + ($box,$valid)=addr_box_gen($base_in, $end_in,\@newbase,\@newend,\@connects,$number); + $status_all[$number]=$valid; + $table->attach($box,5,7,$number+1,$number+2,'expand','shrink',2,2); + $table->show_all; + } ); + $row++; + }#if + }#foreach my $num + }#foreach my $plug + }#foreach my $instance_id + my $ok = def_image_button('icons/select.png','OK'); + my $refresh = def_image_button('icons/revert.png','Revert'); + my $refbox=def_hbox(TRUE,0); + $refbox->pack_start($refresh, FALSE, FALSE,0); + $refresh->signal_connect( 'clicked'=> sub { + $window->destroy; + wb_address_setting($soc); + }); + $ok->signal_connect ( 'clicked'=> sub { + my $st=1; + foreach my $valid (@status_all){ + if($valid==0){ + $st=0; + } + } + if($st==1){ + $row=1; + foreach my $instance_id (@all_instances){ + my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); + foreach my $plug (@plugs){ + my @nums=$soc->soc_list_plug_nums($instance_id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); + if(defined $connect_socket && ($connect_socket eq 'wb_slave')){ + my $number=$row-1; + $soc->soc_add_plug_base_addr($instance_id,$plug,$num,$newbase[$number],$newend[$number]); + $row++; + }#if + }#foreach my $num + }#foreach my $plug + }#foreach my $instance_id + $window->destroy; + }else{ + message_dialog("Invalid address!",'error'); + } + }); + my $mtable = def_table(10, 2, FALSE); + $mtable->attach_defaults($scrolled_win,0,2,0,9); + $mtable->attach ($refbox,0,1,9,10,'expand','shrink',2,2); + $mtable->attach($ok,1,2,9,10,'expand','fill',2,2); + $window->add ($mtable); + $window->show_all; +} - my @status_all; - $row=1; - foreach my $instance_id (@all_instances){ - my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); - foreach my $plug (@plugs){ - my @nums=$soc->soc_list_plug_nums($instance_id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); - if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ - my $instance_name=$soc->soc_get_instance_name($instance_id); - my $plug_name=(defined $name ) ? gen_label_in_left($name): - gen_label_in_left("$plug\[$num\]"); - - my $connected_instance_name= $soc->soc_get_instance_name($connect_id); - my $number=$row-1; - my $label1= gen_label_in_left("$number: $instance_name"); - my $label2= gen_label_in_left($connected_instance_name); - my $entry1= gen_entry_new_with_max_length (10,sprintf("0x%08x", $base)); - my $entry2= gen_entry_new_with_max_length (10,sprintf("0x%08x", $end)); - - my ($box,$valid) =addr_box_gen(sprintf("0x%08x", $base), sprintf("0x%08x", $end),\@newbase,\@newend,\@connects,$number); - $status_all[$number]=$valid; - - - $table->attach($label1,0,1,$row,$row+1,'expand','shrink',2,2); - $table->attach($plug_name,1,2,$row,$row+1,'expand','shrink',2,2); - $table->attach($label2,2,3,$row,$row+1,'expand','shrink',2,2); - $table->attach($entry1,3,4,$row,$row+1,'expand','shrink',2,2); - $table->attach($entry2,4,5,$row,$row+1,'expand','shrink',2,2); - - - $table->attach($box,5,7,$row,$row+1,'expand','shrink',2,2); - - - $entry1->signal_connect('changed'=>sub{ - my $base_in=$entry1->get_text(); - if (length($base_in)<2){ $entry1->set_text('0x')}; - my $end_in=$entry2->get_text(); - my $valid; - $box->destroy; - ($box,$valid)=addr_box_gen($base_in, $end_in,\@newbase,\@newend,\@connects,$number); - $status_all[$number]=$valid; - $table->attach($box,5,7,$number+1,$number+2,'expand','shrink',2,2); - $table->show_all; - - - } ); - $entry2->signal_connect('changed'=>sub{ - my $base_in=$entry1->get_text(); - my $end_in=$entry2->get_text(); - if (length($end_in)<2){ $entry2->set_text('0x')}; - my $valid; - $box->destroy; - ($box,$valid)=addr_box_gen($base_in, $end_in,\@newbase,\@newend,\@connects,$number); - $status_all[$number]=$valid; - $table->attach($box,5,7,$number+1,$number+2,'expand','shrink',2,2); - $table->show_all; - } ); - - - - $row++; - - - }#if - }#foreach my $num - }#foreach my $plug - }#foreach my $instance_id - - - my $ok = def_image_button('icons/select.png','OK'); - - - - my $refresh = def_image_button('icons/revert.png','Revert'); - my $refbox=def_hbox(TRUE,0); - $refbox->pack_start($refresh, FALSE, FALSE,0); - - $refresh->signal_connect( 'clicked'=> sub { - $window->destroy; - wb_address_setting($soc); - - - }); - $ok->signal_connect ( 'clicked'=> sub { - my $st=1; - foreach my $valid (@status_all){ - if($valid==0){ - $st=0; - - } - } - - if($st==1){ - $row=1; - foreach my $instance_id (@all_instances){ - my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); - foreach my $plug (@plugs){ - my @nums=$soc->soc_list_plug_nums($instance_id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); - if(defined $connect_socket && ($connect_socket eq 'wb_slave')){ - my $number=$row-1; - $soc->soc_add_plug_base_addr($instance_id,$plug,$num,$newbase[$number],$newend[$number]); - $row++; - }#if - }#foreach my $num - }#foreach my $plug - }#foreach my $instance_id - - - - - - $window->destroy; - }else{ - message_dialog("Invalid address!",'error'); - - } - - - }); - - - my $mtable = def_table(10, 2, FALSE); - $mtable->attach_defaults($scrolled_win,0,2,0,9); - $mtable->attach ($refbox,0,1,9,10,'expand','shrink',2,2); - $mtable->attach($ok,1,2,9,10,'expand','fill',2,2); - $window->add ($mtable); - $window->show_all; - - - - -} ############## -# addr_box_gen +# addr_box_gen ############## - sub addr_box_gen{ - my ($base_in, $end_in,$newbase_ref,$newend_ref,$connects_ref,$number)=@_; - my $box= def_hbox(TRUE,0); - my $label; - my $valid=1; - my $info; - if(is_hex($base_in) && is_hex($end_in)){ - my $size=(hex ($end_in) >= hex ($base_in))? hex ($end_in) - hex ($base_in) +1 : 0; - my $size_text= metric_conversion($size); - $label= gen_label_in_center($size_text); - $$newbase_ref[$number]=hex($base_in); - $$newend_ref[$number]=hex($end_in); - $info=check_entered_address($newbase_ref,$newend_ref,$connects_ref,$number); - if(defined $info) {$valid=0;} - - } - else { - $label= gen_label_in_center("Invalid hex value!"); - $info="Invalid hex value!"; - $valid=0; - } - - - my $status=(defined $info)? gen_button_message ($info,'icons/warning.png'): - gen_button_message (undef,'icons/select.png'); - - $box->pack_start($label,FALSE,FALSE,3); - $box->pack_start($status,FALSE,FALSE,3); - return ($box,$valid); - -} - - - + my ($base_in, $end_in,$newbase_ref,$newend_ref,$connects_ref,$number)=@_; + my $box= def_hbox(TRUE,0); + my $label; + my $valid=1; + my $info; + if(is_hex($base_in) && is_hex($end_in)){ + my $size=(hex ($end_in) >= hex ($base_in))? hex ($end_in) - hex ($base_in) +1 : 0; + my $size_text= metric_conversion($size); + $label= gen_label_in_center($size_text); + $$newbase_ref[$number]=hex($base_in); + $$newend_ref[$number]=hex($end_in); + $info=check_entered_address($newbase_ref,$newend_ref,$connects_ref,$number); + if(defined $info) {$valid=0;} + } + else { + $label= gen_label_in_center("Invalid hex value!"); + $info="Invalid hex value!"; + $valid=0; + } + my $status=(defined $info)? gen_button_message ($info,'icons/warning.png'): + gen_button_message (undef,'icons/select.png'); + $box->pack_start($label,FALSE,FALSE,3); + $box->pack_start($status,FALSE,FALSE,3); + return ($box,$valid); +} ########### -# get_parameter_final_value +# get_parameter_final_value ############ sub get_parameter_final_value{ - my ($soc,$id,$param)=@_; - #get ordered param - my @ordered_param=$soc->soc_get_instance_param_order($id); - my %sim_params; - foreach my $p (@ordered_param){ - my $value=$soc->soc_get_module_param_value($id,$p); - #print "\n$value=\$soc->soc_get_module_param_value($id,$p)\n"; - foreach my $q (sort keys %sim_params){ - - $value=replace_value($value,$q,$sim_params{$q}) if (defined $value); - - - } - $sim_params{$p}=$value; - #print "\$sim_params{$p}=$value;\n"; - } - return $sim_params{$param}; -} - - - - -sub replace_value{ - my ($string,$param,$value)=@_; - - my $new_string=$string; - #print "$new_range\n"; - my $new_param= $value; - ($new_string=$new_string)=~ s/\b$param\b/$new_param/g; - my $new_val = eval $new_string; - return $new_val if (defined $new_val); - return $string; - -} - - - + my ($soc,$id,$param)=@_; + #get ordered param + my @ordered_param=$soc->soc_get_instance_param_order($id); + my %sim_params; + foreach my $p (@ordered_param){ + my $value=$soc->soc_get_module_param_value($id,$p); + #print "\n$value=\$soc->soc_get_module_param_value($id,$p)\n"; + foreach my $q (sort keys %sim_params){ + $value=replace_value($value,$q,$sim_params{$q}) if (defined $value); + } + $sim_params{$p}=$value; + #print "\$sim_params{$p}=$value;\n"; + } + return $sim_params{$param}; +} +sub replace_value{ + my ($string,$param,$value)=@_; + my $new_string=$string; + #print "$new_range\n"; + my $new_param= $value; + ($new_string=$new_string)=~ s/\b$param\b/$new_param/g; + my $new_val = eval $new_string; + return $new_val if (defined $new_val); + return $string; +} sub check_entered_address{ - my ($base_ref,$end_ref,$connect_ref,$number)=@_; - my @bases=@{$base_ref}; - my @ends=@{$end_ref}; - my @connects=@{$connect_ref}; - - my $current_base=$bases[$number]; - my $current_end=$ends[$number]; - - if($current_base> $current_end) { - - return "Error: the given base address is bigger than the End address!"; - } - - my $size= scalar @bases; - my $conflicts; - foreach (my $i=0; $i<$size; $i++){ - if($i != $number){ #if not same row - if ($connects[$i] eq $connects[$number]) {#same bus - my $ok=(($bases[$i]< $bases[$number] && $bases[$i] < $ends[$number])||($bases[$i]> $bases[$number] && $bases[$i] > $ends[$number])); - if($ok==0) { - $conflicts=(defined $conflicts )? "$conflicts,$i": $i; - } - } - - - } - - - } - if (defined $conflicts){ return " The given address range has conflict with rows:$conflicts"; } - return; - - -} + my ($base_ref,$end_ref,$connect_ref,$number)=@_; + my @bases=@{$base_ref}; + my @ends=@{$end_ref}; + my @connects=@{$connect_ref}; + my $current_base=$bases[$number]; + my $current_end=$ends[$number]; + if($current_base> $current_end) { + return "Error: the given base address is bigger than the End address!"; + } + my $size= scalar @bases; + my $conflicts; + foreach (my $i=0; $i<$size; $i++){ + if($i != $number){ #if not same row + if ($connects[$i] eq $connects[$number]) {#same bus + my $ok=(($bases[$i]< $bases[$number] && $bases[$i] < $ends[$number])||($bases[$i]> $bases[$number] && $bases[$i] > $ends[$number])); + if($ok==0) { + $conflicts=(defined $conflicts )? "$conflicts,$i": $i; + } + } + } + } + if (defined $conflicts){ return " The given address range has conflict with rows:$conflicts"; } + return; +} ############# -# load_soc +# load_soc ############# - sub load_soc{ - my ($soc,$info)=@_; - my $ip = ip->lib_new (); - my $file; - my $dialog = gen_file_dialog (undef, 'SOC'); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/soc"); - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.SOC'){ - my ($pp,$r,$err) = regen_object($file); - if ($r || !defined $pp){ - show_info($info,"**Error reading $file file: $err\n"); - $dialog->destroy; - return; - } - clone_obj($soc,$pp); - check_instances_version($soc,$ip); - set_gui_status($soc,"load_file",0); - } - } - $dialog->destroy; - + my ($soc,$info)=@_; + my $ip = ip->lib_new (); + my $file; + my $dialog = gen_file_dialog (undef, 'SOC'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/lib/soc"); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.SOC'){ + my ($pp,$r,$err) = regen_object($file); + if ($r || !defined $pp){ + show_info($info,"**Error reading $file file: $err\n"); + $dialog->destroy; + return; + } + clone_obj($soc,$pp); + check_instances_version($soc,$ip); + set_gui_status($soc,"load_file",0); + } + } + $dialog->destroy; } - - - sub check_instances_version{ - my ($soc,$ip)=@_; - - #check if the IP's version didnt increases + my ($soc,$ip)=@_; + #check if the IP's version didnt increases my @all_instances=$soc->soc_get_all_instances(); foreach my $instance_id (@all_instances){ - my ($old_v,$new_v)= get_old_new_ip_version ($soc,$ip,$instance_id); - my $differences=''; - $differences="$differences \t The $instance_id version (V.$old_v) mismatches with the one existing in the library (V.$new_v).\n " if($old_v != $new_v); - - - message_dialog("Warning: The generated system may not work correctly: \n $differences Please remove and then add the aforementioned instance(s) to update them with current version(s)") if(length($differences)>1); - + my ($old_v,$new_v)= get_old_new_ip_version ($soc,$ip,$instance_id); + my $differences=''; + $differences="$differences \t The $instance_id version (V.$old_v) mismatches with the one existing in the library (V.$new_v).\n " if($old_v != $new_v); + message_dialog("Warning: The generated system may not work correctly: \n $differences Please remove and then add the aforementioned instance(s) to update them with current version(s)") if(length($differences)>1); } - - } sub get_old_new_ip_version{ - my ($soc,$ip,$instance_id)=@_; - my $old_v=$soc->object_get_attribute($instance_id,"version",undef); - $old_v=0 if(!defined $old_v); - my $module=$soc->soc_get_module($instance_id); - my $category=$soc->soc_get_category($instance_id); - my $new_v=$ip->ip_get($category,$module,"version"); - $new_v=0 if(!defined $new_v); - return ($old_v,$new_v); + my ($soc,$ip,$instance_id)=@_; + my $old_v=$soc->object_get_attribute($instance_id,"version",undef); + $old_v=0 if(!defined $old_v); + my $module=$soc->soc_get_module($instance_id); + my $category=$soc->soc_get_category($instance_id); + my $new_v=$ip->ip_get($category,$module,"version"); + $new_v=0 if(!defined $new_v); + return ($old_v,$new_v); } sub check_for_ni{ - my $self=shift; - my $ckeck=0; - my @instances=$self->soc_get_all_instances(); - foreach my $id (@instances){ - my $category = $self->soc_get_category($id); - if ($category eq 'NoC') { - $ckeck=1; - } - } - return $ckeck; - + my $self=shift; + my $ckeck=0; + my @instances=$self->soc_get_all_instances(); + foreach my $id (@instances){ + my $category = $self->soc_get_category($id); + if ($category eq 'NoC') { + $ckeck=1; + } + } + return $ckeck; } - sub get_ram_init{ - my $soc=shift; - my $window = def_popwin_size(80,50,"Memory initial file setting setting",'percent'); - my $table = def_table(10, 6, FALSE); - - my $scrolled_win = add_widget_to_scrolled_win($table); - my $row=0; - my $col=0; - my @instances=$soc->soc_get_all_instances(); - foreach my $id (@instances){ - my $category = $soc->soc_get_category($id); - if ($category eq 'RAM') { - my $ram_name= $soc->soc_get_instance_name($id); - $table->attach (gen_label_in_left("$ram_name"),$col,$col+1, $row, $row+1,'fill','shrink',2,2);$col++; - my $init_type=gen_combobox_object ($soc,'RAM_INIT','type',"Dont_Care,Fill_0,Fill_1,Search_in_sw,Fixed_file","Search_in_sw",undef); - my $init_inf= "Define how the memory must be initialized : - Dont_Care: The memory wont be initialized - Fill_0: All memory bits will fill with value zero - Fill_1: All memory bits will fill with value one - Search_in_sw: Each instance of this processing core - use different initial file that is - located in its SW folder. - Fixed_file: All instance of this processing core - use the same initial file"; - - $row++; - } - } - - - $window->add($scrolled_win); - $window->show_all; + my $soc=shift; + my $window = def_popwin_size(80,50,"Memory initial file setting setting",'percent'); + my $table = def_table(10, 6, FALSE); + my $scrolled_win = add_widget_to_scrolled_win($table); + my $row=0; + my $col=0; + my @instances=$soc->soc_get_all_instances(); + foreach my $id (@instances){ + my $category = $soc->soc_get_category($id); + if ($category eq 'RAM') { + my $ram_name= $soc->soc_get_instance_name($id); + $table->attach (gen_label_in_left("$ram_name"),$col,$col+1, $row, $row+1,'fill','shrink',2,2);$col++; + my $init_type=gen_combobox_object ($soc,'RAM_INIT','type',"Dont_Care,Fill_0,Fill_1,Search_in_sw,Fixed_file","Search_in_sw",undef); + my $init_inf= "Define how the memory must be initialized : + Dont_Care: The memory wont be initialized + Fill_0: All memory bits will fill with value zero + Fill_1: All memory bits will fill with value one + Search_in_sw: Each instance of this processing core + use different initial file that is + located in its SW folder. + Fixed_file: All instance of this processing core + use the same initial file"; + $row++; + } + } + $window->add($scrolled_win); + $window->show_all; } - sub software_edit_soc { - my $soc=shift; - my $name=$soc->object_get_attribute('soc_name'); - $name="" if (!defined $name); - if (length($name)==0){ - message_dialog("Please define the Tile name!"); - return ; - } - my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; - my $sw = "$target_dir/sw"; - my ($app,$table,$tview) = software_main($sw); - - - + my $soc=shift; + my $name=$soc->object_get_attribute('soc_name'); + $name="" if (!defined $name); + if (length($name)==0){ + message_dialog("Please define the Tile name!"); + return ; + } + my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; + my $sw = "$target_dir/sw"; + my ($app,$table,$tview) = software_main($sw); my $ram = def_image_button('icons/info.png',"Required BRAMs\' size",FALSE,1); my $linker = def_image_button('icons/setting.png','LD Linker',FALSE,1); - my $make = def_image_button('icons/gen.png','Compile'); - my $regen= def_image_button('icons/refresh.png','Regenerate main.c'); - my $prog= def_image_button('icons/write.png','Program the memory'); - - $table->attach ($ram,0, 1, 1,2,'shrink','shrink',0,0); - $table->attach ($regen,1, 2, 1,2,'shrink','shrink',0,0); - $table->attach ($linker,4, 5, 1,2,'shrink','shrink',0,0); - $table->attach ($make,5, 6, 1,2,'shrink','shrink',0,0); - $table->attach ($prog,9, 10, 1,2,'shrink','shrink',0,0); - $regen -> signal_connect ("clicked" => sub{ - my $response = yes_no_dialog("Are you sure you want to regenerate the main.c file? Note that any changes you have made will be lost"); - if ($response eq 'yes') { - save_file ("$sw/main.c",main_c_template($name)); - $app->refresh_source("$sw/main.c"); - } - }); - + my $make = def_image_button('icons/gen.png','Compile'); + my $regen= def_image_button('icons/refresh.png','Regenerate main.c'); + my $prog= def_image_button('icons/write.png','Program the memory'); + $table->attach ($ram,0, 1, 1,2,'shrink','shrink',0,0); + $table->attach ($regen,1, 2, 1,2,'shrink','shrink',0,0); + $table->attach ($linker,4, 5, 1,2,'shrink','shrink',0,0); + $table->attach ($make,5, 6, 1,2,'shrink','shrink',0,0); + $table->attach ($prog,9, 10, 1,2,'shrink','shrink',0,0); + $regen -> signal_connect ("clicked" => sub{ + my $response = yes_no_dialog("Are you sure you want to regenerate the main.c file? Note that any changes you have made will be lost"); + if ($response eq 'yes') { + save_file ("$sw/main.c",main_c_template($name)); + $app->refresh_source("$sw/main.c"); + } + }); my $load; - $make -> signal_connect("clicked" => sub{ - $load->destroy if(defined $load); - $app->ask_to_save_changes(); - $load= show_gif("icons/load.gif"); + $make -> signal_connect("clicked" => sub{ + $load->destroy if(defined $load); + $app->ask_to_save_changes(); + $load= show_gif("icons/load.gif"); $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); - $load->show_all; - unless (run_make_file($sw,$tview,'clean')){ - $load->destroy; - $load=def_icon("icons/cancel.png"); - $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); - $load->show_all; - return; + $load->show_all; + unless (run_make_file($sw,$tview,'clean')){ + $load->destroy; + $load=def_icon("icons/cancel.png"); + $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); + $load->show_all; + return; }; - unless (run_make_file($sw,$tview)){ - $load->destroy; - $load=def_icon("icons/cancel.png"); - $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); - $load->show_all; - return; - } - $load->destroy; - $load=def_icon("icons/button_ok.png"); - $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); - $load->show_all; - }); - - #Programe the board - $prog-> signal_connect("clicked" => sub{ - my $error = 0; - my $bash_file="$target_dir/sw/program.sh"; - my $jtag_intfc="$sw/jtag_intfc.sh"; - - add_info($tview,"Program the board using quartus_pgm and $bash_file file\n"); - #check if the programming file exists - unless (-f $bash_file) { - add_colored_info($tview,"\tThe $bash_file does not exists! \n", 'red'); - $error=1; - } - #check if the jtag_intfc.sh file exists - unless (-f $jtag_intfc) { - add_colored_info($tview,"\tThe $jtag_intfc does not exists!. Press the compile button and select your FPGA board first to generate $jtag_intfc file\n", 'red'); - $error=1; - } - - return if($error); - my $command = "cd $target_dir/sw; bash program.sh"; - add_info($tview,"$command\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); - if(length $stderr>1){ - add_colored_info($tview,"$stderr\n",'red'); - add_colored_info($tview,"Memory was not programmed successfully!\n",'red'); - }else { - - if($exit){ - add_colored_info($tview,"$stdout\n",'red'); - add_colored_info($tview,"Memory was not programmed successfully!\n",'red'); - }else{ - add_info($tview,"$stdout\n"); - add_colored_info($tview,"Memory is programmed successfully!\n",'blue'); - - } - - } - }); - - $ram -> signal_connect("clicked" => sub{ - show_reqired_brams($soc,$tview); - }); - - $linker -> signal_connect("clicked" => sub{ - linker_setting($soc,$tview); - }); - + unless (run_make_file($sw,$tview)){ + $load->destroy; + $load=def_icon("icons/cancel.png"); + $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); + $load->show_all; + return; + } + $load->destroy; + $load=def_icon("icons/button_ok.png"); + $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); + $load->show_all; + }); + #Programe the board + $prog-> signal_connect("clicked" => sub{ + my $error = 0; + my $bash_file="$target_dir/sw/program.sh"; + my $jtag_intfc="$sw/jtag_intfc.sh"; + add_info($tview,"Program the board using quartus_pgm and $bash_file file\n"); + #check if the programming file exists + unless (-f $bash_file) { + add_colored_info($tview,"\tThe $bash_file does not exists! \n", 'red'); + $error=1; + } + #check if the jtag_intfc.sh file exists + unless (-f $jtag_intfc) { + add_colored_info($tview,"\tThe $jtag_intfc does not exists!. Press the compile button and select your FPGA board first to generate $jtag_intfc file\n", 'red'); + $error=1; + } + return if($error); + my $command = "cd $target_dir/sw; bash program.sh"; + add_info($tview,"$command\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); + if(length $stderr>1){ + add_colored_info($tview,"$stderr\n",'red'); + add_colored_info($tview,"Memory was not programmed successfully!\n",'red'); + }else { + if($exit){ + add_colored_info($tview,"$stdout\n",'red'); + add_colored_info($tview,"Memory was not programmed successfully!\n",'red'); + }else{ + add_info($tview,"$stdout\n"); + add_colored_info($tview,"Memory is programmed successfully!\n",'blue'); + } + } + }); + $ram -> signal_connect("clicked" => sub{ + show_reqired_brams($soc,$tview); + }); + $linker -> signal_connect("clicked" => sub{ + linker_setting($soc,$tview); + }); } - sub soc_mem_prog { - my $chain=shift; - my $string="#!/bin/bash - - + my $chain=shift; + my $string="#!/bin/bash #JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/JTAG_INTFC\" source ./jtag_intfc.sh - #reset and disable cpus, then release the reset but keep the cpus disabled - \$JTAG_INTFC -t $chain -n 127 -d \"I:1,D:2:3,D:2:2,I:0\" - -# jtag instruction -# 0: bypass -# 1: getting data +# jtag instruction +# 0: bypass +# 1: getting data # jtag data : -# bit 0 is reset -# bit 1 is disable +# bit 0 is reset +# bit 1 is disable # I:1 set jtag_enable in active mode # D:2:3 load jtag_enable data register with 0x3 reset=1 disable=1 # D:2:2 load jtag_enable data register with 0x2 reset=0 disable=1 # I:0 set jtag_enable in bypass mode - - - #Program the memory - - bash write_memory.sh - - + bash write_memory.sh #Enable the cpu \$JTAG_INTFC -t $chain -n 127 -d \"I:1,D:2:0,I:0\" # I:1 set jtag_enable in active mode # D:2:0 load jtag_enable data register with 0x0 reset=0 disable=0 # I:0 set jtag_enable in bypass mode "; -return $string; - + return $string; } - sub soc_gen_top_ip{ - my $soc=shift; - my $top_ip=ip_gen->top_gen_new(); - my $ip = ip->lib_new (); - my $intfc=interface->interface_new(); - my @instances=$soc->soc_get_all_instances(); - my $wires=soc->new_wires(); - foreach my $id (@instances){ - my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, - $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires); - } #$id - return $top_ip; + my $soc=shift; + my $top_ip=ip_gen->top_gen_new(); + my $ip = ip->lib_new (); + my $intfc=interface->interface_new(); + my @instances=$soc->soc_get_all_instances(); + my $wires=soc->new_wires(); + foreach my $id (@instances){ + my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, + $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires); + } #$id + return $top_ip; } - - - sub get_soc_clk_source_list{ - my $soc=shift; - my %all_sources; + my $soc=shift; + my %all_sources; my $top = soc_gen_top_ip($soc); my @intfcs=$top->top_get_intfc_list(); - my @sources=('clk','reset'); - foreach my $intfc (@intfcs){ - my($type,$name,$num)= split("[:\[ \\]]", $intfc); - foreach my $s (@sources){ - if ($intfc =~ /plug:$s/){ - my @ports=$top->top_get_intfc_ports_list($intfc); - $all_sources{$s}=\@ports; - } - } - } - return %all_sources; -} + my @sources=('clk','reset'); + foreach my $intfc (@intfcs){ + my($type,$name,$num)= split("[:\[ \\]]", $intfc); + foreach my $s (@sources){ + if ($intfc =~ /plug:$s/){ + my @ports=$top->top_get_intfc_ports_list($intfc); + $all_sources{$s}=\@ports; + } + } + } + return %all_sources; +} sub check_soc_name{ - my $name=shift; - $name="" if (!defined $name); - if (length($name)==0){ - message_dialog("Please define the Tile name!"); - return 1; - } - - my @tmp=split('_',$name); - if ( $tmp[-1] =~ /^[0-9]+$/ ){ - message_dialog("The soc name must not end with '_number'!"); - return 1; - } - - my $error = check_verilog_identifier_syntax($name); - if ( defined $error ){ - message_dialog("The \"$name\" is given with an unacceptable formatting. This name will be used as top level Verilog module name so it must follow Verilog identifier declaration formatting:\n $error"); - return 1; - } - return 0; + my $name=shift; + $name="" if (!defined $name); + if (length($name)==0){ + message_dialog("Please define the Tile name!"); + return 1; + } + my @tmp=split('_',$name); + if ( $tmp[-1] =~ /^[0-9]+$/ ){ + message_dialog("The soc name must not end with '_number'!"); + return 1; + } + my $error = check_verilog_identifier_syntax($name); + if ( defined $error ){ + message_dialog("The \"$name\" is given with an unacceptable formatting. This name will be used as top level Verilog module name so it must follow Verilog identifier declaration formatting:\n $error"); + return 1; + } + return 0; } - ############ # main ############ - - - -sub soc_clk_setting_win1 { - my ($soc,$info)=@_; - my $window = def_popwin_size(80,80,"CLK setting",'percent'); - - my $next=def_image_button('icons/right.png','Next'); - my $mtable = def_table(10, 1, FALSE); - #get the list of all tiles clk sources - - - - my $table = def_table(10, 7, FALSE); - my($row,$column)=(0,0); - - my %all = get_soc_clk_source_list($soc) ; - my @ports = @{$all{'clk'}} if defined $all{'clk'}; - my $n=0; - foreach my $p (@ports){ - my $r_lab=gen_label_in_center("$p:"); - $table->attach ($r_lab,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=1; - $soc->object_add_attribute('SOURCE_SET',"clk_${n}_name",$p); - ($column,$row)=get_clk_constrain_widget($soc,$table,$column,$row,'clk',$n); - $n++; - } - - $mtable->attach_defaults($table,0,1,0,1); - $mtable->attach($next,0,1,20,21,'expand','fill',2,2); - $window->add ($mtable); - $window->show_all(); - $next-> signal_connect("clicked" => sub{ - $window->destroy; - clk_setting_win2($soc,$info,'soc'); - - }); - - - - +sub soc_clk_setting_win1 { + my ($soc,$info)=@_; + my $window = def_popwin_size(80,80,"CLK setting",'percent'); + my $next=def_image_button('icons/right.png','Next'); + my $mtable = def_table(10, 1, FALSE); + #get the list of all tiles clk sources + my $table = def_table(10, 7, FALSE); + my($row,$column)=(0,0); + my %all = get_soc_clk_source_list($soc) ; + my @ports = @{$all{'clk'}} if defined $all{'clk'}; + my $n=0; + foreach my $p (@ports){ + my $r_lab=gen_label_in_center("$p:"); + $table->attach ($r_lab,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=1; + $soc->object_add_attribute('SOURCE_SET',"clk_${n}_name",$p); + ($column,$row)=get_clk_constrain_widget($soc,$table,$column,$row,'clk',$n); + $n++; + } + $mtable->attach_defaults($table,0,1,0,1); + $mtable->attach($next,0,1,20,21,'expand','fill',2,2); + $window->add ($mtable); + $window->show_all(); + $next-> signal_connect("clicked" => sub{ + $window->destroy; + clk_setting_win2($soc,$info,'soc'); + }); } - ###### # ctrl ###### - sub soc_ctrl_tab { - my ($soc,$info,$ip)=@_; - - my $generate = def_image_button('icons/gen.png','_Generate RTL',FALSE,1); - my $compile = def_image_button('icons/gate.png','Compile RTL'); - my $software = def_image_button('icons/binary.png','Software'); - my $diagram = def_image_button('icons/diagram.png','Diagram'); - my $clk= def_image_button('icons/clk.png','CLK setting'); - my $unset = def_image_button('icons/intfc.png','Unset Intfc.'); - - my $ram = def_image_button('icons/RAM.png','Memory'); - my $wb = def_image_button('icons/setting.png','WB addr'); - #my $open = def_image_button('icons/browse.png',"_Load Tile",FALSE,1); - #my $entry=gen_entry_object($soc,'soc_name',undef,undef,undef,undef); - #my $entrybox=gen_label_info(" Tile name:",$entry); - #my $save = def_image_button('icons/save.png'); - #my $open_dir = def_image_button('icons/open-folder.png'); - #set_tip($save, "Save current tile configuration setting"); - #set_tip($open_dir, "Open target tile folder"); - - #$entrybox->pack_start( $save, FALSE, FALSE, 0); - #$entrybox->pack_start( $open_dir, FALSE, FALSE, 0); - - my $main_table = def_table (1, 12, FALSE); - - - my $target_dir= "$ENV{'PRONOC_WORK'}/SOC"; - my ($entrybox,$entry ) =gen_save_load_widget ( - $soc, #the object + my ($soc,$info,$ip)=@_; + my $generate = def_image_button('icons/gen.png','_Generate RTL',FALSE,1); + my $compile = def_image_button('icons/gate.png','Compile RTL'); + my $software = def_image_button('icons/binary.png','Software'); + my $diagram = def_image_button('icons/diagram.png','Diagram'); + my $clk= def_image_button('icons/clk.png','CLK setting'); + my $unset = def_image_button('icons/intfc.png','Unset Intfc.'); + my $ram = def_image_button('icons/RAM.png','Memory'); + my $wb = def_image_button('icons/setting.png','WB addr'); + #my $open = def_image_button('icons/browse.png',"_Load Tile",FALSE,1); + #my $entry=gen_entry_object($soc,'soc_name',undef,undef,undef,undef); + #my $entrybox=gen_label_info(" Tile name:",$entry); + #my $save = def_image_button('icons/save.png'); + #my $open_dir = def_image_button('icons/open-folder.png'); + #set_tip($save, "Save current tile configuration setting"); + #set_tip($open_dir, "Open target tile folder"); + #$entrybox->pack_start( $save, FALSE, FALSE, 0); + #$entrybox->pack_start( $open_dir, FALSE, FALSE, 0); + my $main_table = def_table (1, 12, FALSE); + my $target_dir= "$ENV{'PRONOC_WORK'}/SOC"; + my ($entrybox,$entry ) =gen_save_load_widget ( + $soc, #the object "Tile name",#the label shown for setting configuration - 'soc_name',#the key name for saveing the setting configuration in object + 'soc_name',#the key name for saveing the setting configuration in object 'Tile',#the label full name show in tool tips $target_dir,#Where the generted RTL files are loacted. Undef if not aplicaple 'soc',#check the given name match the SoC or mpsoc name rules 'lib/soc',#where the current configuration seting file is saved 'SOC',#the extenstion given for configuration seting file - \&load_soc,#refrence to load function - $info + \&load_soc,#refrence to load function + $info ); - - - - - - #$main_table->attach ($open , 0, 1, 0,1,'expand','shrink',2,2); - $main_table->attach ($entrybox , 1, 3, 0,1,'expand','shrink',2,2); - $main_table->attach ($unset , 3, 4, 0,1,'expand','shrink',2,2); - $main_table->attach ($wb , 4, 5, 0,1,'expand','shrink',2,2); - $main_table->attach ($diagram , 5, 6, 0,1,'expand','shrink',2,2); - $main_table->attach ($clk , 6, 7, 0,1,'expand','shrink',2,2); - $main_table->attach ($generate , 7, 8, 0,1,'expand','shrink',2,2); - $main_table->attach ($software , 8, 9, 0,1,'expand','shrink',2,2); - $main_table->attach ($compile ,10,12, 0,1,'expand','shrink',2,2); - - - $clk-> signal_connect("clicked" => sub{ - soc_clk_setting_win1($soc,$info); - }); - - $diagram-> signal_connect("clicked" => sub{ - show_tile_diagram ($soc); - }); - - - #$save-> signal_connect("clicked" => sub{ - # my $name=$soc->object_get_attribute('soc_name'); - # return if(check_soc_name($name)) ; - - # # Write object file - # open(FILE, ">lib/soc/$name.SOC") || die "Can not open: $!"; - # print FILE perl_file_header("$name.SOC"); - # print FILE Data::Dumper->Dump([\%$soc],['soc']); - # close(FILE) || die "Error closing file: $!"; - # message_dialog("Processing Tile \"$name\" is saved as lib/soc/$name.SOC."); - - #}); - - - $generate-> signal_connect("clicked" => sub{ - my $name=$soc->object_get_attribute('soc_name'); - return if(check_soc_name($name)) ; - - my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; - my $hw_dir = "$target_dir/src_verilog"; - my $sw_path = "$target_dir/sw"; - - $soc->object_add_attribute('global_param','CORE_ID',0); - $soc->object_add_attribute('global_param','SW_LOC',$sw_path); - - unlink "$hw_dir/file_list"; - generate_soc($soc,$info,$target_dir,$hw_dir,$sw_path,1,1); - - my $has_ni= check_for_ni($soc); - if($has_ni){ - my $message = "Processing Tile \"$name\" has been created successfully at $target_dir/. In order to include this tile in MPSoC Generator you need to restart the ProNoC. Do you ant to reset the ProNoC now?"; - my $response = yes_no_dialog ($message); - if ($response eq 'yes') { - exec($^X, $0, @ARGV);# reset ProNoC to apply changes - } - - } else { - message_dialog("Processing Tile \"$name\" has been created successfully at $target_dir/."); - - } - }); - - $software -> signal_connect("clicked" => sub{ - software_edit_soc($soc); - - }); - - $unset-> signal_connect("clicked" => sub{ - set_unset_infc($soc); - }); - - $ram-> signal_connect("clicked" => sub{ - get_ram_init($soc); - - }); - - - - $compile -> signal_connect("clicked" => sub{ - $soc->object_add_attribute('compile','compilers',"QuartusII,Vivado,Verilator,Modelsim"); - my $name=$soc->object_get_attribute('soc_name'); - $name="" if (!defined $name); - if (length($name)==0){ - message_dialog("Please define the Tile name!"); - return ; - } - my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; - my $hw_dir = "$target_dir/src_verilog"; - my $sw_path = "$target_dir/sw"; - my $top = "$target_dir/src_verilog/${name}_top.sv"; - if (-f $top){ - unlink "$hw_dir/file_list"; - generate_soc($soc,$info,$target_dir,$hw_dir,$sw_path,1,1); - select_compiler($soc,$name,$top,$target_dir); - } else { - message_dialog("Cannot find $top file. Please run RTL Generator first!",'error'); - return; - } - }); - - $wb-> signal_connect("clicked" => sub{ - wb_address_setting($soc); - - }); - - #$open-> signal_connect("clicked" => sub{ - # load_soc($soc,$info); - - #}); - - #$open_dir-> signal_connect("clicked" => sub{ - # my $name=$soc->object_get_attribute('soc_name'); - # $name="" if (!defined $name); - # if (length($name)==0){ - # message_dialog("Please define the Tile name!"); - # return ; - # } - # my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; - # unless (-d $target_dir){ - # message_dialog("Cannot find $target_dir.\n Please run RTL Generator first!",'error'); - # return; - # } - # system "xdg-open $target_dir"; - - #}); - - return $main_table; - + #$main_table->attach ($open , 0, 1, 0,1,'expand','shrink',2,2); + $main_table->attach ($entrybox , 1, 3, 0,1,'expand','shrink',2,2); + $main_table->attach ($unset , 3, 4, 0,1,'expand','shrink',2,2); + $main_table->attach ($wb , 4, 5, 0,1,'expand','shrink',2,2); + $main_table->attach ($diagram , 5, 6, 0,1,'expand','shrink',2,2); + $main_table->attach ($clk , 6, 7, 0,1,'expand','shrink',2,2); + $main_table->attach ($generate , 7, 8, 0,1,'expand','shrink',2,2); + $main_table->attach ($software , 8, 9, 0,1,'expand','shrink',2,2); + $main_table->attach ($compile ,10,12, 0,1,'expand','shrink',2,2); + $clk-> signal_connect("clicked" => sub{ + soc_clk_setting_win1($soc,$info); + }); + $diagram-> signal_connect("clicked" => sub{ + show_tile_diagram ($soc); + }); + #$save-> signal_connect("clicked" => sub{ + # my $name=$soc->object_get_attribute('soc_name'); + # return if(check_soc_name($name)) ; + # # Write object file + # open(FILE, ">lib/soc/$name.SOC") || die "Can not open: $!"; + # print FILE perl_file_header("$name.SOC"); + # print FILE Data::Dumper->Dump([\%$soc],['soc']); + # close(FILE) || die "Error closing file: $!"; + # message_dialog("Processing Tile \"$name\" is saved as lib/soc/$name.SOC."); + #}); + $generate-> signal_connect("clicked" => sub{ + my $name=$soc->object_get_attribute('soc_name'); + return if(check_soc_name($name)) ; + my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; + my $hw_dir = "$target_dir/src_verilog"; + my $sw_path = "$target_dir/sw"; + $soc->object_add_attribute('global_param','CORE_ID',0); + $soc->object_add_attribute('global_param','SW_LOC',$sw_path); + unlink "$hw_dir/file_list"; + generate_soc($soc,$info,$target_dir,$hw_dir,$sw_path,1,1); + my $has_ni= check_for_ni($soc); + if($has_ni){ + my $message = "Processing Tile \"$name\" has been created successfully at $target_dir/. In order to include this tile in MPSoC Generator you need to restart the ProNoC. Do you ant to reset the ProNoC now?"; + my $response = yes_no_dialog ($message); + if ($response eq 'yes') { + exec($^X, $0, @ARGV);# reset ProNoC to apply changes + } + } else { + message_dialog("Processing Tile \"$name\" has been created successfully at $target_dir/."); + } + }); + $software -> signal_connect("clicked" => sub{ + software_edit_soc($soc); + }); + $unset-> signal_connect("clicked" => sub{ + set_unset_infc($soc); + }); + $ram-> signal_connect("clicked" => sub{ + get_ram_init($soc); + }); + $compile -> signal_connect("clicked" => sub{ + $soc->object_add_attribute('compile','compilers',"QuartusII,Vivado,Verilator,Modelsim"); + my $name=$soc->object_get_attribute('soc_name'); + $name="" if (!defined $name); + if (length($name)==0){ + message_dialog("Please define the Tile name!"); + return ; + } + my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; + my $hw_dir = "$target_dir/src_verilog"; + my $sw_path = "$target_dir/sw"; + my $top = "$target_dir/src_verilog/${name}_top.sv"; + if (-f $top){ + unlink "$hw_dir/file_list"; + generate_soc($soc,$info,$target_dir,$hw_dir,$sw_path,1,1); + select_compiler($soc,$name,$top,$target_dir); + } else { + message_dialog("Cannot find $top file. Please run RTL Generator first!",'error'); + return; + } + }); + $wb-> signal_connect("clicked" => sub{ + wb_address_setting($soc); + }); + #$open-> signal_connect("clicked" => sub{ + # load_soc($soc,$info); + #}); + #$open_dir-> signal_connect("clicked" => sub{ + # my $name=$soc->object_get_attribute('soc_name'); + # $name="" if (!defined $name); + # if (length($name)==0){ + # message_dialog("Please define the Tile name!"); + # return ; + # } + # my $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$name"; + # unless (-d $target_dir){ + # message_dialog("Cannot find $target_dir.\n Please run RTL Generator first!",'error'); + # return; + # } + # system "xdg-open $target_dir"; + #}); + return $main_table; } - sub socgen_main{ - - my $infc = interface->interface_new(); - my $ip = ip->lib_new (); - my $soc = soc->soc_new(); - set_gui_status($soc,"ideal",0); - - # The main table containing the lib tree, selected modules and info section - my $main_table = def_table (20, 12, FALSE); - - # The box which holds the info, warning, error ... messages - my ($infobox,$info)= create_txview(); - - - # A tree view for holding a library - my %tree_text; - my @categories= $ip->ip_get_categories(); + my $infc = interface->interface_new(); + my $ip = ip->lib_new (); + my $soc = soc->soc_new(); + set_gui_status($soc,"ideal",0); + # The main table containing the lib tree, selected modules and info section + my $main_table = def_table (20, 12, FALSE); + # The box which holds the info, warning, error ... messages + my ($infobox,$info)= create_txview(); + # A tree view for holding a library + my %tree_text; + my @categories= $ip->ip_get_categories(); foreach my $p (@categories) { - #next if ($p eq 'PLL'); - my @modules= $ip->get_modules($p); - $tree_text{$p}=\@modules; + #next if ($p eq 'PLL'); + my @modules= $ip->get_modules($p); + $tree_text{$p}=\@modules; } - my $tree_box = create_tree ($soc,'IP list', $info,\%tree_text,\&show_select_ip_description,\&add_module_to_soc); - - $main_table->set_row_spacings (4); - $main_table->set_col_spacings (1); - - my $device_win=show_active_dev($soc,$ip,$infc,$info); - - - - - - my $h1=gen_hpaned($tree_box,.15,$device_win); - my $v2=gen_vpaned($h1,.55,$infobox); - $main_table->attach_defaults ($v2 , 0, 12, 0,19); - - my $ctrl = soc_ctrl_tab($soc,$info,$ip); - $main_table->attach ($ctrl , 0, 12, 19,20,'fill','fill',2,2); - - - - my $sc_win = add_widget_to_scrolled_win($main_table); - - - - #check soc status every 0.5 second. refresh device table if there is any changes - Glib::Timeout->add (100, sub{ - my ($state,$timeout)= get_gui_status($soc); - - if ($timeout>0){ - $timeout--; - set_gui_status($soc,$state,$timeout); - - }elsif ($state eq 'save_project'){ - # Write object file - my $name=$soc->object_get_attribute('soc_name',undef); - open(FILE, ">lib/soc/$name.SOC") || die "Can not open: $!"; - print FILE perl_file_header("$name.SOC"); - print FILE Data::Dumper->Dump([\%$soc],['soc']); - close(FILE) || die "Error closing file: $!"; - set_gui_status($soc,"ideal",0); - } - elsif( $state ne "ideal" ){ - $device_win->destroy; - $device_win=show_active_dev($soc,$ip,$infc,$info); - $h1 -> pack2($device_win, TRUE, TRUE); - $h1 -> show_all; - $ctrl->destroy; - $ctrl= soc_ctrl_tab($soc,$info,$ip); - $main_table->attach ($ctrl , 0, 12, 19,20,'fill','fill',2,2); - $main_table->show_all; - set_gui_status($soc,"ideal",0); - } - return TRUE; - - } ); - - - - return $sc_win; - - - + my $tree_box = create_tree ($soc,'IP list', $info,\%tree_text,\&show_select_ip_description,\&add_module_to_soc); + $main_table->set_row_spacings (4); + $main_table->set_col_spacings (1); + my $device_win=show_active_dev($soc,$ip,$infc,$info); + my $h1=gen_hpaned($tree_box,.15,$device_win); + my $v2=gen_vpaned($h1,.55,$infobox); + $main_table->attach_defaults ($v2 , 0, 12, 0,19); + my $ctrl = soc_ctrl_tab($soc,$info,$ip); + $main_table->attach ($ctrl , 0, 12, 19,20,'fill','fill',2,2); + my $sc_win = add_widget_to_scrolled_win($main_table); + #check soc status every 0.5 second. refresh device table if there is any changes + Glib::Timeout->add (100, sub{ + my ($state,$timeout)= get_gui_status($soc); + if ($timeout>0){ + $timeout--; + set_gui_status($soc,$state,$timeout); + }elsif ($state eq 'save_project'){ + # Write object file + my $name=$soc->object_get_attribute('soc_name',undef); + open(FILE, ">lib/soc/$name.SOC") || die "Can not open: $!"; + print FILE perl_file_header("$name.SOC"); + print FILE Data::Dumper->Dump([\%$soc],['soc']); + close(FILE) || die "Error closing file: $!"; + set_gui_status($soc,"ideal",0); + } + elsif( $state ne "ideal" ){ + $device_win->destroy; + $device_win=show_active_dev($soc,$ip,$infc,$info); + $h1 -> pack2($device_win, TRUE, TRUE); + $h1 -> show_all; + $ctrl->destroy; + $ctrl= soc_ctrl_tab($soc,$info,$ip); + $main_table->attach ($ctrl , 0, 12, 19,20,'fill','fill',2,2); + $main_table->show_all; + set_gui_status($soc,"ideal",0); + } + return TRUE; + } ); + return $sc_win; } - - - - - - +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/software_editor.pl b/mpsoc/perl_gui/lib/perl/software_editor.pl index 5947671..dcec7a7 100644 --- a/mpsoc/perl_gui/lib/perl/software_editor.pl +++ b/mpsoc/perl_gui/lib/perl/software_editor.pl @@ -1,22 +1,16 @@ #!/usr/bin/perl -w - use strict; use warnings; - use FindBin; use lib $FindBin::Bin; use Consts; - use constant::boolean; - - use Data::Dumper; use File::Basename; use Cwd 'abs_path'; - use base 'Class::Accessor::Fast'; - use Consts; + BEGIN { my $module = (Consts::GTK_VERSION==2) ? 'Gtk2' : 'Gtk3'; my $file = $module; @@ -26,963 +20,725 @@ BEGIN $module->import; } - -require "widget.pl"; - +require "widget.pl"; __PACKAGE__->mk_accessors(qw{ - window - sourceview - buffer - filename - search_regexp - search_case - search_entry - regexp - highlighted - open_list_ref - source_view_notebook - menue - modified - label - ask_to_save - close_b + window + sourceview + buffer + filename + search_regexp + search_case + search_entry + regexp + highlighted + open_list_ref + source_view_notebook + menue + modified + label + ask_to_save + close_b }); - - - - my $NAME = 'ProNoC'; -my $path = ""; - - - +my $path = ""; exit gtk_gui_run(\&software_main_stand_alone) unless caller; - sub software_main_stand_alone(){ - $path = "../../"; - - set_path_env(); - my $project_dir = get_project_dir(); #mpsoc dir addr - my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; - if (-f $paths_file){#} && defined $ENV{PRONOC_WORK} ) { - my $paths= do $paths_file; - set_gui_setting($paths); - } - - set_defualt_font_size(); - my ($app,$table,$tview,$window) = software_main("../../../../../back/tmp",undef,) ; - $window->signal_connect (destroy => sub { gui_quite();}); + $path = "../../"; + set_path_env(); + my $project_dir = get_project_dir(); #mpsoc dir addr + my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; + if (-f $paths_file){#} && defined $ENV{PRONOC_WORK} ) { + my $paths= do $paths_file; + set_gui_setting($paths); + } + set_defualt_font_size(); + my ($app,$table,$tview,$window) = software_main("../../../../../back/tmp",undef,) ; + $window->signal_connect (destroy => sub { gui_quite();}); } - - - - sub software_main { - my ($sw,$file,$pages_ref,$label_ref) = @_; - - - - my $app = __PACKAGE__->new(); - my ($table,$tview,$widget)=$app->build_gui($sw,$pages_ref,$label_ref); - my $main_c=(defined $file)? "$sw/$file" : "$sw/main.c"; - my @tmp; - $app->open_list_ref(\@tmp); - $app->ask_to_save(def_button()); - $app->load_source($main_c) if (-f $main_c ); - return ($app,$table,$tview,$widget); + my ($sw,$file,$pages_ref,$label_ref) = @_; + my $app = __PACKAGE__->new(); + my ($table,$tview,$widget)=$app->build_gui($sw,$pages_ref,$label_ref); + my $main_c=(defined $file)? "$sw/$file" : "$sw/main.c"; + my @tmp; + $app->open_list_ref(\@tmp); + $app->ask_to_save(def_button()); + $app->load_source($main_c) if (-f $main_c ); + return ($app,$table,$tview,$widget); } - - - sub build_gui { - my ($app,$sw,$pages_ref,$label_ref) = @_; - - - my $table= def_table(2,10,FALSE); - - my $vbox = def_vbox(FALSE, 0); - my $scwin_text = add_widget_to_scrolled_win($vbox); - - my ($scwin_info,$tview)= create_txview(); - my ($tree_view,$tree_store) =$app->build_tree_view($sw); - my $scwin_dirs = add_widget_to_scrolled_win($tree_view); - - - my $hpaned = gen_hpaned($scwin_dirs,0.15,$scwin_text); - my $vpaned = gen_vpaned($hpaned,0.6,$scwin_info); - - $table->attach_defaults ($vpaned,0, 10, 0,1); - - my $window = def_popwin_size (84,84,'Source Editor','percent'); - - my @menue_item=("$sw/",$window,$tree_view,$tree_store,$scwin_dirs); - $app->menue(\@menue_item); - if (defined $pages_ref){ - #first page is software editor - my $notebook = gen_notebook(); - - my $label1=def_image_label($path."icons/binary.png","Software Editor",1); - $notebook->append_page ($table,$label1); - $label1->show_all; - - - my @pages=@{$pages_ref}; - my @labels=@{$label_ref}; - my $i=0; - foreach my $page (@pages){ - my $label=$labels[$i]; - $notebook->append_page ($page,$label); - $label->show_all; - $i++; - } - $notebook->show_all; - $notebook->set_current_page(0); - $window -> add ( $notebook); - }else { - $window -> add ( $table); - } - - $app->window($window); - - - my $hbox = def_table(FALSE, 0); - my $source_view_notebook = gen_notebook(); - $vbox->pack_start($hbox, FALSE, FALSE, 0); - $vbox->pack_start($source_view_notebook, TRUE, TRUE, 0); - - - - - $app->source_view_notebook($source_view_notebook); + my ($app,$sw,$pages_ref,$label_ref) = @_; + my $table= def_table(2,10,FALSE); + my $vbox = def_vbox(FALSE, 0); + my $scwin_text = add_widget_to_scrolled_win($vbox); + my ($scwin_info,$tview)= create_txview(); + my ($tree_view,$tree_store) =$app->build_tree_view($sw); + my $scwin_dirs = add_widget_to_scrolled_win($tree_view); + my $hpaned = gen_hpaned($scwin_dirs,0.15,$scwin_text); + my $vpaned = gen_vpaned($hpaned,0.6,$scwin_info); + $table->attach_defaults ($vpaned,0, 10, 0,1); + my $window = def_popwin_size (84,84,'Source Editor','percent'); + my @menue_item=("$sw/",$window,$tree_view,$tree_store,$scwin_dirs); + $app->menue(\@menue_item); + if (defined $pages_ref){ + #first page is software editor + my $notebook = gen_notebook(); + my $label1=def_image_label($path."icons/binary.png","Software Editor",1); + $notebook->append_page ($table,$label1); + $label1->show_all; + my @pages=@{$pages_ref}; + my @labels=@{$label_ref}; + my $i=0; + foreach my $page (@pages){ + my $label=$labels[$i]; + $notebook->append_page ($page,$label); + $label->show_all; + $i++; + } + $notebook->show_all; + $notebook->set_current_page(0); + $window -> add ( $notebook); + }else { + $window -> add ( $table); + } + $app->window($window); + my $hbox = def_table(FALSE, 0); + my $source_view_notebook = gen_notebook(); + $vbox->pack_start($hbox, FALSE, FALSE, 0); + $vbox->pack_start($source_view_notebook, TRUE, TRUE, 0); + $app->source_view_notebook($source_view_notebook); $window->show_all(); - - $window->signal_connect ('delete_event'=> sub { - $app->ask_to_save_changes(); - return 0; - - }); - - - - - - return ($table,$tview,$window); + $window->signal_connect ('delete_event'=> sub { + $app->ask_to_save_changes(); + return 0; + }); + return ($table,$tview,$window); } sub ask_to_save_changes{ - my $app=shift; - my $save = $app->ask_to_save(); - $save->clicked; + my $app=shift; + my $save = $app->ask_to_save(); + $save->clicked; } sub update_modified { - my $self=shift; - if($self->modified() ==2 ){ - $self->set_source_label_modified(FALSE); - return; - } - elsif($self->modified() ==FALSE ){ - #if ($buffer->get_modified()){ - $self->set_source_label_modified(TRUE); - #} - } + my $self=shift; + if($self->modified() ==2 ){ + $self->set_source_label_modified(FALSE); + return; + } + elsif($self->modified() ==FALSE ){ + #if ($buffer->get_modified()){ + $self->set_source_label_modified(TRUE); + #} + } } sub new_source_view{ - my ($app,$filename)=@_; - + my ($app,$filename)=@_; my $self = __PACKAGE__->new(); - my ($name,$p,$suffix) = fileparse("$filename",qr"\..[^.]*$"); - my $label = gen_label_in_left ("${name}${suffix}"); - $self->modified(2);#initial - $self->label($label); - $self->filename($filename); - - my $hbox = def_table(FALSE, 0); - my $vbox = def_vbox(FALSE, 0); - my $ref =$app->menue(); - my ($sw,$window,$tree_view,$tree_store,$scwin_dirs) =@{$ref}; + my ($name,$p,$suffix) = fileparse("$filename",qr"\..[^.]*$"); + my $label = gen_label_in_left ("${name}${suffix}"); + $self->modified(2);#initial + $self->label($label); + $self->filename($filename); + my $hbox = def_table(FALSE, 0); + my $vbox = def_vbox(FALSE, 0); + my $ref =$app->menue(); + my ($sw,$window,$tree_view,$tree_store,$scwin_dirs) =@{$ref}; $hbox->attach($self->build_menu($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app), 0, 1, 0,1,'shrink','shrink',2,2); - - $hbox->attach_defaults($self->build_search_box, 1,2,0,1); + $hbox->attach_defaults($self->build_search_box, 1,2,0,1); $vbox->pack_start($hbox, FALSE, FALSE, 0); - - my $buffer = $self->create_SourceView_buffer(); - my $sourceview = gen_SourceView_with_buffer($buffer); - $sourceview->signal_connect('key-press-event' => sub { handle_key( @_,$self ) } ); - $sourceview->set_show_line_numbers(TRUE); - $sourceview->set_tab_width(2); - $sourceview->set_indent_on_tab(TRUE); - $sourceview->set_highlight_current_line(TRUE); - - - # $sourceview->set_draw_spaces(['tab', 'newline']); - # - # Fix TextView's annoying paste behaviour when pasting with the mouse - # (middle button click). By default gtk will scroll the text view to the - # original place where the cursor is. - # - $sourceview->signal_connect(button_press_event => sub { - my ($view, $event) = @_; - - # We're only interested on middle mouse clicks (mouse-paste) - return FALSE unless $event->button == 2; - - # Remember the position of the paste - my (@coords) = $sourceview->window_to_buffer_coords('text', $event->x, $event->y); - my ($iter) = $sourceview->get_iter_at_position(@coords); - $self->{paste_mark} = $buffer->create_mark('paste', $iter, FALSE); - - return FALSE; - }); - - - # - # If a paste is done through the middle click then place the cursor at the end - # of the pasted text. - # - $buffer->signal_connect('paste-done' => sub { - my $mark = delete $self->{paste_mark} or return; - - my $iter = $buffer->get_iter_at_mark($mark); - $buffer->place_cursor($iter); - - $self->sourceview->scroll_to_mark( - $mark, - 0.0, - FALSE, - 0.0, 0.5 - ); - $buffer->delete_mark($mark); - }); - - $buffer->signal_connect('insert-text' => sub { - update_modified($self); - }); - $buffer->signal_connect('delete-range' => sub { - update_modified($self); - }); - - - - my $scroll = add_widget_to_scrolled_win($sourceview); - $vbox->pack_start($scroll, TRUE, TRUE, 0); - $self->sourceview($sourceview); - $self->buffer($sourceview->get_buffer); - - - my $notebook = $app->source_view_notebook(); - my $close = def_button('x'); - - my $box = def_hbox(FALSE,0); - $box->pack_start($label, TRUE, FALSE, 0); - $box->pack_start($close, TRUE, FALSE, 0); - $notebook->append_page ($vbox,$box); - set_tip($box,"$filename"); - $box->show_all; - $notebook->show_all(); - my $n= $notebook->get_n_pages(); - $notebook->set_current_page($n-1); - #save $sourceview ref in $app - my %srcviews; - my $ref2 = $app->sourceview(); - if(defined $ref2){ - %srcviews =%{$ref2}; - } - $srcviews{$n-1}=$self; - $app->sourceview(\%srcviews); - - - $close->signal_connect("clicked" => sub { - #check if the file has been modified or not - if($self->modified()==TRUE){ - my $r=create_dialog ("Save changes to documnet ${name}${suffix}?","If you do'nt save, changes will be permanently lost.",$path."icons/help.png","Save","Close without saving","Cancel"); - return if ($r eq "Cancel"); - if ($r eq "Save"){ - $self->do_save(); - } - - } - $vbox->destroy; - $box->destroy; - $self = undef; - my $ref =$app->open_list_ref(); - my @new =remove_scolar_from_array($ref,$filename); - $app->open_list_ref(\@new); - - }); - - my $save = $app->ask_to_save(); - + my $buffer = $self->create_SourceView_buffer(); + my $sourceview = gen_SourceView_with_buffer($buffer); + $sourceview->signal_connect('key-press-event' => sub { handle_key( @_,$self ) } ); + $sourceview->set_show_line_numbers(TRUE); + $sourceview->set_tab_width(2); + $sourceview->set_indent_on_tab(TRUE); + $sourceview->set_highlight_current_line(TRUE); + # $sourceview->set_draw_spaces(['tab', 'newline']); + # + # Fix TextView's annoying paste behaviour when pasting with the mouse + # (middle button click). By default gtk will scroll the text view to the + # original place where the cursor is. + # + $sourceview->signal_connect(button_press_event => sub { + my ($view, $event) = @_; + # We're only interested on middle mouse clicks (mouse-paste) + return FALSE unless $event->button == 2; + # Remember the position of the paste + my (@coords) = $sourceview->window_to_buffer_coords('text', $event->x, $event->y); + my ($iter) = $sourceview->get_iter_at_position(@coords); + $self->{paste_mark} = $buffer->create_mark('paste', $iter, FALSE); + return FALSE; + }); + # + # If a paste is done through the middle click then place the cursor at the end + # of the pasted text. + # + $buffer->signal_connect('paste-done' => sub { + my $mark = delete $self->{paste_mark} or return; + my $iter = $buffer->get_iter_at_mark($mark); + $buffer->place_cursor($iter); + $self->sourceview->scroll_to_mark( + $mark, + 0.0, + FALSE, + 0.0, 0.5 + ); + $buffer->delete_mark($mark); + }); + $buffer->signal_connect('insert-text' => sub { + update_modified($self); + }); + $buffer->signal_connect('delete-range' => sub { + update_modified($self); + }); + my $scroll = add_widget_to_scrolled_win($sourceview); + $vbox->pack_start($scroll, TRUE, TRUE, 0); + $self->sourceview($sourceview); + $self->buffer($sourceview->get_buffer); + my $notebook = $app->source_view_notebook(); + my $close = def_button('x'); + my $box = def_hbox(FALSE,0); + $box->pack_start($label, TRUE, FALSE, 0); + $box->pack_start($close, TRUE, FALSE, 0); + $notebook->append_page ($vbox,$box); + set_tip($box,"$filename"); + $box->show_all; + $notebook->show_all(); + my $n= $notebook->get_n_pages(); + $notebook->set_current_page($n-1); + #save $sourceview ref in $app + my %srcviews; + my $ref2 = $app->sourceview(); + if(defined $ref2){ + %srcviews =%{$ref2}; + } + $srcviews{$n-1}=$self; + $app->sourceview(\%srcviews); + $close->signal_connect("clicked" => sub { + #check if the file has been modified or not + if($self->modified()==TRUE){ + my $r=create_dialog ("Save changes to documnet ${name}${suffix}?","If you do'nt save, changes will be permanently lost.",$path."icons/help.png","Save","Close without saving","Cancel"); + return if ($r eq "Cancel"); + if ($r eq "Save"){ + $self->do_save(); + } + } + $vbox->destroy; + $box->destroy; + $self = undef; + my $ref =$app->open_list_ref(); + my @new =remove_scolar_from_array($ref,$filename); + $app->open_list_ref(\@new); + }); + my $save = $app->ask_to_save(); $save->signal_connect("clicked" => sub { - #check if the file has been modified or not - return if(!defined $self); - if($self->modified()==TRUE){ - my $r=create_dialog ("Save changes to documnet ${name}${suffix}?"," ",$path."icons/help.png","Save","Continue without saving"); - return if ($r eq "Continue without saving"); - if ($r eq "Save"){ - $self->do_save(); - } - - } - }); - - $self->close_b($close); - return $self; + #check if the file has been modified or not + return if(!defined $self); + if($self->modified()==TRUE){ + my $r=create_dialog ("Save changes to documnet ${name}${suffix}?"," ",$path."icons/help.png","Save","Continue without saving"); + return if ($r eq "Continue without saving"); + if ($r eq "Save"){ + $self->do_save(); + } + } + }); + $self->close_b($close); + return $self; } - - sub build_tree_view{ - my ($app,$sw)=@_; - - # Directory name, full path - my ($tree_store,$tree_view) =file_edit_tree(); - -# $tree_view->signal_connect (button_release_event => sub{ - $tree_view->signal_connect (row_activated => sub{ - my $tree_model = $tree_view->get_model(); - my $selection = $tree_view->get_selection(); - my $iter = $selection->get_selected(); - - if(defined $iter){ - my $path = $tree_model->get($iter, 1) ; - $path= substr $path, 0, -1; - #$self->do_save(); - #print "open $path\n"; - $app->load_source($path) if(-f $path); - } - return; - }); - - - $tree_view->signal_connect ('row-expanded' => sub { - my ($tree_view, $iter, $tree_path) = @_; - my $tree_model = $tree_view->get_model(); - my ($dir, $path) = $tree_model->get($iter); - - # for each of $iter's children add any subdirectories - my $child = $tree_model->iter_children ($iter); - - - my $r; - $r=$tree_model->iter_is_valid($child); - while ($child && $r ==1) { - - my ($dir, $path) = $tree_model->get($child, 0, 1); - add_to_tree($tree_view,$tree_store, $child, $dir, $path); - $child=treemodel_next_iter($child , $tree_model); - $r=$tree_model->iter_is_valid($child) if (defined $child); - - } - return; -}); - -my $child = $tree_store->append(undef); - -$tree_store->set($child, 0, $sw, 1, '/'); -add_to_tree($tree_view,$tree_store, $child, '/', "$sw/"); -return ($tree_view,$tree_store); - + my ($app,$sw)=@_; + # Directory name, full path + my ($tree_store,$tree_view) =file_edit_tree(); +# $tree_view->signal_connect (button_release_event => sub{ + $tree_view->signal_connect (row_activated => sub{ + my $tree_model = $tree_view->get_model(); + my $selection = $tree_view->get_selection(); + my $iter = $selection->get_selected(); + if(defined $iter){ + my $path = $tree_model->get($iter, 1) ; + $path= substr $path, 0, -1; + #$self->do_save(); + #print "open $path\n"; + $app->load_source($path) if(-f $path); + } + return; + }); + $tree_view->signal_connect ('row-expanded' => sub { + my ($tree_view, $iter, $tree_path) = @_; + my $tree_model = $tree_view->get_model(); + my ($dir, $path) = $tree_model->get($iter); + # for each of $iter's children add any subdirectories + my $child = $tree_model->iter_children ($iter); + my $r; + $r=$tree_model->iter_is_valid($child); + while ($child && $r ==1) { + my ($dir, $path) = $tree_model->get($child, 0, 1); + add_to_tree($tree_view,$tree_store, $child, $dir, $path); + $child=treemodel_next_iter($child , $tree_model); + $r=$tree_model->iter_is_valid($child) if (defined $child); + } + return; + }); + my $child = $tree_store->append(undef); + $tree_store->set($child, 0, $sw, 1, '/'); + add_to_tree($tree_view,$tree_store, $child, '/', "$sw/"); + return ($tree_view,$tree_store); } - - sub build_search_box { - my $self = shift; - - # Elements of the search box - my $hbox = def_hbox(FALSE, 0); - - my $search_entry = gen_entry(); - $search_entry->signal_connect(activate => sub {$self->do_search()}); - $search_entry->signal_connect(icon_release => sub {$self->do_search()}); - $self->search_entry($search_entry); - - my $search_regexp = gen_checkbutton('RegExp'); - $search_regexp->signal_connect(toggled => sub { - $self->search_regexp($search_regexp->get_active); - }); - - my $search_case = gen_checkbutton('Case'); - $search_case->signal_connect(toggled => sub { - $self->search_case($search_case->get_active); - }); - - - - my $search_icon = def_image_button($path."icons/browse.png"); - $search_entry->set_icon_from_stock(primary => 'gtk-find'); - - - $hbox->pack_start($search_entry, TRUE, TRUE , 0); - $hbox->pack_start($search_regexp, FALSE, FALSE, 0); - $hbox->pack_start($search_case, FALSE, FALSE, 0); - - return $hbox; + my $self = shift; + # Elements of the search box + my $hbox = def_hbox(FALSE, 0); + my $search_entry = gen_entry(); + $search_entry->signal_connect(activate => sub {$self->do_search()}); + $search_entry->signal_connect(icon_release => sub {$self->do_search()}); + $self->search_entry($search_entry); + my $search_regexp = gen_checkbutton('RegExp'); + $search_regexp->signal_connect(toggled => sub { + $self->search_regexp($search_regexp->get_active); + }); + my $search_case = gen_checkbutton('Case'); + $search_case->signal_connect(toggled => sub { + $self->search_case($search_case->get_active); + }); + my $search_icon = def_image_button($path."icons/browse.png"); + $search_entry->set_icon_from_stock(primary => 'gtk-find'); + $hbox->pack_start($search_entry, TRUE, TRUE , 0); + $hbox->pack_start($search_regexp, FALSE, FALSE, 0); + $hbox->pack_start($search_case, FALSE, FALSE, 0); + return $hbox; } sub refresh_source { - my $app = shift; - my ($filename) = abs_path(@_); - - - my $ref =$app->open_list_ref(); - my @open_list; - @open_list = @{$ref} if(defined $ref); - #check if the file is opend before activate its notebook win, remove its content - my $pos=get_scolar_pos ($filename,@open_list); - my $self; - if (defined $pos){ - my $notebook = $app->source_view_notebook(); - $notebook->set_current_page($pos); - - my $ref = $app->sourceview(); - if(defined $ref){ - my %srcviews =%{$ref}; - my $n = $notebook->get_current_page; - $self=$srcviews{$n}; - }else { - return; - } - } - else { - $self=new_source_view($app,"$filename"); - push(@open_list,$filename); - $app->open_list_ref(\@open_list); - - } - my $buffer = $self->buffer; - - # Guess the programming language of the file - $self->detect_language($filename); - - # Loading a file should not be undoable. - my $content; - do { - open my $handle, $filename or die "Can't read file $filename because $!"; - local $/; - $content = <$handle>; - close $handle; - }; - $buffer->begin_not_undoable_action(); - $buffer->set_text($content); - $buffer->end_not_undoable_action(); - - #$buffer->set_modified(FALSE); - $buffer->place_cursor($buffer->get_start_iter); - - - - my $notebook = $app->source_view_notebook(); - $notebook->show_all(); - - - #$self->window->set_title("$filename - $NAME"); + my $app = shift; + my ($filename) = abs_path(@_); + my $ref =$app->open_list_ref(); + my @open_list; + @open_list = @{$ref} if(defined $ref); + #check if the file is opend before activate its notebook win, remove its content + my $pos=get_scolar_pos ($filename,@open_list); + my $self; + if (defined $pos){ + my $notebook = $app->source_view_notebook(); + $notebook->set_current_page($pos); + my $ref = $app->sourceview(); + if(defined $ref){ + my %srcviews =%{$ref}; + my $n = $notebook->get_current_page; + $self=$srcviews{$n}; + }else { + return; + } + } + else { + $self=new_source_view($app,"$filename"); + push(@open_list,$filename); + $app->open_list_ref(\@open_list); + } + my $buffer = $self->buffer; + # Guess the programming language of the file + $self->detect_language($filename); + # Loading a file should not be undoable. + my $content; + do { + open my $handle, $filename or die "Can't read file $filename because $!"; + local $/; + $content = <$handle>; + close $handle; + }; + $buffer->begin_not_undoable_action(); + $buffer->set_text($content); + $buffer->end_not_undoable_action(); + #$buffer->set_modified(FALSE); + $buffer->place_cursor($buffer->get_start_iter); + my $notebook = $app->source_view_notebook(); + $notebook->show_all(); + #$self->window->set_title("$filename - $NAME"); } - - - - - - - - - - sub load_source { - my $app = shift; - my ($filename) = abs_path(@_); - - - my $ref =$app->open_list_ref(); - my @open_list; - @open_list = @{$ref} if(defined $ref); - #check if the file is opend before activate its notebook win - my $pos=get_scolar_pos ($filename,@open_list); - - if (defined $pos){ - my $notebook = $app->source_view_notebook(); - $notebook->set_current_page($pos); - return; - } - - - #create a new source view and load the file there - - my $self=new_source_view($app,"$filename"); - - push(@open_list,$filename); - $app->open_list_ref(\@open_list); - - - - my $buffer = $self->buffer; - - # Guess the programming language of the file - $self->detect_language($filename); - - # Loading a file should not be undoable. - my $content; - do { - open my $handle, $filename or die "Can't read file $filename because $!"; - local $/; - $content = <$handle>; - close $handle; - }; - $buffer->begin_not_undoable_action(); - $buffer->set_text($content); - $buffer->end_not_undoable_action(); - - #$buffer->set_modified(FALSE); - $buffer->place_cursor($buffer->get_start_iter); - - - - my $notebook = $app->source_view_notebook(); - $notebook->show_all(); - - - #$self->window->set_title("$filename - $NAME"); + my $app = shift; + my ($filename) = abs_path(@_); + my $ref =$app->open_list_ref(); + my @open_list; + @open_list = @{$ref} if(defined $ref); + #check if the file is opend before activate its notebook win + my $pos=get_scolar_pos ($filename,@open_list); + if (defined $pos){ + my $notebook = $app->source_view_notebook(); + $notebook->set_current_page($pos); + return; + } + #create a new source view and load the file there + my $self=new_source_view($app,"$filename"); + push(@open_list,$filename); + $app->open_list_ref(\@open_list); + my $buffer = $self->buffer; + # Guess the programming language of the file + $self->detect_language($filename); + # Loading a file should not be undoable. + my $content; + do { + open my $handle, $filename or die "Can't read file $filename because $!"; + local $/; + $content = <$handle>; + close $handle; + }; + $buffer->begin_not_undoable_action(); + $buffer->set_text($content); + $buffer->end_not_undoable_action(); + #$buffer->set_modified(FALSE); + $buffer->place_cursor($buffer->get_start_iter); + my $notebook = $app->source_view_notebook(); + $notebook->show_all(); + #$self->window->set_title("$filename - $NAME"); } - sub clear_highlighted { - my $self = shift; - - my $highlighted = delete $self->{highlighted} or return; - - my $buffer = $self->buffer; - - my @iters; - foreach my $mark (@{ $highlighted->{marks} }) { - my $iter = $buffer->get_iter_at_mark($mark); - push @iters, $iter; - $buffer->delete_mark($mark); - } - - $buffer->remove_tag_by_name($highlighted->{name}, @iters); + my $self = shift; + my $highlighted = delete $self->{highlighted} or return; + my $buffer = $self->buffer; + my @iters; + foreach my $mark (@{ $highlighted->{marks} }) { + my $iter = $buffer->get_iter_at_mark($mark); + push @iters, $iter; + $buffer->delete_mark($mark); + } + $buffer->remove_tag_by_name($highlighted->{name}, @iters); } - sub get_text { - my $self = shift; - my $buffer = $self->buffer; - return $buffer->get_text($buffer->get_start_iter, $buffer->get_end_iter, FALSE); + my $self = shift; + my $buffer = $self->buffer; + return $buffer->get_text($buffer->get_start_iter, $buffer->get_end_iter, FALSE); } - sub do_search { - my $self = shift; - my $criteria = $self->search_entry->get_text; - if ($criteria eq '') {return;} - - my $case = $self->search_case; - my $buffer = $self->buffer; - - - # Start the search at the last search result or from the current cursor's - # position. As a fall back we also add the beginning of the document. Once we - # have the start position we can erase the previous search results. - my @start; - if (my $highlighted = $self->highlighted) { - # Search from the last match - push @start, $buffer->get_iter_at_mark($highlighted->{marks}[1]); - $self->clear_highlighted(); - } - else { - # Search from the cursor - push @start, $buffer->get_iter_at_offset( - $buffer->get_property('cursor-position') - ); - } - push @start, $buffer->get_start_iter; - - my @iters; - #if ($self->search_regexp) { - if(1){ - # SourceView does not support regular expressions so we - # have to do the search by hand! - - my $text = $self->get_text; - my $regexp; - if ($self->search_regexp){ - $regexp = $case ? qr/$criteria/m : qr/$criteria/im; - }else { - $regexp = $case ? qr/\Q${criteria}\E/m : qr/\Q${criteria}\E/im; - - } - - foreach my $iter (@start) { - # Tell Perl where to start the regexp lookup - pos($text) = $iter->get_offset; - - if ($text =~ /($regexp)/g) { - my $word = $1; - my $pos = pos($text); - @iters = ( - $buffer->get_iter_at_offset($pos - length($word)), - $buffer->get_iter_at_offset($pos), - ); - last; - } - } - } - else { - # Use the builtin search mechanism - my $flags = $case ? [ ] : [ 'case-insensitive' ]; - foreach my $iter (@start) { - #@iters = Gtk3::SourceView::Iter->forward_search($iter, $criteria, $flags); - last if @iters; - } - } - - $self->show_highlighted(search => @iters) if @iters; + my $self = shift; + my $criteria = $self->search_entry->get_text; + if ($criteria eq '') {return;} + my $case = $self->search_case; + my $buffer = $self->buffer; + # Start the search at the last search result or from the current cursor's + # position. As a fall back we also add the beginning of the document. Once we + # have the start position we can erase the previous search results. + my @start; + if (my $highlighted = $self->highlighted) { + # Search from the last match + push @start, $buffer->get_iter_at_mark($highlighted->{marks}[1]); + $self->clear_highlighted(); + } + else { + # Search from the cursor + push @start, $buffer->get_iter_at_offset( + $buffer->get_property('cursor-position') + ); + } + push @start, $buffer->get_start_iter; + my @iters; + #if ($self->search_regexp) { + if(1){ + # SourceView does not support regular expressions so we + # have to do the search by hand! + my $text = $self->get_text; + my $regexp; + if ($self->search_regexp){ + $regexp = $case ? qr/$criteria/m : qr/$criteria/im; + }else { + $regexp = $case ? qr/\Q${criteria}\E/m : qr/\Q${criteria}\E/im; + } + foreach my $iter (@start) { + # Tell Perl where to start the regexp lookup + pos($text) = $iter->get_offset; + if ($text =~ /($regexp)/g) { + my $word = $1; + my $pos = pos($text); + @iters = ( + $buffer->get_iter_at_offset($pos - length($word)), + $buffer->get_iter_at_offset($pos), + ); + last; + } + } + } + else { + # Use the builtin search mechanism + my $flags = $case ? [ ] : [ 'case-insensitive' ]; + foreach my $iter (@start) { + #@iters = Gtk3::SourceView::Iter->forward_search($iter, $criteria, $flags); + last if @iters; + } + } + $self->show_highlighted(search => @iters) if @iters; } - sub show_highlighted { - my $self = shift; - my ($tag_name, $start, $end) = @_; - my $buffer = $self->buffer; - - # Highlight the region, remember it and scroll to it - my $match_start = $buffer->create_mark('match-start', $start, TRUE); - my $match_end = $buffer->create_mark('match-end', $end, FALSE); - - $buffer->apply_tag_by_name($tag_name, $start, $end); - - # We have a callback that listens to when the cursor is placed and we don't - # want it to undo our work! So let's unhighlight the previous entry. - delete $self->{highlighted}; - $buffer->place_cursor($end); - - $self->sourceview->scroll_to_mark( - $match_start, - 0.2, - FALSE, - 0.0, 0.5 - ); - - # Keep a reference to the markers once they have been added to the buffer. - # Using them before can be catastrophic (segmenation fault). - # - $self->highlighted({ - name => $tag_name, - marks => [$match_start, $match_end], - }); + my $self = shift; + my ($tag_name, $start, $end) = @_; + my $buffer = $self->buffer; + # Highlight the region, remember it and scroll to it + my $match_start = $buffer->create_mark('match-start', $start, TRUE); + my $match_end = $buffer->create_mark('match-end', $end, FALSE); + $buffer->apply_tag_by_name($tag_name, $start, $end); + # We have a callback that listens to when the cursor is placed and we don't + # want it to undo our work! So let's unhighlight the previous entry. + delete $self->{highlighted}; + $buffer->place_cursor($end); + $self->sourceview->scroll_to_mark( + $match_start, + 0.2, + FALSE, + 0.0, 0.5 + ); + # Keep a reference to the markers once they have been added to the buffer. + # Using them before can be catastrophic (segmenation fault). + # + $self->highlighted({ + name => $tag_name, + marks => [$match_start, $match_end], + }); } - sub do_file_new { - my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; - - my $dialog = save_file_dialog('New file'); - if(defined $sw){ - $dialog->set_current_folder ($sw); - #print "open_in:$sw\n"; - - } - - my $response = $dialog->run(); - if ($response eq 'ok') { - my $file=$dialog->get_filename; - save_file($file,''); - $tree_view->destroy; - ($tree_view,$tree_store) =$app->build_tree_view($sw); - add_widget_to_scrolled_win($tree_view,$scwin_dirs); - $scwin_dirs->show_all; - $app->load_source($file); - } - $dialog->destroy(); + my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; + my $dialog = save_file_dialog('New file'); + if(defined $sw){ + $dialog->set_current_folder ($sw); + #print "open_in:$sw\n"; + } + my $response = $dialog->run(); + if ($response eq 'ok') { + my $file=$dialog->get_filename; + save_file($file,''); + $tree_view->destroy; + ($tree_view,$tree_store) =$app->build_tree_view($sw); + add_widget_to_scrolled_win($tree_view,$scwin_dirs); + $scwin_dirs->show_all; + $app->load_source($file); + } + $dialog->destroy(); } sub do_remove{ - my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; - my $fname = $self->filename; - my $r = yes_no_dialog ("Are you sure you want to permanently delete $fname file?"); - return if $r eq 'no'; - $self->close_b()->clicked; - unlink $fname; - $tree_view->destroy; - ($tree_view,$tree_store) =$app->build_tree_view($sw); - add_widget_to_scrolled_win($tree_view,$scwin_dirs); - $scwin_dirs->show_all; - - + my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; + my $fname = $self->filename; + my $r = yes_no_dialog ("Are you sure you want to permanently delete $fname file?"); + return if $r eq 'no'; + $self->close_b()->clicked; + unlink $fname; + $tree_view->destroy; + ($tree_view,$tree_store) =$app->build_tree_view($sw); + add_widget_to_scrolled_win($tree_view,$scwin_dirs); + $scwin_dirs->show_all; } - sub do_file_open { - my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; - - my $dialog = gen_file_dialog("Open file..."); - $dialog->signal_connect(response => sub { - my ($dialog, $response) = @_; - - if ($response eq 'ok') { - my $file = $dialog->get_filename; - return if -d $file; - $app->load_source($file); - } - - $dialog->destroy(); - }); - $dialog->show(); + my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; + my $dialog = gen_file_dialog("Open file..."); + $dialog->signal_connect(response => sub { + my ($dialog, $response) = @_; + if ($response eq 'ok') { + my $file = $dialog->get_filename; + return if -d $file; + $app->load_source($file); + } + $dialog->destroy(); + }); + $dialog->show(); } - sub do_show_about_dialog { - about(Consts::VERSION); + about(Consts::VERSION); } - sub do_ask_goto_line { - my $self = shift; - - my $dialog=new_dialog_with_buttons($self); - - my $hbox =def_hbox(FALSE, 0); - $hbox->pack_start( - gen_label_in_left("Line number: "), - FALSE, FALSE, 0 - ); - my $entry = gen_entry(); - $hbox->pack_start($entry, TRUE, TRUE, 0); - - $dialog->get_content_area->add($hbox); - $dialog->show_all(); - - - # Signal handlers - $entry->signal_connect(activate => sub { - if ($entry->get_text =~ /(\d+)/) { - $dialog->response('ok'); - } - }); - - # Run the dialog - my $response = $dialog->run(); - - return unless $response eq 'ok'; - - return unless my ($line) = ($entry->get_text =~ /(\d+)/); - my $buffer = $self->buffer; - my $start = $buffer->get_iter_at_line($line - 1); - my $end = $start->copy; - $end->forward_to_line_end; - - $self->clear_highlighted(); - $self->show_highlighted(goto_line => $start, $end); - $dialog->destroy(); + my $self = shift; + my $dialog=new_dialog_with_buttons($self); + my $hbox =def_hbox(FALSE, 0); + $hbox->pack_start( + gen_label_in_left("Line number: "), + FALSE, FALSE, 0 + ); + my $entry = gen_entry(); + $hbox->pack_start($entry, TRUE, TRUE, 0); + $dialog->get_content_area->add($hbox); + $dialog->show_all(); + # Signal handlers + $entry->signal_connect(activate => sub { + if ($entry->get_text =~ /(\d+)/) { + $dialog->response('ok'); + } + }); + # Run the dialog + my $response = $dialog->run(); + return unless $response eq 'ok'; + return unless my ($line) = ($entry->get_text =~ /(\d+)/); + my $buffer = $self->buffer; + my $start = $buffer->get_iter_at_line($line - 1); + my $end = $start->copy; + $end->forward_to_line_end; + $self->clear_highlighted(); + $self->show_highlighted(goto_line => $start, $end); + $dialog->destroy(); } - sub do_quit { - my ($self,$window) = @_; - $window->destroy; + my ($self,$window) = @_; + $window->destroy; } - sub do_save_as { - my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; - - # If no file is associated with the editor then ask the user for a file where - # to save the contents of the buffer. - my $dialog = save_file_dialog('Save file'); - if(defined $sw){ - $dialog->set_current_folder ($sw); - #print "open_in:$sw\n"; - - } - - my $response = $dialog->run(); - if ($response eq 'ok') { - my $file=$dialog->get_filename; - - my $buffer = $self->buffer; - open my $handle, '>:encoding(UTF-8)', $file or die "Can't write to $file: $!"; - print $handle $self->get_text; - close $handle; - - $tree_view->destroy; - ($tree_view,$tree_store) =$app->build_tree_view($sw); - add_widget_to_scrolled_win($tree_view,$scwin_dirs); - $scwin_dirs->show_all; - $app->load_source($file); - - - } - $dialog->destroy(); - - + my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; + # If no file is associated with the editor then ask the user for a file where + # to save the contents of the buffer. + my $dialog = save_file_dialog('Save file'); + if(defined $sw){ + $dialog->set_current_folder ($sw); + #print "open_in:$sw\n"; + } + my $response = $dialog->run(); + if ($response eq 'ok') { + my $file=$dialog->get_filename; + my $buffer = $self->buffer; + open my $handle, '>:encoding(UTF-8)', $file or die "Can't write to $file: $!"; + print $handle $self->get_text; + close $handle; + $tree_view->destroy; + ($tree_view,$tree_store) =$app->build_tree_view($sw); + add_widget_to_scrolled_win($tree_view,$scwin_dirs); + $scwin_dirs->show_all; + $app->load_source($file); + } + $dialog->destroy(); } - sub do_save { - my $self = shift; - - my $filename = $self->filename; - - # If there's no file then do a save as... - if (! $filename) { - #$self->do_save_as(); - return; - } - - my $buffer = $self->buffer; - open my $handle, '>:encoding(UTF-8)', $filename or die "Can't write to $filename: $!"; - print $handle $self->get_text; - close $handle; - $self->set_source_label_modified(FALSE); - if (! $buffer->get_language) { - $self->detect_language($filename); - } + my $self = shift; + my $filename = $self->filename; + # If there's no file then do a save as... + if (! $filename) { + #$self->do_save_as(); + return; + } + my $buffer = $self->buffer; + open my $handle, '>:encoding(UTF-8)', $filename or die "Can't write to $filename: $!"; + print $handle $self->get_text; + close $handle; + $self->set_source_label_modified(FALSE); + if (! $buffer->get_language) { + $self->detect_language($filename); + } } - sub set_source_label_modified{ - my ($self,$is_modified)=@_; - $self->modified($is_modified); - my $buffer = $self->buffer; - $buffer->set_modified($is_modified); - my $label=$self->label(); - my $fname = $self->filename; - my ($name,$p,$suffix) = fileparse("$fname",qr"\..[^.]*$"); - + my ($self,$is_modified)=@_; + $self->modified($is_modified); + my $buffer = $self->buffer; + $buffer->set_modified($is_modified); + my $label=$self->label(); + my $fname = $self->filename; + my ($name,$p,$suffix) = fileparse("$fname",qr"\..[^.]*$"); if ($is_modified ==TRUE){ - $label->set_markup("*${name}${suffix}"); - }else{ - $label->set_markup("${name}${suffix}"); - - } - $label->show_all; + $label->set_markup("*${name}${suffix}"); + }else{ + $label->set_markup("${name}${suffix}"); + } + $label->show_all; } sub build_menu { - my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; - - - - my @menu_items = ( - [ "/_File", undef, undef, 0, "" ], - [ "/File/_New", "N", sub { $self->do_file_new($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app); }, 0, undef ], - [ "/File/_Open", "O", sub { $self->do_file_open($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) }, 0, undef ], - [ "/File/_Save", "S", sub { $self->do_save($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) }, 0, undef ], - [ "/File/_SaveAs", "S", sub { $self->do_save_as($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app)} , 0, undef], - [ "/File/_Delete", "D", sub { $self->do_remove($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app)} , 0, undef], - [ "/File/_Quit", "Q", sub { $self->do_quit($window) }, 0, undef ], - - [ "/_Search", undef, undef, 0, "" ], - [ "/Search/_Goto a Line", "L", sub { $self->do_ask_goto_line($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app)}, 0, undef ], - - [ "/_Help", undef, undef, 0, "" ], - [ "/_Help/_About", "F1", sub { $self->do_show_about_dialog($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) } , 0, undef ], - - - -); - - - return gen_MenuBar($window,@menu_items); - + my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) = @_; + my @menu_items = ( + [ "/_File", undef, undef, 0, "" ], + [ "/File/_New", "N", sub { $self->do_file_new($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app); }, 0, undef ], + [ "/File/_Open", "O", sub { $self->do_file_open($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) }, 0, undef ], + [ "/File/_Save", "S", sub { $self->do_save($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) }, 0, undef ], + [ "/File/_SaveAs", "S", sub { $self->do_save_as($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app)} , 0, undef], + [ "/File/_Delete", "D", sub { $self->do_remove($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app)} , 0, undef], + [ "/File/_Quit", "Q", sub { $self->do_quit($window) }, 0, undef ], + [ "/_Search", undef, undef, 0, "" ], + [ "/Search/_Goto a Line", "L", sub { $self->do_ask_goto_line($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app)}, 0, undef ], + [ "/_Help", undef, undef, 0, "" ], + [ "/_Help/_About", "F1", sub { $self->do_show_about_dialog($sw,$window,$tree_view,$tree_store,$scwin_dirs,$app) } , 0, undef ], + ); + return gen_MenuBar($window,@menu_items); } - - sub add_to_tree { - my ($tree_view,$tree_store, $parent, $dir, $path) = @_; -my $tree_model = $tree_view->get_model(); - -# If $parent already has children, then remove them first - - my $child = $tree_model->iter_children ($parent); - while ($child) { - - $tree_store->remove ($child); - $child = $tree_model->iter_children ($parent); - } - -# Add children from directory listing - opendir(DIRHANDLE, $path) || return ; #die "Cannot open directory:$path $!\n"; - foreach my $subdir (sort readdir(DIRHANDLE)) { - if ($subdir ne '.' and $subdir ne '..' - # and -d $path.$subdir and -r $path.$subdir -) { - my $child = $tree_store->append($parent); - - - $tree_store->set($child, 0, $subdir, 1, "$path$subdir/") ; - - } - } - closedir(DIRHANDLE); + my ($tree_view,$tree_store, $parent, $dir, $path) = @_; + my $tree_model = $tree_view->get_model(); + # If $parent already has children, then remove them first + my $child = $tree_model->iter_children ($parent); + while ($child) { + $tree_store->remove ($child); + $child = $tree_model->iter_children ($parent); + } + # Add children from directory listing + opendir(DIRHANDLE, $path) || return ; #die "Cannot open directory:$path $!\n"; + foreach my $subdir (sort readdir(DIRHANDLE)) { + if ($subdir ne '.' and $subdir ne '..' + # and -d $path.$subdir and -r $path.$subdir + ) { + my $child = $tree_store->append($parent); + $tree_store->set($child, 0, $subdir, 1, "$path$subdir/") ; + } + } + closedir(DIRHANDLE); } - # Directory expanded. Populate subdirectories in readiness. - sub populate_treeo { - -# $iter has been expanded - my ($tree_view,$tree_store, $iter, $tree_path) = @_; - my $tree_model = $tree_view->get_model(); - my ($dir, $path) = $tree_model->get($iter); - -# for each of $iter's children add any subdirectories - my $child = $tree_model->iter_children ($iter); - while ($child) { - my ($dir, $path) = $tree_model->get($child, 0, 1); - add_to_tree($tree_view,$tree_store, $child, $dir, $path); - $child = $tree_model->iter_next ($child); - } - return; + # $iter has been expanded + my ($tree_view,$tree_store, $iter, $tree_path) = @_; + my $tree_model = $tree_view->get_model(); + my ($dir, $path) = $tree_model->get($iter); + # for each of $iter's children add any subdirectories + my $child = $tree_model->iter_children ($iter); + while ($child) { + my ($dir, $path) = $tree_model->get($child, 0, 1); + add_to_tree($tree_view,$tree_store, $child, $dir, $path); + $child = $tree_model->iter_next ($child); + } + return; } - sub run_make_file { - my ($dir,$outtext, $args)=@_; - my $cmd = (defined $args) ? "cd \"$dir/\" \n make $args" : "cd \"$dir/\" \n make "; - my $error=0; - add_info($outtext,"$cmd\n"); - - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); - #($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); - - - if($exit){ - if($stderr){ - $stderr=~ s/[‘,’]//g; - add_info($outtext,"$stdout\n"); - add_colored_info($outtext,"$stderr\n","red"); - } - add_colored_info($outtext,"Compilation failed.\n",'red'); - print " failed!\n"; - return 0; - - }else{ - add_info($outtext,"$stdout\n"); - if($stderr){ #probebly had warning - $stderr=~ s/[‘,’]//g; - #add_info($outtext,"$stdout\n"); - add_colored_info($outtext,"$stderr\n","green"); - } - - add_colored_info($outtext,"Compilation finished successfully.\n",'blue'); - print " successful!\n"; - return 1; - } - - #add_info($outtext,"**********Quartus compilation is done successfully in $target_dir!*************\n") if($error==0); - - - + my ($dir,$outtext, $args)=@_; + my $cmd = (defined $args) ? "cd \"$dir/\" \n make $args" : "cd \"$dir/\" \n make "; + my $error=0; + add_info($outtext,"$cmd\n"); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); + #($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd); + if($exit){ + if($stderr){ + $stderr=~ s/[‘,’]//g; + add_info($outtext,"$stdout\n"); + add_colored_info($outtext,"$stderr\n","red"); + } + add_colored_info($outtext,"Compilation failed.\n",'red'); + print " failed!\n"; + return 0; + }else{ + add_info($outtext,"$stdout\n"); + if($stderr){ #probebly had warning + $stderr=~ s/[‘,’]//g; + #add_info($outtext,"$stdout\n"); + add_colored_info($outtext,"$stderr\n","green"); + } + add_colored_info($outtext,"Compilation finished successfully.\n",'blue'); + print " successful!\n"; + return 1; + } + #add_info($outtext,"**********Quartus compilation is done successfully in $target_dir!*************\n") if($error==0); } sub handle_key { @@ -990,26 +746,18 @@ sub handle_key { my $key = get_pressed_key ($event); my $buffer = $widget->get_buffer(); if ( ($key eq 'f') && control_pressed( $event ) ) { - - - my ($start, $end) = $buffer->get_selection_bounds; - if (defined $start && defined $end){ - my $string = $buffer->get_text ($start, $end, 0); - #print "CTRL+F copy $string to serach box\n"; - $self->search_entry->set_text($string); - } + my ($start, $end) = $buffer->get_selection_bounds; + if (defined $start && defined $end){ + my $string = $buffer->get_text ($start, $end, 0); + #print "CTRL+F copy $string to serach box\n"; + $self->search_entry->set_text($string); + } } - return FALSE; # FALSE -> means propagate key further } sub control_pressed { my ( $event ) = @_; - return $event->state & 'control-mask'; } - - - -1; - +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/sv_parser.pl b/mpsoc/perl_gui/lib/perl/sv_parser.pl index 1156382..c736f54 100644 --- a/mpsoc/perl_gui/lib/perl/sv_parser.pl +++ b/mpsoc/perl_gui/lib/perl/sv_parser.pl @@ -2,28 +2,21 @@ use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - - use Regexp::Common qw /comment/; require "common.pl"; - sub extract_sv_code { - my $file=shift; - my $text = load_file($file); - $text =~ s/($RE{comment}{'C++'})//g; + my $file=shift; + my $text = load_file($file); + $text =~ s/($RE{comment}{'C++'})//g; return $text; - - } - sub read_sv_file { - my $file=shift; - #read file and remove all comments - my $code = extract_sv_code($file); - print $code; -} + my $file=shift; + #read file and remove all comments + my $code = extract_sv_code($file); + print $code; +} \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/temp.pl b/mpsoc/perl_gui/lib/perl/temp.pl index 5f2c8a8..1377263 100755 --- a/mpsoc/perl_gui/lib/perl/temp.pl +++ b/mpsoc/perl_gui/lib/perl/temp.pl @@ -1,38 +1,28 @@ #!/usr/bin/perl -w - use strict; use warnings; use IO::CaptureOutput qw(capture qxx qxy); use Gtk3; - - - my ($screen_x,$screen_y); sub get_default_screen_size{ - return ($screen_x,$screen_y) if (defined $screen_x && defined $screen_y); - my $fh= 'xrandr --current | awk \'$2~/\*/{print $1}\'' ; - my ($stdout, $stderr, $success) = qxx( ($fh) ); - my @a = split ("\n",$stdout); - my ($screen_x,$screen_y) = split ("x",$a[0]); - $screen_x = 600 if(!defined $screen_x); - $screen_y = 800 if(!defined $screen_y); - return ($screen_x,$screen_y); -} - - + return ($screen_x,$screen_y) if (defined $screen_x && defined $screen_y); + my $fh= 'xrandr --current | awk \'$2~/\*/{print $1}\'' ; + my ($stdout, $stderr, $success) = qxx( ($fh) ); + my @a = split ("\n",$stdout); + my ($screen_x,$screen_y) = split ("x",$a[0]); + $screen_x = 600 if(!defined $screen_x); + $screen_y = 800 if(!defined $screen_y); + return ($screen_x,$screen_y); +} my ($x,$y) =get_default_screen_size(); print "$x,$y\n"; - - - sub get_screen_size{ my $screen = Gtk3::Gdk::Screen::get_default; - my $hight = $screen->get_height(); - my $width = $screen->get_width(); - return ($width,$hight); + my $hight = $screen->get_height(); + my $width = $screen->get_width(); + return ($width,$hight); } - ($x,$y) =get_screen_size(); print "$x,$y\n"; diff --git a/mpsoc/perl_gui/lib/perl/topology.pl b/mpsoc/perl_gui/lib/perl/topology.pl index 5535f17..b272f92 100644 --- a/mpsoc/perl_gui/lib/perl/topology.pl +++ b/mpsoc/perl_gui/lib/perl/topology.pl @@ -10,48 +10,41 @@ use lib $FindBin::Bin; sub get_topology_info { - my ($self,$noc_id) =@_; - $noc_id="" if (!defined $noc_id); - my $noc_param="noc_param$noc_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'); - 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); -} - + my ($self,$noc_id) =@_; + $noc_id="" if (!defined $noc_id); + my $noc_param="noc_param$noc_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'); + 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); + 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; # Total number of end points (local ports) in the NoC - my $NR; # Total number of routers in NoC - my $RAw; # Routers address width - my $EAw; # Endpoints address width - my $MAX_P; # Maximum number of ports in any router in the NoC - - my $Fw = 2+$V+$Fpay; - if($topology eq '"TREE"') { - my $K = $T1; + my ($topology, $T1, $T2, $T3,$V, $Fpay)=@_; + my $NE; # Total number of end points (local ports) in the NoC + my $NR; # Total number of routers in NoC + my $RAw; # Routers address width + my $EAw; # Endpoints address width + my $MAX_P; # Maximum number of ports in any router in the NoC + my $Fw = 2+$V+$Fpay; + if($topology eq '"TREE"') { + my $K = $T1; my $L = $T2; $NE = powi( $K,$L ); $NR = sum_powi ( $K,$L ); @@ -60,419 +53,386 @@ sub get_topology_info_sub { my $Lw=log2($L); $RAw=$LKw + $Lw; $EAw = $LKw; - $MAX_P = $K + 1; - - }elsif($topology eq '"FATTREE"') { - my $K = $T1; + $MAX_P = $K + 1; + }elsif($topology eq '"FATTREE"') { + my $K = $T1; my $L = $T2; - $NE = powi( $K,$L ); + $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; - $MAX_P = 2 * $K; - - }elsif ($topology eq '"RING"' || $topology eq '"LINE"'){ - my $NX=$T1; - my $NY=1; - my $NL=$T3; - $NE = $NX*$NY*$NL; + $MAX_P = 2 * $K; + }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; - $MAX_P = 2 + $NL; - - }elsif ($topology eq '"MESH"' || $topology eq '"TORUS"' ) { - my $NX=$T1; - my $NY=$T2; - my $NL=$T3; - $NE = $NX*$NY*$NL; - $NR = $NX*$NY; + $EAw = ($NL==1) ? $RAw : $RAw + $Lw; + $MAX_P = 2 + $NL; + }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; - $MAX_P = 4 + $NL; - - }elsif ($topology eq '"FMESH"'){ - my $NX=$T1; - my $NY=$T2; - my $NL=$T3; - $NE = $NX*$NY*$NL + 2*($NX + $NY); - $NR = $NX*$NY; + $MAX_P = 4 + $NL; + }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); - $MAX_P = 4 + $NL; - - }elsif ($topology eq '"STAR"' ) { - $NE= $T1; - $NR= 1; - $RAw=log2($NR); - $EAw=log2($NE); - $MAX_P = $NE; - - }else{ #custom - $NE= $T1; - $NR= $T2; - $RAw=log2($NR); - $EAw=log2($NE); - $MAX_P = $T3; - } - return ($NE, $NR, $RAw, $EAw, $Fw,$MAX_P); + $EAw = $RAw + log2(4+$NL); + $MAX_P = 4 + $NL; + }elsif ($topology eq '"STAR"' ) { + $NE= $T1; + $NR= 1; + $RAw=log2($NR); + $EAw=log2($NE); + $MAX_P = $NE; + }else{ #custom + $NE= $T1; + $NR= $T2; + $RAw=log2($NR); + $EAw=log2($NE); + $MAX_P = $T3; + } + return ($NE, $NR, $RAw, $EAw, $Fw,$MAX_P); } 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; + 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; + 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]; - } + 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($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; + 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 + 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 - } + 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; - } + 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; - } + 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; - } + 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; + 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); + 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); + 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); + 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); + 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 ($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; + 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 @temp = split ("'h",$p); - if (defined $temp[1]){ - #its hex format - my $m=0; - $p=remove_not_hex($temp[1]); - 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; - } - #its bin format - @temp = split ("'b",$p); - if (defined $temp[1]){ - my $m=0; - $p=remove_not_hex($temp[1]); - my @arr=split (//, $p); - foreach my $i (@arr) { - my $n=hex($i); - $m++ if($i); - } - return $m; - } - return 0;#Error - + my @temp = split ("'h",$p); + if (defined $temp[1]){ + #its hex format + my $m=0; + $p=remove_not_hex($temp[1]); + 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; + } + #its bin format + @temp = split ("'b",$p); + if (defined $temp[1]){ + my $m=0; + $p=remove_not_hex($temp[1]); + my @arr=split (//, $p); + foreach my $i (@arr) { + my $n=hex($i); + $m++ if($i); + } + return $m; + } + return 0;#Error } - - 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 = + 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 $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 @@ -480,268 +440,232 @@ sub get_noc_verilator_top_modules_info { $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"'){ + #"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 $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"') { - + #"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; + $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", - - ); + #"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_topology"; - 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}; + $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_topology"; + 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." - - - + $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 +#if ROUTER_P_NUM >$j #endif $st2=$st2." router_NRs[$p] =$nr_p{$p}; - for(i=0;ireset= reset; - router${i}[i]->clk= clk ; - } + for(i=0;ireset= reset; + router${i}[i]->clk= clk ; + } "; $st4=$st4." - for(i=0;ieval(); + for(i=0;ieval(); "; - $st5=$st5." - for(i=0;ifinal(); + for(i=0;ifinal(); "; - $st6=$st6." - if (ieval(); return;} - i-= NR${i}; + 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}; + 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}; + if (ireset= reset; + router${i}[i]->clk= clk ; + return; + } + i-= NR${i}; "; + $i++; + $j++; + $accum=$accum+$nr_p{$p}; + + } - - $i++; - $j++; - $accum=$accum+$nr_p{$p}; - -} - - $includ_h=$includ_h." - void Vrouter_new(){ - int i=0; - $st2 + int i=0; + $st2 } $custom_include void inline connect_routers_reset_clk(){ - int i; - $st3 + int i; + $st3 } - void inline routers_eval(){ - int i=0; - $st4 + int i=0; + $st4 } void inline routers_final(){ - int i; - $st5 -} + int i; + $st5 +} void inline single_router_eval(int i){ - $st6 + $st6 } #define SMART_NUM ((SMART_MAX==0)? 1 : SMART_MAX) - extern void update_router_st ( - unsigned int, - unsigned int, - void * , - size_t + unsigned int, + unsigned int, + void * , + size_t ); - + void single_router_st_update(int i){ - $st7 + $st7 } void inline single_router_reset_clk(int i){ - $st8 + $st8 } - -"; +"; #$includ_h.=" void connect_all_nodes(){\n"; @@ -750,139 +674,124 @@ sub get_noc_verilator_top_modules_info { #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); -# +# 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*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); -# } +# } +# 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); + 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); - - } - - } - - + 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] ) ); - "; + 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 ) ); - "; + 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); + 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; - } - + 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; + 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 + 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 \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index 5f436b2..17fe5d2 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -82,7 +82,7 @@ sub generate_topology_top_v { my ($cname,$pnode)=split(/\s*,\s*/,$connect); my $cinstance= $self->object_get_attribute("$cname","NAME"); my ($cp)= sscanf("Port[%u]","$pnode"); - #$assign = $assign."//Connect $instance output ports 0 to $cinstance input ports $cp\n"; + #$assign = $assign." //Connect $instance output ports 0 to $cinstance input ports $cp\n"; my $cpplus=$cp+1; foreach my $p (@ports){ my $w=$p->{pwidth}; @@ -174,13 +174,13 @@ sub get_router_instance_v { my $cinstance= $self->object_get_attribute("$cname","NAME"); my $ctype = $self->object_get_attribute("$cname",'TYPE'); my ($cp)= sscanf("Port[%u]","$pnode"); - $router_v = $router_v."//Connect $instance port $i to $cinstance port $cp\n"; + $router_v = $router_v." //Connect $instance port $i to $cinstance port $cp\n"; if($ctype ne 'ENDP'){ - $router_v.=" assign ${instance}_chan_in [$i] = ${cinstance}_chan_out [$cp];\n"; + $router_v.=" assign ${instance}_chan_in [$i] = ${cinstance}_chan_out [$cp];\n"; }else{ - $router_v.=" assign ${instance}_chan_in [$i] = ${cinstance}_chan_in;\n"; - $router_v.=" assign ${cinstance}_chan_out = ${instance}_chan_out [$i];\n"; - $router_v.=" assign ${cinstance}_router_event = ${instance}_router_event [$i];\n"; + $router_v.=" assign ${instance}_chan_in [$i] = ${cinstance}_chan_in;\n"; + $router_v.=" assign ${cinstance}_chan_out = ${instance}_chan_out [$i];\n"; + $router_v.=" assign ${cinstance}_router_event = ${instance}_router_event [$i];\n"; } my $cpplus=$cp+1; @@ -203,8 +203,8 @@ sub get_router_instance_v { } } #@port }else { - $router_v = $router_v."//Connect $instance port $i to ground - assign ${instance}_chan_in [$i]= {SMARTFLIT_CHANEL_w{1'b0}};\n"; + $router_v = $router_v." //Connect $instance port $i to ground + assign ${instance}_chan_in [$i]= {SMARTFLIT_CHANEL_w{1'b0}};\n"; foreach my $p (@ports){ my $w=$p->{pwidth}; my $range = ($w eq 1)? "[$i]" : "[($iplus*$w)-1 : $i*$w ]"; @@ -266,10 +266,10 @@ sub generate_topology_top_genvar_v{ input clk; input smartflit_chanel_t chan_in_all [NE-1 : 0]; output smartflit_chanel_t chan_out_all [NE-1 : 0]; - -//Events + + //Events output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; -//all routers port + //all routers port smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; @@ -381,7 +381,7 @@ sub generate_topology_top_genvar_v{ } $routers.="endgenerate\n"; print $fd " -module ${name}_noc_genvar +module ${name}_noc_genvar #( parameter NOC_ID=0 )( @@ -391,19 +391,12 @@ sub generate_topology_top_genvar_v{ chan_out_all, router_event ); - `NOC_CONF - $ports_def - $router_wires - $endps_wires - $routers - $assign - endmodule "; close $fd; @@ -511,7 +504,7 @@ sub get_wires_assignment_genvar_v{ my $cinstance= $self->object_get_attribute("$cname","NAME"); my $ctype = $self->object_get_attribute("$cname",'TYPE'); my ($cp)= sscanf("Port[%u]","$pnode"); - $assign.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + $assign.=" //Connect $instance input ports $i to $cinstance output ports $cp\n"; my $cpos =($ctype eq 'ENDP')? get_scolar_pos($cname,@ends) : get_scolar_pos($cname,@routers); my $cpplus=$cp+1; my $cposplus = $cpos+1; @@ -523,16 +516,16 @@ sub get_wires_assignment_genvar_v{ my $RNUM_cpos = $rinfo{"RNUM_${cpos}"}; #$assign = $assign."//connet $instance input port $i to $cinstance output port $cp\n"; if($type ne 'ENDP' && $ctype eq 'ENDP'){ - $assign= $assign." assign router_chan_in \[$pos\]\[$i\] = chan_in_all \[$cpos\];\n" if($reverse==0); - $assign= $assign." assign chan_in_all \[$cpos\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); - $assign= $assign." assign chan_out_all \[$cpos\] = router_chan_out \[$pos\]\[$i\];\n" if($reverse==0); - $assign= $assign." assign router_chan_out \[$pos\]\[$i\] = chan_out_all \[$cpos\];\n" if($reverse==1); - $r2e_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + $assign= $assign." assign router_chan_in \[$pos\]\[$i\] = chan_in_all \[$cpos\];\n" if($reverse==0); + $assign= $assign." assign chan_in_all \[$cpos\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); + $assign= $assign." assign chan_out_all \[$cpos\] = router_chan_out \[$pos\]\[$i\];\n" if($reverse==0); + $assign= $assign." assign router_chan_out \[$pos\]\[$i\] = chan_out_all \[$cpos\];\n" if($reverse==1); + $r2e_h.=" //Connect $instance input ports $i to $cinstance output ports $cp\n"; $r2e_h.= "void single_r2e$cpos(void) {connect_r2e($TNUM_pos,$RNUM_pos,$i,$cpos);}\n" if (defined $TNUM_pos); }elsif ($type ne 'ENDP' && $ctype ne 'ENDP'){ - $assign= $assign." assign router_chan_in \[$pos\]\[$i\] = router_chan_out \[$cpos\]\[$cp\];\n" if($reverse==0); - $assign= $assign." assign router_chan_out \[$cpos\]\[$cp\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); - $r2r_h.="//Connect $instance input ports $i to $cinstance output ports $cp\n"; + $assign= $assign." assign router_chan_in \[$pos\]\[$i\] = router_chan_out \[$cpos\]\[$cp\];\n" if($reverse==0); + $assign= $assign." assign router_chan_out \[$cpos\]\[$cp\] = router_chan_in \[$pos\]\[$i\];\n" if($reverse==1); + $r2r_h.=" //Connect $instance input ports $i to $cinstance output ports $cp\n"; $r2r_h.= "void single_r2r$R_num(void){conect_r2r($TNUM_pos,$RNUM_pos,$i,$TNUM_cpos,$RNUM_cpos,$cp);}\n" if (defined $TNUM_pos); $init_h.=" r2r_cnt_all[$R_num] =(r2r_cnt_table_t){.id1=$pos, .t1=$TNUM_pos, .r1=$RNUM_pos, .p1=$i,.id2=$cpos, .t2=$TNUM_cpos, .r2=$RNUM_cpos, .p2=$cp };\n"; $R_num++; @@ -540,10 +533,10 @@ sub get_wires_assignment_genvar_v{ }else { my $TNUM_pos = $rinfo{"TNUM_${pos}" }; my $RNUM_pos = $rinfo{"RNUM_${pos}" }; - $assign = $assign."//Connect $instance port $i to ground\n"; - $assign= $assign." assign router_chan_in \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==0); - $assign= $assign." assign router_chan_out \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==1); - $gnd_h.="//Connect $instance port $i to ground\n"; + $assign = $assign." //Connect $instance port $i to ground\n"; + $assign= $assign." assign router_chan_in \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==0); + $assign= $assign." assign router_chan_out \[$pos\]\[$i\] ={SMARTFLIT_CHANEL_w{1'b0}};\n " if($reverse==1); + $gnd_h.=" //Connect $instance port $i to ground\n"; $gnd_h.= " connect_r2gnd($TNUM_pos,$RNUM_pos,$i);\n" if (defined $TNUM_pos); } } diff --git a/mpsoc/perl_gui/lib/perl/trace_gen.pl b/mpsoc/perl_gui/lib/perl/trace_gen.pl index e90f818..cd42698 100644 --- a/mpsoc/perl_gui/lib/perl/trace_gen.pl +++ b/mpsoc/perl_gui/lib/perl/trace_gen.pl @@ -21,16 +21,16 @@ require "drag_drop.pl"; __PACKAGE__->mk_accessors(qw{ - window - sourceview - buffer - filename - search_regexp - search_case - search_entry - regexp - highlighted - + window + sourceview + buffer + filename + search_regexp + search_case + search_entry + regexp + highlighted + }); my $NAME = 'Trace_gen'; @@ -38,2097 +38,1552 @@ exit trace_gen_main() unless caller; - sub trace_gen_main { - my ($mode,$ref,$w)=@_; - my $app = __PACKAGE__->new(); - my $table=$app->build_trace_gui($mode,$ref,$w); - - return $table; + my ($mode,$ref,$w)=@_; + my $app = __PACKAGE__->new(); + my $table=$app->build_trace_gui($mode,$ref,$w); + return $table; } - ######## # trace_ctr ######## - sub trace_pad_ctrl{ - my ($self,$tview,$mode)=@_; - - my $table= def_table(2,10,FALSE); - - my $row=0; - my $col=0; - #$table->attach ($separator , 0, 10 , $row, $row+1,'fill','fill',2,2); $row++; - - my $add = def_image_button('icons/import.png'); - set_tip($add,'Load Task Graph') if($mode eq "task"); - set_tip($add,'Load ORCC source files') if($mode eq "orcc"); - my $remove = def_image_button('icons/cancel.png'); - set_tip($remove,'Remove Selected Trace(s)'); - my $draw = def_image_button('icons/diagram.png'); - set_tip($draw,'View Task Graph'); - my $auto = def_image_button('icons/refresh.png'); - set_tip($auto,'Automatically calculate the traces burst size and injection ratio according to their bandwidth'); - my $box=def_pack_hbox(FALSE,FALSE,$add,$draw,$remove,$auto); - - #my $auto = def_image_button('icons/setting.png'); - #set_tip($auto,'Automatically set the burst size and injection ratio according to the packet size and bandwidth'); - - - $col=0; - $table->attach ($box,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col++; - - $row++; - $col=0; - my $info="Automatically set the burst size and injection ratio according to the packet size and bandwidth"; - #add_param_widget($self,"Auto inject rate \& burst size",'Auto_inject', 0,"Check-box",1,$info, $table,$row,$col,1,'Auto',0,'ref',"vertical"); - $row++; - $col=0; - my $info1="If hard-build QoS is enabled in NoC by using Weighted round robin arbiter (WRRA) instead of RRA, then the initial weights allow QoS support in NoC as in presence of contention, packets with higher initial weights receive higher bandwidth and lower worst case delay compared to others." ; - - #my $selects="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,hot spot"; - my $min=$self->object_get_attribute('select_multiple','min_pck_size'); - my $max=$self->object_get_attribute('select_multiple','max_pck_size'); - $min=$max=5 if(!defined $min); - - my @selectedinfo; - $self->object_add_attribute('Auto','Auto_inject',"1\'b0" ); - my $a= $self->object_get_attribute('Auto','Auto_inject'); - - if ($a eq "1\'b0"){ - @selectedinfo = ( - { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>$info1, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Min pck size ", param_name=>'min_pck_size', type=>'Spin-button', default_val=>5, content=>"2,$max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, - { label=>" Max pck size ",param_name=>'max_pck_size', type=>'Spin-button', default_val=>5, content=>"$min,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, - { label=>" Burst_size ", param_name=>'burst_size', type=>'Spin-button', default_val=>1, content=>"1,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Inject rate(%) ", param_name=>'injct_rate', type=>'Spin-button', default_val=>10, content=>"1,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Inject rate variation(%) ", param_name=>'injct_rate_var', type=>'Spin-button', default_val=>20, content=>"0,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - - ); - - - }else{ - @selectedinfo = ( - { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Min pck size ", param_name=>'min_pck_size', type=>'Spin-button', default_val=>5, content=>"2,$max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, - { label=>" Max pck size ",param_name=>'max_pck_size', type=>'Spin-button', default_val=>5, content=>"$min,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, - - ); - } - if($mode eq "orcc"){ - my $v_val= $self->object_get_attribute('noc_param','V'); - my $v_max=$v_val-1; - my $c_val= $self->object_get_attribute('noc_param','C'); - my $c_max=($c_val==0)? 0 : $c_val-1; - - @selectedinfo = ( - { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Virtual chanel#", param_name=>'vc', type=>'Spin-button', default_val=>0, content=>"0,$v_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Message class# ", param_name=>'class', type=>'Spin-button', default_val=>0, content=>"0,$c_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef} - ); - - } - - - my @traces= get_trace_list($self,'raw'); - my $any_selected=0; - foreach my $p (@traces) { - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); - $any_selected=1 if($self->object_get_attribute("raw_$p",'selected')==1); - - } - - if($any_selected){ + my ($self,$tview,$mode)=@_; + my $table= def_table(2,10,FALSE); + my $row=0; + my $col=0; + #$table->attach ($separator , 0, 10 , $row, $row+1,'fill','fill',2,2); $row++; + my $add = def_image_button('icons/import.png'); + set_tip($add,'Load Task Graph') if($mode eq "task"); + set_tip($add,'Load ORCC source files') if($mode eq "orcc"); + my $remove = def_image_button('icons/cancel.png'); + set_tip($remove,'Remove Selected Trace(s)'); + my $draw = def_image_button('icons/diagram.png'); + set_tip($draw,'View Task Graph'); + my $auto = def_image_button('icons/refresh.png'); + set_tip($auto,'Automatically calculate the traces burst size and injection ratio according to their bandwidth'); + my $box=def_pack_hbox(FALSE,FALSE,$add,$draw,$remove,$auto); + #my $auto = def_image_button('icons/setting.png'); + #set_tip($auto,'Automatically set the burst size and injection ratio according to the packet size and bandwidth'); + $col=0; + $table->attach ($box,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col++; + $row++; + $col=0; + my $info="Automatically set the burst size and injection ratio according to the packet size and bandwidth"; + #add_param_widget($self,"Auto inject rate \& burst size",'Auto_inject', 0,"Check-box",1,$info, $table,$row,$col,1,'Auto',0,'ref',"vertical"); + $row++; + $col=0; + my $info1="If hard-build QoS is enabled in NoC by using Weighted round robin arbiter (WRRA) instead of RRA, then the initial weights allow QoS support in NoC as in presence of contention, packets with higher initial weights receive higher bandwidth and lower worst case delay compared to others." ; + #my $selects="tornado,transposed 1,transposed 2,bit reverse,bit complement,random,hot spot"; + my $min=$self->object_get_attribute('select_multiple','min_pck_size'); + my $max=$self->object_get_attribute('select_multiple','max_pck_size'); + $min=$max=5 if(!defined $min); + my @selectedinfo; + $self->object_add_attribute('Auto','Auto_inject',"1\'b0" ); + my $a= $self->object_get_attribute('Auto','Auto_inject'); + if ($a eq "1\'b0"){ + @selectedinfo = ( + { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>$info1, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Min pck size ", param_name=>'min_pck_size', type=>'Spin-button', default_val=>5, content=>"2,$max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, + { label=>" Max pck size ",param_name=>'max_pck_size', type=>'Spin-button', default_val=>5, content=>"$min,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, + { label=>" Burst_size ", param_name=>'burst_size', type=>'Spin-button', default_val=>1, content=>"1,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Inject rate(%) ", param_name=>'injct_rate', type=>'Spin-button', default_val=>10, content=>"1,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Inject rate variation(%) ", param_name=>'injct_rate_var', type=>'Spin-button', default_val=>20, content=>"0,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + ); + }else{ + @selectedinfo = ( + { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Min pck size ", param_name=>'min_pck_size', type=>'Spin-button', default_val=>5, content=>"2,$max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, + { label=>" Max pck size ",param_name=>'max_pck_size', type=>'Spin-button', default_val=>5, content=>"$min,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, + ); + } + if($mode eq "orcc"){ + my $v_val= $self->object_get_attribute('noc_param','V'); + my $v_max=$v_val-1; + my $c_val= $self->object_get_attribute('noc_param','C'); + my $c_max=($c_val==0)? 0 : $c_val-1; + @selectedinfo = ( + { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Virtual chanel#", param_name=>'vc', type=>'Spin-button', default_val=>0, content=>"0,$v_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Message class# ", param_name=>'class', type=>'Spin-button', default_val=>0, content=>"0,$c_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef} + ); + } + my @traces= get_trace_list($self,'raw'); + my $any_selected=0; + foreach my $p (@traces) { + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); + $any_selected=1 if($self->object_get_attribute("raw_$p",'selected')==1); + } + + if($any_selected){ add_Hsep_to_table($table,0, 10, $row);$row++; - $table->attach (gen_label_in_center('Apply to all selected traces'),0, 10, $row, $row+1,'fill','fill',2,2);$row++; - } - - foreach my $d (@selectedinfo) { - my $apply= def_image_button("icons/enter.png",undef); - $apply->signal_connect( 'clicked'=> sub{ - $self->object_add_attribute('select_multiple','action',$d->{param_name}); - $self->set_gui_status('ref',0); - }); - if($any_selected){ - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},$d->{new_status},"horizontal"); - $table->attach ($apply , $col, $col+1, $row,$row+1,'shrink','shrink',2,2);$row++;$col=0; - # $row=noc_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); - } - } - - - - - - - my $project_dir = get_project_dir()."/mpsoc/"; - - - $add->signal_connect ( 'clicked'=> sub{ - load_task_file($self,$project_dir,$tview) if($mode eq 'task'); - load_orcc_file($self,$tview) if($mode eq 'orcc'); - }); - - $draw->signal_connect ( 'clicked'=> sub{ - show_trace_diagram($self,'trace'); - }); - - $remove->signal_connect ( 'clicked'=> sub{ - $self->remove_selected_traces('raw'); - }); - - $auto->signal_connect ( 'clicked'=> sub{ - $self->auto_generate_injtratio('raw'); - }); - - - my $sc_win = add_widget_to_scrolled_win($table); - - - return $sc_win; - + $table->attach (gen_label_in_center('Apply to all selected traces'),0, 10, $row, $row+1,'fill','fill',2,2);$row++; + } + + foreach my $d (@selectedinfo) { + my $apply= def_image_button("icons/enter.png",undef); + $apply->signal_connect( 'clicked'=> sub{ + $self->object_add_attribute('select_multiple','action',$d->{param_name}); + $self->set_gui_status('ref',0); + }); + if($any_selected){ + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},$d->{new_status},"horizontal"); + $table->attach ($apply , $col, $col+1, $row,$row+1,'shrink','shrink',2,2);$row++;$col=0; + # $row=noc_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}); + } + } + + my $project_dir = get_project_dir()."/mpsoc/"; + $add->signal_connect ( 'clicked'=> sub{ + load_task_file($self,$project_dir,$tview) if($mode eq 'task'); + load_orcc_file($self,$tview) if($mode eq 'orcc'); + }); + + $draw->signal_connect ( 'clicked'=> sub{ + show_trace_diagram($self,'trace'); + }); + + $remove->signal_connect ( 'clicked'=> sub{ + $self->remove_selected_traces('raw'); + }); + + $auto->signal_connect ( 'clicked'=> sub{ + $self->auto_generate_injtratio('raw'); + }); + my $sc_win = add_widget_to_scrolled_win($table); + return $sc_win; } sub load_task_file{ - my($self,$project_dir,$tview)=@_; - my $file; - my $dialog = gen_file_dialog(undef,'app'); - my $open_in = abs_path("${project_dir}/perl_gui/lib/simulate/embedded_app_graphs"); - $dialog->set_current_folder ($open_in); - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - $self->load_tarce_file($file,$tview); - } - $dialog->destroy; + my($self,$project_dir,$tview)=@_; + my $file; + my $dialog = gen_file_dialog(undef,'app'); + my $open_in = abs_path("${project_dir}/perl_gui/lib/simulate/embedded_app_graphs"); + $dialog->set_current_folder ($open_in); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + $self->load_tarce_file($file,$tview); + } + $dialog->destroy; } ###### # map_ctr -###### - +###### sub trace_map_ctrl{ - - my ($self,$tview,$mode,$NE)=@_; - my $table= def_table(2,10,FALSE); - - my $run_map= def_image_button("icons/enter.png",undef); - my $drawmap = def_image_button('icons/trace.png'); - my $diagram = def_image_button('icons/diagram.png'); - set_tip($drawmap,'View actor Mapping Diagram') if($mode eq 'orcc'); - set_tip($drawmap,'View Task Mapping Diagram') if($mode eq 'task'); - set_tip($diagram,'View Topology Diagram') if($mode eq 'task'); - set_tip($diagram,'View actor connection Diagram') if($mode eq 'orcc'); - - my $auto = def_image_button('icons/refresh.png'); - set_tip($auto,'Automatically set the network dimensions according to the task number'); - my $clean = def_image_button('icons/clear.png'); - set_tip($clean,'Remove mapping'); - - my $box; - $box=def_pack_hbox(FALSE,FALSE,$drawmap,$diagram,$clean,$auto) if($mode eq 'task'); - $box=def_pack_hbox(FALSE,FALSE,$drawmap,$diagram,$clean) if($mode eq 'orcc'); - - my $col=0; - my $row=0; - $table->attach ($box,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$row++; - - - if($mode eq 'task'){ - ($row,$col) =noc_topology_setting_gui($self,$table,$tview,$row,1,""); - - $diagram-> signal_connect("clicked" => sub{ - show_topology_diagram ($self) ; - }); - - - } - - if($mode eq 'orcc'){ - - $diagram-> signal_connect("clicked" => sub{ - - show_trace_diagram ($self,'merge-actor'); - }); - - - } - - #my $credit =$self->object_get_attribute('map_param',"credit_en"); - #if(defined $credit){ - # if($credit eq '1\'b0'){ - # $self->object_add_attribute('map_param',"receive_int",'1\'b0'); - #}} - - - - my @info = ($mode eq 'task')? ( - { label=>"Mapping Algorithm", param_name=>"Map_Algrm", type=>"Combo-box", default_val=>'Random', content=>"Nmap,Random,Reverse-NMAP,Direct", info=>undef, param_parent=>'map_param',ref_delay=>undef,placement=>'horizontal'}, - ) : - - ( - { label=>"Mapping Algorithm", param_name=>"Map_Algrm", type=>"Combo-box", default_val=>'Random', content=>"Nmap,Random,Reverse-NMAP,Direct", info=>undef, param_parent=>'map_param',ref_delay=>undef,placement=>'horizontal'}, - { label=>"ORCC FIFO Debug", param_name=>"add_debug", type=>"Check-box", default_val=>'1\'b0', content=>1, info=>"Add Actor FIFO debugging code to generated C codes to make sure FIFOs handshakings signals are handeled correctly between the source and destination cores", param_parent=>'map_param',ref_delay=>undef,placement=>'vertical'}, - { label=>"Sent packet interrupt", param_name=>"sent_int", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"If the sent inttrupt is enabled, once a packet is completely sent out from the NI, the cpu is informed by intrrupt.", param_parent=>'map_param',ref_delay=>undef,placement=>'vertical'}, - { label=>"Receive packet interrupt", param_name=>"receive_int", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"This flag enables receive-interrupt. Hence, the CPU can collect the received packet immediately from the NI. This interrupt avoids the NoC to be blocked by long packets.", param_parent=>'map_param',ref_delay=>1,placement=>'vertical'}, - { label=>"Got NI error interrupt", param_name=>"got_err_int", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"Enable the inttrupt once any of NI error flags is asserted.", param_parent=>'map_param',ref_delay=>undef,placement=>'vertical'}, - #{ label=>"ORCC FIFO Credit", param_name=>"credit_en", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"If this flag is enabled, the credit availbility of destination FIFOs are transfered to source FIFOs. The source FIFOs adapts the sent data size with the available space in destination FIFO. This makes sure the destination FIFO can collet whole of the packet and perevent the NoC resources to be blocked by long packets", param_parent=>'map_param',ref_delay=>1,placement=>'vertical'}, - ); - - #push(@info,{ label=>"Recieve FIFO extra space (%)", param_name=>"rsv_extra", type=>"Spin-button",content=>"1,100,1", default_val=>10, info=>"If ORCC FIFO Credit flag is not enabled, additional space is added to receive FIFOs to avoid FIFO overflow. The receiver FIFO only collects the NI's incoming packet if its occupied size is smaller than this additional space. This memory overhead could be avoided if the packet size is added to the header pre-captured data. However, it is not yet supported.", param_parent=>'map_param',ref_delay=>1,placement=>'vertical'}, - #) if($credit eq '1\'b0'); - - foreach my $d (@info) { - ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},'ref',$d->{placement}); - if($d->{param_name} eq "Map_Algrm"){ - $table->attach ($run_map , $col, $col+1, $row,$row+1,'shrink','shrink',2,2);$row++;$col=0; - $table->attach (gen_label_in_center ("Enable/Disable flags:") , $col, $col+1, $row,$row+1,'shrink','shrink',2,2);$row++;$col=0; - } - } - - - - $run_map->signal_connect( 'clicked'=> sub{ - my $alg=$self->object_get_attribute('map_param','Map_Algrm'); - update_merge_actor_list($self,$tview); - $self->random_map() if ($alg eq 'Random'); - $self->worst_map_algorithm() if ($alg eq 'Reverse-NMAP'); - $self->nmap_algorithm() if ($alg eq 'Nmap'); - $self->direct_map() if ($alg eq 'Direct'); - - - }); - - $drawmap->signal_connect ( 'clicked'=> sub{ - show_trace_diagram($self,'map'); - }); - - $auto->signal_connect ( 'clicked'=> sub{ - my @tasks = $self->get_all_merged_tasks(); - my $task_num= scalar @tasks; - return if($task_num ==0); - my $topology = $self->object_get_attribute('noc_param','TOPOLOGY'); - if ($topology eq '"MESH"' || $topology eq '"TORUS"' ){ - my ($nx,$ny) =network_dim_cal($task_num); - $self->object_add_attribute('noc_param','T1',$nx); - $self->object_add_attribute('noc_param','T2',$ny); - $self->object_add_attribute('noc_param','T3',1); - set_gui_status($self,"ref",1); - }elsif ($topology eq '"RING"' || $topology eq '"LINE"'){ - $self->object_add_attribute('noc_param','T1',$task_num); - $self->object_add_attribute('noc_param','T2',1); - $self->object_add_attribute('noc_param','T3',1); - set_gui_status($self,"ref",1); - } - }); - - $clean->signal_connect ( 'clicked'=> sub{ - remove_mapping($self); - set_gui_status($self,"ref",1); - }); - - return add_widget_to_scrolled_win($table); - - + my ($self,$tview,$mode,$NE)=@_; + my $table= def_table(2,10,FALSE); + my $run_map= def_image_button("icons/enter.png",undef); + my $drawmap = def_image_button('icons/trace.png'); + my $diagram = def_image_button('icons/diagram.png'); + set_tip($drawmap,'View actor Mapping Diagram') if($mode eq 'orcc'); + set_tip($drawmap,'View Task Mapping Diagram') if($mode eq 'task'); + set_tip($diagram,'View Topology Diagram') if($mode eq 'task'); + set_tip($diagram,'View actor connection Diagram') if($mode eq 'orcc'); + my $auto = def_image_button('icons/refresh.png'); + set_tip($auto,'Automatically set the network dimensions according to the task number'); + my $clean = def_image_button('icons/clear.png'); + set_tip($clean,'Remove mapping'); + my $box; + $box=def_pack_hbox(FALSE,FALSE,$drawmap,$diagram,$clean,$auto) if($mode eq 'task'); + $box=def_pack_hbox(FALSE,FALSE,$drawmap,$diagram,$clean) if($mode eq 'orcc'); + my $col=0; + my $row=0; + $table->attach ($box,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$row++; + if($mode eq 'task'){ + ($row,$col) =noc_topology_setting_gui($self,$table,$tview,$row,1,""); + $diagram-> signal_connect("clicked" => sub{ + show_topology_diagram ($self) ; + }); + } + + if($mode eq 'orcc'){ + $diagram-> signal_connect("clicked" => sub{ + show_trace_diagram ($self,'merge-actor'); + }); + } + + #my $credit =$self->object_get_attribute('map_param',"credit_en"); + #if(defined $credit){ + # if($credit eq '1\'b0'){ + # $self->object_add_attribute('map_param',"receive_int",'1\'b0'); + #}} + + my @info = ($mode eq 'task')? ( + { label=>"Mapping Algorithm", param_name=>"Map_Algrm", type=>"Combo-box", default_val=>'Random', content=>"Nmap,Random,Reverse-NMAP,Direct", info=>undef, param_parent=>'map_param',ref_delay=>undef,placement=>'horizontal'}, + ) : + + ( + { label=>"Mapping Algorithm", param_name=>"Map_Algrm", type=>"Combo-box", default_val=>'Random', content=>"Nmap,Random,Reverse-NMAP,Direct", info=>undef, param_parent=>'map_param',ref_delay=>undef,placement=>'horizontal'}, + { label=>"ORCC FIFO Debug", param_name=>"add_debug", type=>"Check-box", default_val=>'1\'b0', content=>1, info=>"Add Actor FIFO debugging code to generated C codes to make sure FIFOs handshakings signals are handeled correctly between the source and destination cores", param_parent=>'map_param',ref_delay=>undef,placement=>'vertical'}, + { label=>"Sent packet interrupt", param_name=>"sent_int", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"If the sent inttrupt is enabled, once a packet is completely sent out from the NI, the cpu is informed by intrrupt.", param_parent=>'map_param',ref_delay=>undef,placement=>'vertical'}, + { label=>"Receive packet interrupt", param_name=>"receive_int", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"This flag enables receive-interrupt. Hence, the CPU can collect the received packet immediately from the NI. This interrupt avoids the NoC to be blocked by long packets.", param_parent=>'map_param',ref_delay=>1,placement=>'vertical'}, + { label=>"Got NI error interrupt", param_name=>"got_err_int", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"Enable the inttrupt once any of NI error flags is asserted.", param_parent=>'map_param',ref_delay=>undef,placement=>'vertical'}, + #{ label=>"ORCC FIFO Credit", param_name=>"credit_en", type=>"Check-box", default_val=>'1\'b1', content=>1, info=>"If this flag is enabled, the credit availbility of destination FIFOs are transfered to source FIFOs. The source FIFOs adapts the sent data size with the available space in destination FIFO. This makes sure the destination FIFO can collet whole of the packet and perevent the NoC resources to be blocked by long packets", param_parent=>'map_param',ref_delay=>1,placement=>'vertical'}, + ); + + #push(@info,{ label=>"Recieve FIFO extra space (%)", param_name=>"rsv_extra", type=>"Spin-button",content=>"1,100,1", default_val=>10, info=>"If ORCC FIFO Credit flag is not enabled, additional space is added to receive FIFOs to avoid FIFO overflow. The receiver FIFO only collects the NI's incoming packet if its occupied size is smaller than this additional space. This memory overhead could be avoided if the packet size is added to the header pre-captured data. However, it is not yet supported.", param_parent=>'map_param',ref_delay=>1,placement=>'vertical'}, + #) if($credit eq '1\'b0'); + foreach my $d (@info) { + ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},'ref',$d->{placement}); + if($d->{param_name} eq "Map_Algrm"){ + $table->attach ($run_map , $col, $col+1, $row,$row+1,'shrink','shrink',2,2);$row++;$col=0; + $table->attach (gen_label_in_center ("Enable/Disable flags:") , $col, $col+1, $row,$row+1,'shrink','shrink',2,2);$row++;$col=0; + } + } + + $run_map->signal_connect( 'clicked'=> sub{ + my $alg=$self->object_get_attribute('map_param','Map_Algrm'); + update_merge_actor_list($self,$tview); + $self->random_map() if ($alg eq 'Random'); + $self->worst_map_algorithm() if ($alg eq 'Reverse-NMAP'); + $self->nmap_algorithm() if ($alg eq 'Nmap'); + $self->direct_map() if ($alg eq 'Direct'); + }); + + $drawmap->signal_connect ( 'clicked'=> sub{ + show_trace_diagram($self,'map'); + }); + + $auto->signal_connect ( 'clicked'=> sub{ + my @tasks = $self->get_all_merged_tasks(); + my $task_num= scalar @tasks; + return if($task_num ==0); + my $topology = $self->object_get_attribute('noc_param','TOPOLOGY'); + if ($topology eq '"MESH"' || $topology eq '"TORUS"' ){ + my ($nx,$ny) =network_dim_cal($task_num); + $self->object_add_attribute('noc_param','T1',$nx); + $self->object_add_attribute('noc_param','T2',$ny); + $self->object_add_attribute('noc_param','T3',1); + set_gui_status($self,"ref",1); + }elsif ($topology eq '"RING"' || $topology eq '"LINE"'){ + $self->object_add_attribute('noc_param','T1',$task_num); + $self->object_add_attribute('noc_param','T2',1); + $self->object_add_attribute('noc_param','T3',1); + set_gui_status($self,"ref",1); + } + }); + + $clean->signal_connect ( 'clicked'=> sub{ + remove_mapping($self); + set_gui_status($self,"ref",1); + }); + return add_widget_to_scrolled_win($table); } ###### # map_ctr -###### +###### sub trace_group_ctrl{ - - my ($self,$tview,$mode,$NE)=@_; - my $table= def_table(2,10,FALSE); - - - - - my $clean = def_image_button('icons/clear.png'); - set_tip($clean,'Ungroup all actors'); - - my $box; - $box=def_pack_hbox(FALSE,FALSE,$clean); - - my $col=0; - my $row=0; - - - - - $table->attach ($box,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$row++; - - #$self->object_add_attribute('grouping','map_limit',$NE); - #add_param_widget ($self,'Max actors in a group:','map_limit', 4,"Spin-button","1,1024,1","The maximum number of actors that can be grouped to be run in one tile", $table,$row,$col,1,'grouping',undef,undef); - - - - $clean->signal_connect ( 'clicked'=> sub{ - my $group_num=$self->object_get_attribute('grouping','group_num'); - my $gname=$self->object_get_attribute('grouping','group_name_root'); - for(my $i=0;$i<$group_num;$i=$i+1){ - $self->object_add_attribute('grouping',"$gname($i)",\()); - } - set_gui_status($self,"ref",1); - }); - - - return add_widget_to_scrolled_win($table); - - - + my ($self,$tview,$mode,$NE)=@_; + my $table= def_table(2,10,FALSE); + my $clean = def_image_button('icons/clear.png'); + set_tip($clean,'Ungroup all actors'); + my $box; + $box=def_pack_hbox(FALSE,FALSE,$clean); + my $col=0; + my $row=0; + $table->attach ($box,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$row++; + #$self->object_add_attribute('grouping','map_limit',$NE); + #add_param_widget ($self,'Max actors in a group:','map_limit', 4,"Spin-button","1,1024,1","The maximum number of actors that can be grouped to be run in one tile", $table,$row,$col,1,'grouping',undef,undef); + $clean->signal_connect ( 'clicked'=> sub{ + my $group_num=$self->object_get_attribute('grouping','group_num'); + my $gname=$self->object_get_attribute('grouping','group_name_root'); + for(my $i=0;$i<$group_num;$i=$i+1){ + $self->object_add_attribute('grouping',"$gname($i)",\()); + } + set_gui_status($self,"ref",1); + }); + return add_widget_to_scrolled_win($table); } - - - - - - ######### # trace ######### - sub trace_pad{ - my ($self,$tview,$mode)=@_; - my $table= def_table(10,10,FALSE); - - my $row=0; - my $col=0; - - - my @selectedinfo = ( - { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Min pck size ", param_name=>'min_pck_size', type=>'Spin-button', default_val=>5, content=>"2,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, - { label=>" Max pck size ",param_name=>'max_pck_size', type=>'Spin-button', default_val=>5, content=>"2,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, - { label=>" Burst_size ", param_name=>'burst_size', type=>'Spin-button', default_val=>1, content=>"1,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Inject rate(%) ", param_name=>'injct_rate', type=>'Spin-button', default_val=>10, content=>"1,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Inject rate variation (%) ", param_name=>'injct_rate_var', type=>'Spin-button', default_val=>20, content=>"0,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - ); - - my $v_val= $self->object_get_attribute('noc_param','V'); - my $v_max=$v_val-1; - - my $c_val= $self->object_get_attribute('noc_param','C'); - my $c_max=($c_val==0)? 0 : $c_val-1; - - - if($mode eq "orcc"){ - - @selectedinfo = ( - { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Virtual chanel# ", param_name=>'vc', type=>'Spin-button', default_val=>0, content=>"0,$v_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, - { label=>" Message class# ", param_name=>'class', type=>'Spin-button', default_val=>0, content=>"0,$c_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef} - ); - } - - - my @traces= get_trace_list($self,'raw'); - my %f; - - - my $sel=$self->object_get_attribute('select_multiple','action'); - - foreach my $p (@traces) { - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); - $f{$file_id}=$file_id.'*'; - $self->object_add_attribute("raw_$p",'selected', 1 ) if ($sel eq 'All'); - $self->object_add_attribute("raw_$p",'selected', 0 ) if ($sel eq 'None'); - $self->object_add_attribute("raw_$p",'selected', 1 ) if ($sel eq "All-$file_id*"); - $self->object_add_attribute("raw_$p",'selected', 0 ) if ($sel eq "None-$file_id*"); - - my $seleceted =$self->object_get_attribute("raw_$p",'selected'); - foreach my $d (@selectedinfo) { - my $val=$self->object_get_attribute($d->{param_parent},$d->{param_name}) if ($sel eq $d->{param_name} && $seleceted); - $self->object_add_attribute("raw_$p",$d->{param_name}, $val ) if ($sel eq $d->{param_name}&& $seleceted); - - } - } - my $sel_options= "Select,All,None"; - if( keys %f > 1){ - foreach my $p (sort keys %f) { - $sel_options="$sel_options,All-$f{$p}"; - $sel_options="$sel_options,None-$f{$p}"; - } - } - $self->object_add_attribute('select_multiple','action',"Select"); - my $selcombo = $self-> gen_combobox_object ('select_multiple',"action", $sel_options,'-','ref',1); - - - if(scalar @traces ){$table-> attach ($selcombo, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++;} - - - my @titles; - #print "******************$mode*******************\n"; - if($mode eq 'task'){ - @titles = (scalar @traces ) ? (" # "," Source "," Destination "," Bandwidth(MB) ", " Initial weight ", " Min pck size ", " Max pck size "): - ("Load a task graph"); - } - else{ - @titles = (scalar @traces ) ? (" # "," Source "," Destination "," Bandwidth(MB) ", " Initial weight#", "Virtual chanel#", "Message class#"): - ("Load an ORCC file"); - } - - my $auto=$self->object_get_attribute('Auto','Auto_inject'); - - push (@titles, (" Burst_size ", " Inject rate(%) ", " Inject rate variation(%) ")) if ($auto eq "1\'b0" && $mode eq 'task'); - foreach my $p (@titles){ - $table-> attach (gen_label_in_left($p), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); - $col++; - } - $row++; - - my $i=0; - #my @t=sort { $a cmp $b } @traces; - - foreach my $p (@traces) { - $col=0; - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); - - - my $check = gen_check_box_object ($self,"raw_$p",'selected',0,'ref',0); - my $weight= gen_spin_object ($self,"raw_$p",'init_weight',"1,16,1", 1,undef,undef); - my $vc= gen_spin_object ($self,"raw_$p",'vc',"0,$v_max,1", 0,undef,undef); - my $class= gen_spin_object ($self,"raw_$p",'class',"0,$c_max,1", 0,undef,undef); - - my $min=$self->object_get_attribute("raw_$p",'min_pck_size'); - my $max=$self->object_get_attribute("raw_$p",'max_pck_size'); - $min=$max=5 if(!defined $min); - my $min_pck_size= gen_spin_object ($self,"raw_$p",'min_pck_size',"2,$max,1", 5,'ref',10); - my $max_pck_size= gen_spin_object ($self,"raw_$p",'max_pck_size',"$min,1024,1", 5,'ref',10); - - my $burst_size = gen_spin_object ($self,"raw_$p",'burst_size',"1,1024,1", 1,undef,undef); - my $injct_rate = gen_spin_object ($self,"raw_$p",'injct_rate',"1,100,1", 10,undef,undef); - my $injct_rate_var = gen_spin_object ($self,"raw_$p",'injct_rate_var',"0,100,1", 20,undef,undef); - - #my $weight= trace_$trace_id",'init_weight' - - $table-> attach ($check, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - $table-> attach (gen_label_in_left($i), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_left("$src") ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_left("$dst") , $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_left("$Mbytes") ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach ($weight ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - if($mode eq 'task'){ - $table-> attach ($min_pck_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach ($max_pck_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - if ($auto eq "1\'b0"){ - $table-> attach ($burst_size ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach ($injct_rate ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach ($injct_rate_var ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - } - }else{ - $table-> attach ($vc ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach ($class ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - } - - $row++; - - } - - my $sc_win = gen_scr_win_with_adjst($self,'trace_pad'); - $sc_win=add_widget_to_scrolled_win($table,$sc_win); - - return $sc_win; + my ($self,$tview,$mode)=@_; + my $table= def_table(10,10,FALSE); + my $row=0; + my $col=0; + my @selectedinfo = ( + { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Min pck size ", param_name=>'min_pck_size', type=>'Spin-button', default_val=>5, content=>"2,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, + { label=>" Max pck size ",param_name=>'max_pck_size', type=>'Spin-button', default_val=>5, content=>"2,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> 10, new_status=>'ref'}, + { label=>" Burst_size ", param_name=>'burst_size', type=>'Spin-button', default_val=>1, content=>"1,1024,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Inject rate(%) ", param_name=>'injct_rate', type=>'Spin-button', default_val=>10, content=>"1,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Inject rate variation (%) ", param_name=>'injct_rate_var', type=>'Spin-button', default_val=>20, content=>"0,100,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + ); + + my $v_val= $self->object_get_attribute('noc_param','V'); + my $v_max=$v_val-1; + my $c_val= $self->object_get_attribute('noc_param','C'); + my $c_max=($c_val==0)? 0 : $c_val-1; + if($mode eq "orcc"){ + @selectedinfo = ( + { label=>" Initial weight ", param_name=>'init_weight', type=>'Spin-button', default_val=>1, content=>"1,16,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Virtual chanel# ", param_name=>'vc', type=>'Spin-button', default_val=>0, content=>"0,$v_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef}, + { label=>" Message class# ", param_name=>'class', type=>'Spin-button', default_val=>0, content=>"0,$c_max,1", info=>undef, param_parent=>'select_multiple', ref_delay=> undef, new_status=>undef} + ); + } + + my @traces= get_trace_list($self,'raw'); + my %f; + my $sel=$self->object_get_attribute('select_multiple','action'); + foreach my $p (@traces) { + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); + $f{$file_id}=$file_id.'*'; + $self->object_add_attribute("raw_$p",'selected', 1 ) if ($sel eq 'All'); + $self->object_add_attribute("raw_$p",'selected', 0 ) if ($sel eq 'None'); + $self->object_add_attribute("raw_$p",'selected', 1 ) if ($sel eq "All-$file_id*"); + $self->object_add_attribute("raw_$p",'selected', 0 ) if ($sel eq "None-$file_id*"); + my $seleceted =$self->object_get_attribute("raw_$p",'selected'); + foreach my $d (@selectedinfo) { + my $val=$self->object_get_attribute($d->{param_parent},$d->{param_name}) if ($sel eq $d->{param_name} && $seleceted); + $self->object_add_attribute("raw_$p",$d->{param_name}, $val ) if ($sel eq $d->{param_name}&& $seleceted); + + } + } + my $sel_options= "Select,All,None"; + if( keys %f > 1){ + foreach my $p (sort keys %f) { + $sel_options="$sel_options,All-$f{$p}"; + $sel_options="$sel_options,None-$f{$p}"; + } + } + $self->object_add_attribute('select_multiple','action',"Select"); + my $selcombo = $self-> gen_combobox_object ('select_multiple',"action", $sel_options,'-','ref',1); + if(scalar @traces ){$table-> attach ($selcombo, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++;} + my @titles; + #print "******************$mode*******************\n"; + if($mode eq 'task'){ + @titles = (scalar @traces ) ? (" # "," Source "," Destination "," Bandwidth(MB) ", " Initial weight ", " Min pck size ", " Max pck size "): + ("Load a task graph"); + } + else{ + @titles = (scalar @traces ) ? (" # "," Source "," Destination "," Bandwidth(MB) ", " Initial weight#", "Virtual chanel#", "Message class#"): + ("Load an ORCC file"); + } + my $auto=$self->object_get_attribute('Auto','Auto_inject'); + push (@titles, (" Burst_size ", " Inject rate(%) ", " Inject rate variation(%) ")) if ($auto eq "1\'b0" && $mode eq 'task'); + foreach my $p (@titles){ + $table-> attach (gen_label_in_left($p), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); + $col++; + } + $row++; + my $i=0; + #my @t=sort { $a cmp $b } @traces; + foreach my $p (@traces) { + $col=0; + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); + my $check = gen_check_box_object ($self,"raw_$p",'selected',0,'ref',0); + my $weight= gen_spin_object ($self,"raw_$p",'init_weight',"1,16,1", 1,undef,undef); + my $vc= gen_spin_object ($self,"raw_$p",'vc',"0,$v_max,1", 0,undef,undef); + my $class= gen_spin_object ($self,"raw_$p",'class',"0,$c_max,1", 0,undef,undef); + my $min=$self->object_get_attribute("raw_$p",'min_pck_size'); + my $max=$self->object_get_attribute("raw_$p",'max_pck_size'); + $min=$max=5 if(!defined $min); + my $min_pck_size= gen_spin_object ($self,"raw_$p",'min_pck_size',"2,$max,1", 5,'ref',10); + my $max_pck_size= gen_spin_object ($self,"raw_$p",'max_pck_size',"$min,1024,1", 5,'ref',10); + my $burst_size = gen_spin_object ($self,"raw_$p",'burst_size',"1,1024,1", 1,undef,undef); + my $injct_rate = gen_spin_object ($self,"raw_$p",'injct_rate',"1,100,1", 10,undef,undef); + my $injct_rate_var = gen_spin_object ($self,"raw_$p",'injct_rate_var',"0,100,1", 20,undef,undef); + #my $weight= trace_$trace_id",'init_weight' + $table-> attach ($check, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_left($i), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_left("$src") ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_left("$dst") , $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_left("$Mbytes") ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach ($weight ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + if($mode eq 'task'){ + $table-> attach ($min_pck_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach ($max_pck_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + if ($auto eq "1\'b0"){ + $table-> attach ($burst_size ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach ($injct_rate ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach ($injct_rate_var ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + } + }else{ + $table-> attach ($vc ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach ($class ,$col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + } + $row++; + } + my $sc_win = gen_scr_win_with_adjst($self,'trace_pad'); + $sc_win=add_widget_to_scrolled_win($table,$sc_win); + return $sc_win; } - sub load_tarce_file{ - my ($self,$file,$tview)=@_; - #open file - my @x; - my %traces; - if (!defined $file) {return; } - if (-e $file) { - my $f_id=$self->object_get_attribute("file_id",undef); - my $t_id=$self->object_get_attribute("trace_id",undef); - open(my $fh, '<:encoding(UTF-8)', $file) or die "Could not open file '$file' $!"; - while (my $row = <$fh>) { - chomp $row; - my @data = split (/\s/,$row); - - next if (! defined $data[0]); - next if ($data[0] eq '#' || scalar @data < 3); - - $self->add_trace($f_id,'raw',$t_id,$data[0],$data[1],$data[2],$file); - $t_id++; - } - $f_id++; - $self->object_add_attribute("trace_id",undef,$t_id); - $self->object_add_attribute("file_id",undef,$f_id); - } - set_gui_status($self,"ref",1); - + my ($self,$file,$tview)=@_; + #open file + my @x; + my %traces; + if (!defined $file) {return; } + if (-e $file) { + my $f_id=$self->object_get_attribute("file_id",undef); + my $t_id=$self->object_get_attribute("trace_id",undef); + open(my $fh, '<:encoding(UTF-8)', $file) or die "Could not open file '$file' $!"; + while (my $row = <$fh>) { + chomp $row; + my @data = split (/\s/,$row); + next if (! defined $data[0]); + next if ($data[0] eq '#' || scalar @data < 3); + $self->add_trace($f_id,'raw',$t_id,$data[0],$data[1],$data[2],$file); + $t_id++; + } + $f_id++; + $self->object_add_attribute("trace_id",undef,$t_id); + $self->object_add_attribute("file_id",undef,$f_id); + } + set_gui_status($self,"ref",1); } - - - ######## # map ####### - - sub group_info { - my ($self,$tview,$mode)=@_; - my $table= def_table(10,10,FALSE); - - - my $sc_win = gen_scr_win_with_adjst($self,'trace_map'); - $sc_win=add_widget_to_scrolled_win($table,$sc_win); - - my $row=0; - my $col=0; - - my $lab= ($mode eq 'task')? "Task-name" :"Actor-name"; - - my @titles = (" # "," $lab ", " Internal" , " Sent ", " Resvd ", " Sent+Resvd "); - foreach my $p (@titles){ - $table-> attach (gen_label_in_left($p), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - } - $col=0; - $row++; - - - - my $i=0; - my @tasks=get_all_merged_tasks($self); - - - - - #print "tils=@tiles \nass=@assigned \nlist=@list\n"; - my %com_tasks= $self->get_communication_task('merge'); - #print Dumper(\%com_tasks); - foreach my $p (@tasks){ - - - $table-> attach (gen_label_in_left($i), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_left($p), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - my @a=('internal' , 'sent','rsv','total'); - foreach my $q (@a){ - my $s = (defined $com_tasks{$p}{$q}) ? $com_tasks{$p}{$q} : '-'; - $table-> attach (gen_label_in_left($s), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - } - - - - - - $i++; - $col=0; - $row++; - } - - - - - - return $sc_win; - + my ($self,$tview,$mode)=@_; + my $table= def_table(10,10,FALSE); + my $sc_win = gen_scr_win_with_adjst($self,'trace_map'); + $sc_win=add_widget_to_scrolled_win($table,$sc_win); + my $row=0; + my $col=0; + my $lab= ($mode eq 'task')? "Task-name" :"Actor-name"; + my @titles = (" # "," $lab ", " Internal" , " Sent ", " Resvd ", " Sent+Resvd "); + foreach my $p (@titles){ + $table-> attach (gen_label_in_left($p), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + } + $col=0; + $row++; + my $i=0; + my @tasks=get_all_merged_tasks($self); + #print "tils=@tiles \nass=@assigned \nlist=@list\n"; + my %com_tasks= $self->get_communication_task('merge'); + #print Dumper(\%com_tasks); + foreach my $p (@tasks){ + $table-> attach (gen_label_in_left($i), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $table-> attach (gen_label_in_left($p), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + my @a=('internal' , 'sent','rsv','total'); + foreach my $q (@a){ + my $s = (defined $com_tasks{$p}{$q}) ? $com_tasks{$p}{$q} : '-'; + $table-> attach (gen_label_in_left($s), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + } + $i++; + $col=0; + $row++; + } + return $sc_win; } - - - - - - - -######## -# map_info -####### - - - ######## # map_info ####### - - sub map_info { - my ($self)=@_; - my $sc_win = gen_scr_win_with_adjst($self,'map_info'); - my $table= def_table(10,10,FALSE); - - - my $row=0; - my $col=0; - my ($avg,$max,$min,$norm)=get_map_info($self); - - - my @data = ( - {0 => "Average distance", 1 =>"$avg"}, - {0 => "Max distance" , 1 =>"$max" }, - {0 => "Min distance" , 1 => "$min"}, - {0 => "Normalized data per hop", 1 =>"$norm" } - ); - - - - # create list store - my @clmn_type = ('Glib::String', 'Glib::String'); - my @clmns = ("Mapping Summary", " "); - add_widget_to_scrolled_win(gen_list_store (\@data,\@clmn_type,\@clmns),$sc_win); - $sc_win->show_all; - return $sc_win; - + my ($self)=@_; + my $sc_win = gen_scr_win_with_adjst($self,'map_info'); + my $table= def_table(10,10,FALSE); + my $row=0; + my $col=0; + my ($avg,$max,$min,$norm)=get_map_info($self); + my @data = ( + {0 => "Average distance", 1 =>"$avg"}, + {0 => "Max distance" , 1 =>"$max" }, + {0 => "Min distance" , 1 => "$min"}, + {0 => "Normalized data per hop", 1 =>"$norm" } + ); + # create list store + my @clmn_type = ('Glib::String', 'Glib::String'); + my @clmns = ("Mapping Summary", " "); + add_widget_to_scrolled_win(gen_list_store (\@data,\@clmn_type,\@clmns),$sc_win); + $sc_win->show_all; + return $sc_win; } - - - sub get_map_info { - my $self=shift; - my ($avg,$max,$min,$norm)=(0,0,999999,0); - my $sum=0; - my $num=0; - - my $data=0; - my $comtotal=0; - - my @traces= get_trace_list($self,'merge'); - - foreach my $p (@traces) { - my ($src, $dst, $Mbytes, $file_id, $file_name)=get_trace($self,'merge',$p); - #my $src_tile = $self->object_get_attribute('MAP_TILE',"$src"); - my $src_tile = get_task_give_tile($self,"$src"); - #my $dst_tile = $self->object_get_attribute('MAP_TILE',"$dst"); - my $dst_tile = get_task_give_tile($self,"$dst"); - next if(!defined $src_tile || !defined $dst_tile ); - next if($src_tile eq '-' || $dst_tile eq "-" ); - #my ($src_x,$src_y)= tile_id_to_loc($src_tile); - - #my ($dst_x,$dst_y)= tile_id_to_loc($dst_tile); - #print" ($dst_x,$dst_y)= tile_id_to_loc($dst_tile)\n"; - - my $mah_distance=get_endpoints_mah_distance($self,tile_id_number($src_tile),tile_id_number($dst_tile)); - #print "$mah_distance=get_mah_distance($src_x,$src_y,$dst_x,$dst_y);\n"; - $min = $mah_distance if($min> $mah_distance); - $max = $mah_distance if($max< $mah_distance); - $sum+=$mah_distance; - $num++; - - $data+=($Mbytes*$mah_distance); - $comtotal+=$Mbytes; - - } - - $avg=$sum/$num if($num!=0); - $min = 0 if $min == 999999; - $norm = $data/$comtotal if ($comtotal !=0); - return ($avg,$max,$min,$norm); - -} - - - - + my $self=shift; + my ($avg,$max,$min,$norm)=(0,0,999999,0); + my $sum=0; + my $num=0; + my $data=0; + my $comtotal=0; + my @traces= get_trace_list($self,'merge'); + foreach my $p (@traces) { + my ($src, $dst, $Mbytes, $file_id, $file_name)=get_trace($self,'merge',$p); + #my $src_tile = $self->object_get_attribute('MAP_TILE',"$src"); + my $src_tile = get_task_give_tile($self,"$src"); + #my $dst_tile = $self->object_get_attribute('MAP_TILE',"$dst"); + my $dst_tile = get_task_give_tile($self,"$dst"); + next if(!defined $src_tile || !defined $dst_tile ); + next if($src_tile eq '-' || $dst_tile eq "-" ); + #my ($src_x,$src_y)= tile_id_to_loc($src_tile); + #my ($dst_x,$dst_y)= tile_id_to_loc($dst_tile); + #print" ($dst_x,$dst_y)= tile_id_to_loc($dst_tile)\n"; + my $mah_distance=get_endpoints_mah_distance($self,tile_id_number($src_tile),tile_id_number($dst_tile)); + #print "$mah_distance=get_mah_distance($src_x,$src_y,$dst_x,$dst_y);\n"; + $min = $mah_distance if($min> $mah_distance); + $max = $mah_distance if($max< $mah_distance); + $sum+=$mah_distance; + $num++; + $data+=($Mbytes*$mah_distance); + $comtotal+=$Mbytes; + } + $avg=$sum/$num if($num!=0); + $min = 0 if $min == 999999; + $norm = $data/$comtotal if ($comtotal !=0); + return ($avg,$max,$min,$norm); +} sub map_combobox { - my ($object,$task_name,$content,$default)=@_; - my @combo_list=@{$content}; - #my $value=$object->object_get_attribute("MAP_TILE",$task_name); - my $value=get_task_give_tile($object,$task_name); - my $pos; - $pos=get_pos($value, @combo_list) if (defined $value); - if(!defined $pos && defined $default){ - #$object->object_add_attribute("MAP_TILE",$task_name,$default); - $pos=get_item_pos($default, @combo_list); - } - #print " my $pos=get_item_pos($value, @combo_list);\n"; - my $widget=gen_combo(\@combo_list, $pos); - $widget-> signal_connect("changed" => sub{ - my $new_tile=$widget->get_active_text(); - $object->map_task($task_name,$new_tile); - - set_gui_status($object,'ref',1); - }); - return $widget; + my ($object,$task_name,$content,$default)=@_; + my @combo_list=@{$content}; + #my $value=$object->object_get_attribute("MAP_TILE",$task_name); + my $value=get_task_give_tile($object,$task_name); + my $pos; + $pos=get_pos($value, @combo_list) if (defined $value); + if(!defined $pos && defined $default){ + #$object->object_add_attribute("MAP_TILE",$task_name,$default); + $pos=get_item_pos($default, @combo_list); + } + #print " my $pos=get_item_pos($value, @combo_list);\n"; + my $widget=gen_combo(\@combo_list, $pos); + $widget-> signal_connect("changed" => sub{ + my $new_tile=$widget->get_active_text(); + $object->map_task($task_name,$new_tile); + + set_gui_status($object,'ref',1); + }); + return $widget; } ########## -# save_as +# save_as ########## sub save_as{ - my ($self)=@_; - # read emulation name - my $name=$self->object_get_attribute ("save_as",undef); - my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; - if ($s == 0){ - message_dialog("Please define file name!"); - return 0; - } - # Write object file - open(FILE, ">lib/simulate/$name.TRC") || die "Can not open: $!"; - print FILE perl_file_header("$name.TRC"); - print FILE Data::Dumper->Dump([\%$self],['Trace']); - close(FILE) || die "Error closing file: $!"; - message_dialog("workspace has been saved as lib/simulate/$name.TRC!"); - return 1; + my ($self)=@_; + # read emulation name + my $name=$self->object_get_attribute ("save_as",undef); + my $s= (!defined $name)? 0 : (length($name)==0)? 0 :1; + if ($s == 0){ + message_dialog("Please define file name!"); + return 0; + } + # Write object file + open(FILE, ">lib/simulate/$name.TRC") || die "Can not open: $!"; + print FILE perl_file_header("$name.TRC"); + print FILE Data::Dumper->Dump([\%$self],['Trace']); + close(FILE) || die "Error closing file: $!"; + message_dialog("workspace has been saved as lib/simulate/$name.TRC!"); + return 1; } - - ############# -# load_workspace +# load_workspace ############ - sub load_workspace { - my $self=shift; - my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); - - my $file; - my $dialog = gen_file_dialog(undef,'TRC'); - my $dir = Cwd::getcwd(); - $dialog->set_current_folder ("$dir/lib/simulate"); - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if($suffix eq '.TRC'){ - - my ($pp,$r,$err) = regen_object($file); - if ($r){ - message_dialog("Error reading $file file: $err\n",'error'); - $dialog->destroy; - return; - } - - my ($tmp,$r1,$err1) = regen_object($file); - - - clone_obj($tmp,$self); - - - clone_obj($self,$pp); - - #update current parameter - my @pnames=('soc_name','ni_name','noc_param'); - foreach my $n (@pnames){ - my $param=$tmp->object_get_attribute($n); - if( defined $param){ - my %params=%{$param}; - foreach my $p (sort keys %params){ - $self->{$n}{$p}=$params{$p}; - } - } - } - - #update mpsocname - $self->object_add_attribute('mpsoc_name',undef,$mpsoc_name) if (defined $mpsoc_name); - - - - - - - #print Dumper($self); - - #message_dialog("done!"); - } - } - $dialog->destroy; + my $self=shift; + my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); + my $file; + my $dialog = gen_file_dialog(undef,'TRC'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/lib/simulate"); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.TRC'){ + + my ($pp,$r,$err) = regen_object($file); + if ($r){ + message_dialog("Error reading $file file: $err\n",'error'); + $dialog->destroy; + return; + } + my ($tmp,$r1,$err1) = regen_object($file); + clone_obj($tmp,$self); + clone_obj($self,$pp); + #update current parameter + my @pnames=('soc_name','ni_name','noc_param'); + foreach my $n (@pnames){ + my $param=$tmp->object_get_attribute($n); + if( defined $param){ + my %params=%{$param}; + foreach my $p (sort keys %params){ + $self->{$n}{$p}=$params{$p}; + } + } + } + #update mpsocname + $self->object_add_attribute('mpsoc_name',undef,$mpsoc_name) if (defined $mpsoc_name); + #print Dumper($self); + #message_dialog("done!"); + } + } + $dialog->destroy; } ######## # genereate_output_tasks ######## - sub genereate_output_tasks{ - my $self=shift; - my $name= $self->object_get_attribute('out_name'); - my $size= (defined $name)? length($name) :0; - if ($size ==0) { - message_dialog("Please define the output file name!"); - return 0; - } - - - - # make target dir - my $dir = Cwd::getcwd(); - my $target_dir = "$ENV{'PRONOC_WORK'}/traffic_pattern"; - mkpath("$target_dir",1,0755); - - my @tasks=get_all_merged_tasks($self); - foreach my $p (@tasks) { - #my $tile=$self->object_get_attribute("MAP_TILE",$p); - my $tile= get_task_give_tile($self,$p); - if ( $tile eq "-" ){ - message_dialog("Error: unmapped task. Please map task $p to a tile", 'error' ); - return; - } - - } - #creat output file + my $self=shift; + my $name= $self->object_get_attribute('out_name'); + my $size= (defined $name)? length($name) :0; + if ($size ==0) { + message_dialog("Please define the output file name!"); + return 0; + } + # make target dir + my $dir = Cwd::getcwd(); + my $target_dir = "$ENV{'PRONOC_WORK'}/traffic_pattern"; + mkpath("$target_dir",1,0755); + my @tasks=get_all_merged_tasks($self); + foreach my $p (@tasks) { + #my $tile=$self->object_get_attribute("MAP_TILE",$p); + my $tile= get_task_give_tile($self,$p); + if ( $tile eq "-" ){ + message_dialog("Error: unmapped task. Please map task $p to a tile", 'error' ); + return; + } + } + #creat output file open(FILE, ">$target_dir/$name.cfg") || die "Can not open: $!"; - print FILE get_cfg_content($self); - close(FILE) || die "Error closing file: $!"; - message_dialog("The traffic pattern is saved as $target_dir/$name.cfg" ); - + print FILE get_cfg_content($self); + close(FILE) || die "Error closing file: $!"; + message_dialog("The traffic pattern is saved as $target_dir/$name.cfg" ); } sub get_cfg_content{ - my $self=shift; - my $file="% source tile, destination tile, bytes, initial_weight, min_pck_size, max_pck_size, burst_size, injection_rate(%), injection_rate variation(%)\n"; - - - - my @tasks= get_trace_list($self,'merge'); - my @traces= get_trace_list($self,'raw'); - - foreach my $p (@traces){ - my ($src_r,$dst_r, $Mbytes_r, $file_id_r, $file_name_r,$init_weight_r,$min_pck_r, $max_pck_r, $burst_r, $injct_rate_r, $injct_rate_var_r)=get_trace($self,'raw',$p); - - - my $src =$self->get_item_group_name('grouping',$src_r); - my $dst =$self->get_item_group_name('grouping',$dst_r); - if ($src eq $dst){ - # source-destination is merged to one tile so ommit it - next; - - }else{ - - my $minpck = $self->object_get_attribute("raw_$p",'min_pck_size'); - my $maxpck = $self->object_get_attribute("raw_$p",'max_pck_size'); - my $avg_pck_size =($minpck+ $maxpck)/2; - my $pck_num = ($Mbytes_r*8) /($avg_pck_size*64); - $pck_num= 1 if($pck_num==0); - - my $src_tile = tile_id_number(get_task_give_tile($self,"$src")); - my $dst_tile = tile_id_number(get_task_give_tile($self,"$dst")); - - my $auto=$self->object_get_attribute('Auto','Auto_inject'); - - my $bytes = $Mbytes_r * 1000000; - - $file=$file."$src_tile, $dst_tile, $bytes, $init_weight_r, $min_pck_r, $max_pck_r"; - $file=$file.", $burst_r, $injct_rate_r, $injct_rate_var_r \n" if ($auto eq "1\'b0"); - $file=$file." \n" if ($auto eq "1\'b1"); - - - } - } - - - - return $file; + my $self=shift; + my $file="% source tile, destination tile, bytes, initial_weight, min_pck_size, max_pck_size, burst_size, injection_rate(%), injection_rate variation(%)\n"; + my @tasks= get_trace_list($self,'merge'); + my @traces= get_trace_list($self,'raw'); + foreach my $p (@traces){ + my ($src_r,$dst_r, $Mbytes_r, $file_id_r, $file_name_r,$init_weight_r,$min_pck_r, $max_pck_r, $burst_r, $injct_rate_r, $injct_rate_var_r)=get_trace($self,'raw',$p); + my $src =$self->get_item_group_name('grouping',$src_r); + my $dst =$self->get_item_group_name('grouping',$dst_r); + if ($src eq $dst){ + # source-destination is merged to one tile so ommit it + next; + }else{ + my $minpck = $self->object_get_attribute("raw_$p",'min_pck_size'); + my $maxpck = $self->object_get_attribute("raw_$p",'max_pck_size'); + my $avg_pck_size =($minpck+ $maxpck)/2; + my $pck_num = ($Mbytes_r*8) /($avg_pck_size*64); + $pck_num= 1 if($pck_num==0); + my $src_tile = tile_id_number(get_task_give_tile($self,"$src")); + my $dst_tile = tile_id_number(get_task_give_tile($self,"$dst")); + my $auto=$self->object_get_attribute('Auto','Auto_inject'); + my $bytes = $Mbytes_r * 1000000; + $file=$file."$src_tile, $dst_tile, $bytes, $init_weight_r, $min_pck_r, $max_pck_r"; + $file=$file.", $burst_r, $injct_rate_r, $injct_rate_var_r \n" if ($auto eq "1\'b0"); + $file=$file." \n" if ($auto eq "1\'b1"); + } + } + return $file; } sub add_trace{ - my ($self, $file_id,$category,$trace_id, $source,$dest, $Mbytes, $file_name,$src_port,$dst_port,$buff_size,$chanel,$vc,$class)=@_; - $self->object_add_attribute("${category}_$trace_id",'file',$file_id); - $self->object_add_attribute("${category}_$trace_id",'source',"${source}"); - $self->object_add_attribute("${category}_$trace_id",'destination',"${dest}"); - $self->object_add_attribute("${category}_$trace_id",'Mbytes', $Mbytes); - $self->object_add_attribute("${category}_$trace_id",'file_name', $file_name); - $self->object_add_attribute("${category}_$trace_id",'selected', 0); - $self->object_add_attribute("${category}_$trace_id",'init_weight', 1); - $self->object_add_attribute("${category}_$trace_id",'scr_port',$src_port); - $self->object_add_attribute("${category}_$trace_id",'dst_port',$dst_port); - $self->object_add_attribute("${category}_$trace_id",'buff_size',$buff_size); - $self->object_add_attribute("${category}_$trace_id",'chanel',$chanel); - $self->object_add_attribute("${category}_$trace_id",'vc',$vc); - $self->object_add_attribute("${category}_$trace_id",'class',$class); - $self->{"${category}_traces"}{$trace_id}=1; - + my ($self, $file_id,$category,$trace_id, $source,$dest, $Mbytes, $file_name,$src_port,$dst_port,$buff_size,$chanel,$vc,$class)=@_; + $self->object_add_attribute("${category}_$trace_id",'file',$file_id); + $self->object_add_attribute("${category}_$trace_id",'source',"${source}"); + $self->object_add_attribute("${category}_$trace_id",'destination',"${dest}"); + $self->object_add_attribute("${category}_$trace_id",'Mbytes', $Mbytes); + $self->object_add_attribute("${category}_$trace_id",'file_name', $file_name); + $self->object_add_attribute("${category}_$trace_id",'selected', 0); + $self->object_add_attribute("${category}_$trace_id",'init_weight', 1); + $self->object_add_attribute("${category}_$trace_id",'scr_port',$src_port); + $self->object_add_attribute("${category}_$trace_id",'dst_port',$dst_port); + $self->object_add_attribute("${category}_$trace_id",'buff_size',$buff_size); + $self->object_add_attribute("${category}_$trace_id",'chanel',$chanel); + $self->object_add_attribute("${category}_$trace_id",'vc',$vc); + $self->object_add_attribute("${category}_$trace_id",'class',$class); + $self->{"${category}_traces"}{$trace_id}=1; } sub add_trace_extra { - my ($self, $file_id,$category,$trace_id,$min_pck, $max_pck,$burst, $injct_rate, $injct_rate_var)=@_; - $self->object_add_attribute("${category}_$trace_id",'min_pck_size',$min_pck); - $self->object_add_attribute("${category}_$trace_id",'max_pck_size',$max_pck); - $self->object_add_attribute("${category}_$trace_id",'burst_size',$burst); - $self->object_add_attribute("${category}_$trace_id",'injct_rate',$injct_rate); - $self->object_add_attribute("${category}_$trace_id",'injct_rate_var',$injct_rate_var); -} - + my ($self, $file_id,$category,$trace_id,$min_pck, $max_pck,$burst, $injct_rate, $injct_rate_var)=@_; + $self->object_add_attribute("${category}_$trace_id",'min_pck_size',$min_pck); + $self->object_add_attribute("${category}_$trace_id",'max_pck_size',$max_pck); + $self->object_add_attribute("${category}_$trace_id",'burst_size',$burst); + $self->object_add_attribute("${category}_$trace_id",'injct_rate',$injct_rate); + $self->object_add_attribute("${category}_$trace_id",'injct_rate_var',$injct_rate_var); +} sub remove_trace{ - my ($self,$category, $trace_id)=@_; - delete $self->{"${category}_$trace_id"}; - delete $self->{"${category}_traces"}{$trace_id}; + my ($self,$category, $trace_id)=@_; + delete $self->{"${category}_$trace_id"}; + delete $self->{"${category}_traces"}{$trace_id}; } sub get_trace_list{ - my ($self,$category)=@_; - #print "($self,$category)\n"; - return sort (keys %{$self->{"${category}_traces"}}); + my ($self,$category)=@_; + #print "($self,$category)\n"; + return sort (keys %{$self->{"${category}_traces"}}); } sub remove_all_traces{ - my ($self,$category)=@_; - my @all =get_trace_list($self,$category); - foreach my $trace_id (@all ){ - remove_trace ($self,$category, $trace_id); - } + my ($self,$category)=@_; + my @all =get_trace_list($self,$category); + foreach my $trace_id (@all ){ + remove_trace ($self,$category, $trace_id); + } } - sub get_trace{ - my ($self,$category,$trace_id)=@_; - my $file_id = $self->object_get_attribute("${category}_$trace_id",'file'); - my $source = $self->object_get_attribute("${category}_$trace_id",'source'); - my $dest = $self->object_get_attribute("${category}_$trace_id",'destination'); - my $Mbytes = $self->object_get_attribute("${category}_$trace_id",'Mbytes'); - my $file_name = $self->object_get_attribute("${category}_$trace_id",'file_name'); - my $init_weight = $self->object_get_attribute("${category}_$trace_id",'init_weight'); - my $min_pck_size= $self->object_get_attribute("${category}_$trace_id",'min_pck_size'); - my $max_pck_size= $self->object_get_attribute("${category}_$trace_id",'max_pck_size'); - my $burst_size = $self->object_get_attribute("${category}_$trace_id",'burst_size'); - my $injct_rate = $self->object_get_attribute("${category}_$trace_id",'injct_rate'); - my $injct_rate_var = $self->object_get_attribute("${category}_$trace_id",'injct_rate_var'); - my $src_port = $self->object_get_attribute("${category}_$trace_id",'scr_port'); - my $dst_port = $self->object_get_attribute("${category}_$trace_id",'dst_port'); - my $buff_size= $self->object_get_attribute("${category}_$trace_id",'buff_size'); - my $chanel = $self->object_get_attribute("${category}_$trace_id",'chanel'); - my $vc= $self->object_get_attribute("${category}_$trace_id",'vc'); - my $class= $self->object_get_attribute("${category}_$trace_id",'class'); - return ($source,$dest, $Mbytes, $file_id,$file_name,$init_weight,$min_pck_size, $max_pck_size, $burst_size, $injct_rate, $injct_rate_var, $src_port,$dst_port,$buff_size,$chanel,$vc,$class); + my ($self,$category,$trace_id)=@_; + my $file_id = $self->object_get_attribute("${category}_$trace_id",'file'); + my $source = $self->object_get_attribute("${category}_$trace_id",'source'); + my $dest = $self->object_get_attribute("${category}_$trace_id",'destination'); + my $Mbytes = $self->object_get_attribute("${category}_$trace_id",'Mbytes'); + my $file_name = $self->object_get_attribute("${category}_$trace_id",'file_name'); + my $init_weight = $self->object_get_attribute("${category}_$trace_id",'init_weight'); + my $min_pck_size = $self->object_get_attribute("${category}_$trace_id",'min_pck_size'); + my $max_pck_size = $self->object_get_attribute("${category}_$trace_id",'max_pck_size'); + my $burst_size = $self->object_get_attribute("${category}_$trace_id",'burst_size'); + my $injct_rate = $self->object_get_attribute("${category}_$trace_id",'injct_rate'); + my $injct_rate_var = $self->object_get_attribute("${category}_$trace_id",'injct_rate_var'); + my $src_port = $self->object_get_attribute("${category}_$trace_id",'scr_port'); + my $dst_port = $self->object_get_attribute("${category}_$trace_id",'dst_port'); + my $buff_size= $self->object_get_attribute("${category}_$trace_id",'buff_size'); + my $chanel = $self->object_get_attribute("${category}_$trace_id",'chanel'); + my $vc= $self->object_get_attribute("${category}_$trace_id",'vc'); + my $class= $self->object_get_attribute("${category}_$trace_id",'class'); + return ($source,$dest, $Mbytes, $file_id,$file_name,$init_weight,$min_pck_size, $max_pck_size, $burst_size, $injct_rate, $injct_rate_var, $src_port,$dst_port,$buff_size,$chanel,$vc,$class); } sub get_all_tasks{ - my ($self,$category)=@_; - my @traces= get_trace_list($self,$category); - my @x; - foreach my $p (@traces){ - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,$category,$p); - push(@x,$src); - push(@x,$dst); - } - my @x2 = uniq(sort @x) if (scalar @x); - return @x2; + my ($self,$category)=@_; + my @traces= get_trace_list($self,$category); + my @x; + foreach my $p (@traces){ + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,$category,$p); + push(@x,$src); + push(@x,$dst); + } + my @x2 = uniq(sort @x) if (scalar @x); + return @x2; } - sub remove_mapping{ - my $self=shift; - $self->object_add_attribute('MAP_TASK',undef,undef); - $self->object_add_attribute('mapping',undef,undef); - #$self->object_add_attribute('MAP_TILE',undef,undef); + my $self=shift; + $self->object_add_attribute('MAP_TASK',undef,undef); + $self->object_add_attribute('mapping',undef,undef); + #$self->object_add_attribute('MAP_TILE',undef,undef); } - - sub remove_nlock_mapping{ - my $self=shift; - my @tasks=get_all_merged_tasks($self); - - foreach my $p (@tasks){ - my $lock=$self->object_get_attribute("MAP_LOCK",$p); - $lock = 0 if (!defined $lock); - if($lock == 0){ - #my $tile=$self->object_get_attribute("MAP_TILE",$p); - my $tile=get_task_give_tile($self,$p); - #$self->object_add_attribute("MAP_TILE",$p,undef); - $self->object_add_attribute("MAP_TASK",$tile,undef); - $self->object_add_attribute("mapping",$tile,undef); - - - } - } + my $self=shift; + my @tasks=get_all_merged_tasks($self); + foreach my $p (@tasks){ + my $lock=$self->object_get_attribute("MAP_LOCK",$p); + $lock = 0 if (!defined $lock); + if($lock == 0){ + #my $tile=$self->object_get_attribute("MAP_TILE",$p); + my $tile=get_task_give_tile($self,$p); + #$self->object_add_attribute("MAP_TILE",$p,undef); + $self->object_add_attribute("MAP_TASK",$tile,undef); + $self->object_add_attribute("mapping",$tile,undef); + } + } } sub get_nlock_tasks { - #my ($self,$taskref,$tileref)=shift; - my $self=shift; - my @unluck_tasks; - my @tasks=get_all_merged_tasks($self); - - foreach my $p (@tasks){ - my $lock=$self->object_get_attribute("MAP_LOCK",$p); - $lock = 0 if (!defined $lock); - if($lock == 0){ - push(@unluck_tasks,$p); - } - - } - return @unluck_tasks; + #my ($self,$taskref,$tileref)=shift; + my $self=shift; + my @unluck_tasks; + my @tasks=get_all_merged_tasks($self); + foreach my $p (@tasks){ + my $lock=$self->object_get_attribute("MAP_LOCK",$p); + $lock = 0 if (!defined $lock); + if($lock == 0){ + push(@unluck_tasks,$p); + } + } + return @unluck_tasks; } sub get_nlock_tiles { - #my ($self,$taskref,$tileref)=shift; - my $self=shift; - my @luck_tiles; - my @tasks=get_all_merged_tasks($self); - - foreach my $task (@tasks){ - my $lock=$self->object_get_attribute("MAP_LOCK",$task); - $lock = 0 if (!defined $lock); - if($lock == 1){ - #my $tile=$self->object_get_attribute('MAP_TILE',"$task"); - my $tile=get_task_give_tile($self,"$task"); - push(@luck_tiles,$tile); - } - - } - my @tiles=get_tiles_name($self); - - #a-b - return get_diff_array(\@tiles,\@luck_tiles); + #my ($self,$taskref,$tileref)=shift; + my $self=shift; + my @luck_tiles; + my @tasks=get_all_merged_tasks($self); + foreach my $task (@tasks){ + my $lock=$self->object_get_attribute("MAP_LOCK",$task); + $lock = 0 if (!defined $lock); + if($lock == 1){ + #my $tile=$self->object_get_attribute('MAP_TILE',"$task"); + my $tile=get_task_give_tile($self,"$task"); + push(@luck_tiles,$tile); + } + } + my @tiles=get_tiles_name($self); + #a-b + return get_diff_array(\@tiles,\@luck_tiles); } sub get_locked_map { - my $self=shift; - my %map; - my @tasks=get_all_merged_tasks($self); - - foreach my $task (@tasks){ - my $lock=$self->object_get_attribute("MAP_LOCK",$task); - - $lock = 0 if (!defined $lock); - if($lock == 1){ - #my $tile=$self->object_get_attribute('MAP_TILE',"$task"); - my $tile=get_task_give_tile($self,"$task"); - $map{$task}=$tile; - } - - } - return %map; + my $self=shift; + my %map; + my @tasks=get_all_merged_tasks($self); + foreach my $task (@tasks){ + my $lock=$self->object_get_attribute("MAP_LOCK",$task); + $lock = 0 if (!defined $lock); + if($lock == 1){ + #my $tile=$self->object_get_attribute('MAP_TILE',"$task"); + my $tile=get_task_give_tile($self,"$task"); + $map{$task}=$tile; + } + } + return %map; } ######### -# Mapping algorithm +# Mapping algorithm ######### sub random_map{ - my $self=shift; - - - - my $nx=$self->object_get_attribute('noc_param','T1'); - my $ny=$self->object_get_attribute('noc_param','T2'); - my $nc= $nx * $ny; - - - - my @tasks=get_nlock_tasks($self); - my @tiles=get_nlock_tiles($self); - $self->remove_nlock_mapping() ; - - - my @rnd= shuffle @tiles; - - my $i=0; - foreach my $task (@tasks){ - if($i>=scalar @rnd){ - last; - }; - my $tile=$rnd[$i]; - #$self->object_add_attribute('MAP_TILE',"$task",$tile); - $self->object_add_attribute('MAP_TASK',"$tile",$task); - my @l=($task); - $self->object_add_attribute("mapping","$tile",\@l); - - $i++; - - } - - set_gui_status($self,"ref",1); - + my $self=shift; + my $nx=$self->object_get_attribute('noc_param','T1'); + my $ny=$self->object_get_attribute('noc_param','T2'); + my $nc= $nx * $ny; + my @tasks=get_nlock_tasks($self); + my @tiles=get_nlock_tiles($self); + $self->remove_nlock_mapping() ; + my @rnd= shuffle @tiles; + my $i=0; + foreach my $task (@tasks){ + if($i>=scalar @rnd){ + last; + }; + my $tile=$rnd[$i]; + #$self->object_add_attribute('MAP_TILE',"$task",$tile); + $self->object_add_attribute('MAP_TASK',"$tile",$task); + my @l=($task); + $self->object_add_attribute("mapping","$tile",\@l); + $i++; + } + set_gui_status($self,"ref",1); } sub direct_map { - my $self=shift; - - - my @tasks=get_nlock_tasks($self); - my @tiles=get_nlock_tiles($self); - $self->remove_nlock_mapping() ; - - my @sort_tiles; - my %tilenum; - foreach my $tile (@tiles){ - #my ($x,$y)=tile_id_to_loc($tile); - #my $id= $y*$nx+$x; - my $id=tile_id_number($tile); - $tilenum{$id}=$tile; - } - - foreach my $id (sort {$a <=> $b} keys %tilenum){ - - push(@sort_tiles, $tilenum{$id}); - } - - - my @sort_tasks = sort @tasks; - - - my $i=0; - foreach my $task (@sort_tasks){ - if($i>=scalar @sort_tiles){ - last; - }; - my $tile=$sort_tiles[$i]; - #$self->object_add_attribute('MAP_TILE',"$task",$tile); - $self->object_add_attribute('MAP_TASK',"$tile",$task); - my @l = ($task); - $self->object_add_attribute("mapping","$tile",\@l); - - $i++; - - } - - set_gui_status($self,"ref",1); - - + my $self=shift; + my @tasks=get_nlock_tasks($self); + my @tiles=get_nlock_tiles($self); + $self->remove_nlock_mapping() ; + my @sort_tiles; + my %tilenum; + foreach my $tile (@tiles){ + #my ($x,$y)=tile_id_to_loc($tile); + #my $id= $y*$nx+$x; + my $id=tile_id_number($tile); + $tilenum{$id}=$tile; + } + + foreach my $id (sort {$a <=> $b} keys %tilenum){ + + push(@sort_tiles, $tilenum{$id}); + } + + my @sort_tasks = sort @tasks; + my $i=0; + foreach my $task (@sort_tasks){ + if($i>=scalar @sort_tiles){ + last; + }; + my $tile=$sort_tiles[$i]; + #$self->object_add_attribute('MAP_TILE',"$task",$tile); + $self->object_add_attribute('MAP_TASK',"$tile",$task); + my @l = ($task); + $self->object_add_attribute("mapping","$tile",\@l); + $i++; + } + set_gui_status($self,"ref",1); } sub get_task_give_tile{ - my ($self,$task)=@_; - my @tiles=get_tiles_name($self); - foreach my $p (@tiles){ - my $r=$self->object_get_attribute("mapping","$p"); - - my @l=@{$r} if(defined $r); - if(defined $l[0] ){ - return $p if($l[0] eq $task ); - } - } - return undef; + my ($self,$task)=@_; + my @tiles=get_tiles_name($self); + foreach my $p (@tiles){ + my $r=$self->object_get_attribute("mapping","$p"); + my @l=@{$r} if(defined $r); + if(defined $l[0] ){ + return $p if($l[0] eq $task ); + } + } + return undef; } - sub network_3dim_cal{ - my $n_tasks= shift; - - my $dim_x = floor($n_tasks**(1/3)); - - my ($dim_y,$dim_z)=network_dim_cal(ceil($n_tasks/$dim_x)); - - - - return ($dim_x,$dim_y,$dim_z); - - -} - - - - + my $n_tasks= shift; + my $dim_x = floor($n_tasks**(1/3)); + my ($dim_y,$dim_z)=network_dim_cal(ceil($n_tasks/$dim_x)); + return ($dim_x,$dim_y,$dim_z); +} sub network_dim_cal{ - my $n_tasks= shift; - - my $dim_y = floor(sqrt($n_tasks)); - - my $dim_x = ceil($n_tasks/$dim_y); - - return ($dim_x,$dim_y); - - #cout << "dim_x = " << dim_x << "; dim_y = " << dim_y << endl; + my $n_tasks= shift; + my $dim_y = floor(sqrt($n_tasks)); + my $dim_x = ceil($n_tasks/$dim_y); + return ($dim_x,$dim_y); + #cout << "dim_x = " << dim_x << "; dim_y = " << dim_y << endl; } - sub get_tiles_name{ - my $self=shift; - my @tiles; + my $self=shift; + my @tiles; my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); #print " my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self)\n"; - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - push(@tiles,"tile($tile_num)"); - } - - return @tiles; + for (my $tile_num=0;$tile_num<$NE;$tile_num++){ + push(@tiles,"tile($tile_num)"); + } + return @tiles; } - sub tile_id_number{ - my $tile=shift; - my ($x) = $tile =~ /(\d+)/g; - return $x; + my $tile=shift; + my ($x) = $tile =~ /(\d+)/g; + return $x; } - - sub get_communication_task{ - my ($self,$category)=@_; - my %com_tasks; - my @tasks=get_all_merged_tasks($self); - my @traces= get_trace_list($self,'raw'); - - - - foreach my $p (@tasks){ - $com_tasks{$p}{'total'}= 0; - - foreach my $q (@tasks){ - $com_tasks{$p}{$q}= 0; - - } - } - - foreach my $p (@traces){ - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); - $src =$self->get_item_group_name('grouping',$src); - $dst =$self->get_item_group_name('grouping',$dst); - if ($src eq $dst){ - $com_tasks{$src}{'internal'} += $Mbytes; - - }else{ - - $com_tasks{$src}{'sent'} += $Mbytes; - $com_tasks{$dst}{'rsv'} += $Mbytes; - - $com_tasks{$src}{'total'} += $Mbytes; - $com_tasks{$dst}{'total'} += $Mbytes; - $com_tasks{$src}{$dst} += $Mbytes; - $com_tasks{$file_id}{'maxsent'} = $com_tasks{$src}{'sent'} if(!defined $com_tasks{$file_id}{'maxsent'}); - $com_tasks{$file_id}{'maxsent'} = $com_tasks{$src}{'sent'} if( $com_tasks{$file_id}{'maxsent'}<$com_tasks{$src}{'sent'}); - - - - my $minpck = $self->object_get_attribute("raw_$p",'min_pck_size'); - my $maxpck = $self->object_get_attribute("raw_$p",'max_pck_size'); - my $avg_pck_size =($minpck+ $maxpck)/2; - my $pck_num = ($Mbytes*8) /($avg_pck_size*64); - $pck_num= 1 if($pck_num==0); - $com_tasks{$src}{'min_pck_num'} =$pck_num if(!defined $com_tasks{$src}{'min_pck_num'}); - $com_tasks{$src}{'min_pck_num'} =$pck_num if( $com_tasks{$src}{'min_pck_num'} > $pck_num); - } - - } - return %com_tasks; -} + my ($self,$category)=@_; + my %com_tasks; + my @tasks=get_all_merged_tasks($self); + my @traces= get_trace_list($self,'raw'); + foreach my $p (@tasks){ + $com_tasks{$p}{'total'}= 0; + foreach my $q (@tasks){ + $com_tasks{$p}{$q}= 0; + } + } + + foreach my $p (@traces){ + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,'raw',$p); + $src =$self->get_item_group_name('grouping',$src); + $dst =$self->get_item_group_name('grouping',$dst); + if ($src eq $dst){ + $com_tasks{$src}{'internal'} += $Mbytes; + }else{ + $com_tasks{$src}{'sent'} += $Mbytes; + $com_tasks{$dst}{'rsv'} += $Mbytes; + $com_tasks{$src}{'total'} += $Mbytes; + $com_tasks{$dst}{'total'} += $Mbytes; + $com_tasks{$src}{$dst} += $Mbytes; + $com_tasks{$file_id}{'maxsent'} = $com_tasks{$src}{'sent'} if(!defined $com_tasks{$file_id}{'maxsent'}); + $com_tasks{$file_id}{'maxsent'} = $com_tasks{$src}{'sent'} if( $com_tasks{$file_id}{'maxsent'}<$com_tasks{$src}{'sent'}); + my $minpck = $self->object_get_attribute("raw_$p",'min_pck_size'); + my $maxpck = $self->object_get_attribute("raw_$p",'max_pck_size'); + my $avg_pck_size =($minpck+ $maxpck)/2; + my $pck_num = ($Mbytes*8) /($avg_pck_size*64); + $pck_num= 1 if($pck_num==0); + $com_tasks{$src}{'min_pck_num'} =$pck_num if(!defined $com_tasks{$src}{'min_pck_num'}); + $com_tasks{$src}{'min_pck_num'} =$pck_num if( $com_tasks{$src}{'min_pck_num'} > $pck_num); + } + } + return %com_tasks; +} sub find_max_neighbor_tile_old{ - my $self=shift; - #Select the tile located in center as the max-neighbor if its not locked for any other task - my ($NE,$NR) = get_topology_info($self); - - my $ne_mid = floor($NE/2); - print "$ne_mid = $ne_mid\n"; - - - #my $centered_tile= get_tile_name($self,$x_mid ,$y_mid); - #Select the tile located in center as the max-neighbor if its not locked for any other task - #therwise select the tile with the min manhatan distance to center tile - my @tiles=get_nlock_tiles($self); - my $min=1000000; - my $max_neighbors_tile_id; - foreach my $tile (@tiles){ - #my ($x,$y)=tile_id_to_loc($tile); - my $tile_num = tile_id_number($tile); - my $mah_distance=get_endpoints_mah_distance($self,$ne_mid,$tile_num); - - if($min > $mah_distance ){ - $min = $mah_distance; - $max_neighbors_tile_id=$tile; - } - - } - - return $max_neighbors_tile_id; -} - - -sub find_max_neighbor_tile{ - my $self=shift; - #Select the tile with the list manhatan distance from all endpoints - my ($NE,$NR) = get_topology_info($self); - my $min_manth_dist_acum; - my $max_neighbors_tile_id; - - for (my $i=0; $i<$NE; $i++){ - my $c=0; - for (my $j=0; $j<$NE; $j++){ - next if($i==$j); - my $d=get_endpoints_mah_distance($self,$i,$j); - $c+=$d*$d; - } - $min_manth_dist_acum=$c if(!defined $min_manth_dist_acum); - if($c <= $min_manth_dist_acum){ - $min_manth_dist_acum=$c; - $max_neighbors_tile_id="tile($i)"; - } - - } - - - return $max_neighbors_tile_id; -} - - - -sub find_min_neighbor_tile { - my $self=shift; - - my $ne_mid = 0; - - #my $centered_tile= get_tile_name($self,$x_mid ,$y_mid); - #Select the tile located in center as the max-neighbor if its not locked for any other task - #otherwise select the tile with the min Manhattan distance to center tile - my @tiles=get_nlock_tiles($self); - my $min=1000000; - my $min_neighbors_tile_id; - foreach my $tile (@tiles){ - #my ($x,$y)=tile_id_to_loc($tile); - my $tile_num = tile_id_number($tile); - my $mah_distance=get_endpoints_mah_distance($self,$ne_mid,$tile_num ); - if($min > $mah_distance ){ - $min = $mah_distance; - $min_neighbors_tile_id=$tile; - } - - } - - return $min_neighbors_tile_id; -} - + my $self=shift; + #Select the tile located in center as the max-neighbor if its not locked for any other task + my ($NE,$NR) = get_topology_info($self); + my $ne_mid = floor($NE/2); + print "$ne_mid = $ne_mid\n"; + #my $centered_tile= get_tile_name($self,$x_mid ,$y_mid); + #Select the tile located in center as the max-neighbor if its not locked for any other task + #therwise select the tile with the min manhatan distance to center tile + my @tiles=get_nlock_tiles($self); + my $min=1000000; + my $max_neighbors_tile_id; + foreach my $tile (@tiles){ + #my ($x,$y)=tile_id_to_loc($tile); + my $tile_num = tile_id_number($tile); + my $mah_distance=get_endpoints_mah_distance($self,$ne_mid,$tile_num); + if($min > $mah_distance ){ + $min = $mah_distance; + $max_neighbors_tile_id=$tile; + } + } + return $max_neighbors_tile_id; +} +sub find_max_neighbor_tile{ + my $self=shift; + #Select the tile with the list manhatan distance from all endpoints + my ($NE,$NR) = get_topology_info($self); + my $min_manth_dist_acum; + my $max_neighbors_tile_id; + for (my $i=0; $i<$NE; $i++){ + my $c=0; + for (my $j=0; $j<$NE; $j++){ + next if($i==$j); + my $d=get_endpoints_mah_distance($self,$i,$j); + $c+=$d*$d; + } + $min_manth_dist_acum=$c if(!defined $min_manth_dist_acum); + if($c <= $min_manth_dist_acum){ + $min_manth_dist_acum=$c; + $max_neighbors_tile_id="tile($i)"; + } + + } + return $max_neighbors_tile_id; +} + +sub find_min_neighbor_tile { + my $self=shift; + my $ne_mid = 0; + #my $centered_tile= get_tile_name($self,$x_mid ,$y_mid); + #Select the tile located in center as the max-neighbor if its not locked for any other task + #otherwise select the tile with the min Manhattan distance to center tile + my @tiles=get_nlock_tiles($self); + my $min=1000000; + my $min_neighbors_tile_id; + foreach my $tile (@tiles){ + #my ($x,$y)=tile_id_to_loc($tile); + my $tile_num = tile_id_number($tile); + my $mah_distance=get_endpoints_mah_distance($self,$ne_mid,$tile_num ); + if($min > $mah_distance ){ + $min = $mah_distance; + $min_neighbors_tile_id=$tile; + } + } + return $min_neighbors_tile_id; +} sub nmap_algorithm{ - my $self=shift; - my $nx=$self->object_get_attribute('noc_param','T1'); - my $ny=$self->object_get_attribute('noc_param','T2'); - my $nc= $nx * $ny; - - my @tasks=get_all_merged_tasks($self); - my @tiles= get_tiles_name($self); - my $n_tasks = scalar @tasks; - - - my @unmapped_tasks_set=@tasks; # unmapped set of tasks - my @unallocated_tiles_set=@tiles; # tile ids which are not allocated yet - -# print "@unmapped_tasks_set *** @unallocated_tiles_set\n"; - - - #------ step 1: find the task with highest weighted communication volume - # find the max of com_vol - # consider all incoming and outgoing connections of each tasks - - my %com_tasks= $self->get_communication_task('merge'); - #print Data::Dumper->Dump([\%com_tasks],['mpsoc']); - - my $max_com_task; - my $max_com =0; - foreach my $p (sort keys %com_tasks){ - #print "**$p\n"; - if(defined $com_tasks{$p}{'total'}){ - if ($com_tasks{$p}{'total'} >$max_com){ - $max_com = $com_tasks{$p}{'total'}; - $max_com_task = $p; - }} - } - - #print "m=$max_com t=$max_com_task\n"; - - - #------ step 2: find the tile with max number of neighbors - # normally, this tile is in the middle of the array - my $max_neighbors_tile_id = find_max_neighbor_tile($self); - - print "\$max_neighbors_tile_id = $max_neighbors_tile_id\n"; - - - - my %map=get_locked_map ($self); - $self->remove_nlock_mapping(); - foreach my $mapped_task (sort keys %map){ - my $mapped_tile=$map{$mapped_task}; - @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$mapped_task); - @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$mapped_tile); - } - - - - - # add this task with highest weighted communication volume to the mapped task set - #push(@mapped_tasks_set,$max_com_task); - #task_mapping[max_com_task] = max_neighbors_tile_id; - - if(!defined $map{$max_com_task}){ - $map{$max_com_task}=$max_neighbors_tile_id; - @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_task); - @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$max_neighbors_tile_id); - } - - - - #------ step 3: map all unmapped tasks - while(scalar @unmapped_tasks_set){ - $max_com =0; - my $max_com_unmapped_task; - my $max_overall_com=0; - #--------- step 3.1: - # find the unmapped task which communicates most with mapped_tasks_set - # among many tasks which have the same communication volume with mapped_tasks, - # choose the task with highest communication volume with others - - foreach my $unmapped_task (@unmapped_tasks_set){ - - my $com_vol=0; - foreach my $mapped_task (sort keys %map){ - $com_vol += $com_tasks{$unmapped_task}{$mapped_task}; - $com_vol += $com_tasks{$mapped_task}{$unmapped_task}; - } - - my $overall_com_vol = 0; - foreach my $p (@tasks){ - $overall_com_vol += $com_tasks{$unmapped_task}{$p}; - $overall_com_vol += $com_tasks{$p}{$unmapped_task}; - } - - - if ($com_vol > $max_com){ - $max_com = $com_vol; - $max_com_unmapped_task = $unmapped_task; - $max_overall_com = $overall_com_vol; - } - elsif ($com_vol == $max_com){ # choose if it have higher comm volume - if ($overall_com_vol > $max_overall_com){ - $max_com_unmapped_task = $unmapped_task; - $max_overall_com = $overall_com_vol; - } - } - }#foreach my $unmapped_task (@unmapped_tasks_set) - - #--------- step 3.2, find the unallocated tile with lowest communication cost to/from allocated_tile_set - my $min_com_cost; - my $min_com_cost_tile_id; - - - foreach my $unallocated_tile(@unallocated_tiles_set){ - my $com_cost = 0; - #my ($unallocated_x,$unallocated_y)=tile_id_to_loc($unallocated_tile); - my $unallocated_tile_num = tile_id_number($unallocated_tile); - # scan all mapped tasks - foreach my $mapped_task (sort keys %map){ - # get location of this mapped task - my $mapped_tile=$map{$mapped_task}; - #my ($allocated_x,$allocated_y)=tile_id_to_loc($mapped_tile); - my $mapped_tile_num = tile_id_number($mapped_tile); - # mahattan distance of 2 tiles - my $mah_distance=get_endpoints_mah_distance($self,$unallocated_tile_num,$mapped_tile_num); - - - $com_cost += $com_tasks{$max_com_unmapped_task}{$mapped_task} * $mah_distance; - $com_cost += $com_tasks{$mapped_task}{$max_com_unmapped_task} * $mah_distance; - - } - $min_com_cost = $com_cost+1 if(!defined $min_com_cost); - if ($com_cost < $min_com_cost){ - $min_com_cost = $com_cost; - $min_com_cost_tile_id = $unallocated_tile; - } - } - - # add max_com_unmapped_task to the mapped_tasks_set set - #task_mapping[max_com_unmapped_task] = min_com_cost_tile_id; - $map{$max_com_unmapped_task}=$min_com_cost_tile_id; - @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_unmapped_task); - @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$min_com_cost_tile_id); - - } - - - foreach my $mapped_task (sort keys %map){ - my $mapped_tile=$map{$mapped_task}; - #print "$mapped_tile=\$map{$mapped_task};\n"; - #$self->object_add_attribute('MAP_TILE',"$mapped_task", $mapped_tile) if(defined $mapped_tile); - $self->object_add_attribute('MAP_TASK',"$mapped_tile",$mapped_task) if(defined $mapped_tile); - my @l = ($mapped_task); - $self->object_add_attribute('mapping',"$mapped_tile",\@l) if(defined $mapped_tile); - #print "\$self->object_add_attribute('mapping',$mapped_tile,@l) if(defined $mapped_tile);\n"; - } - set_gui_status($self,"ref",1); - -} - - - - - - - + my $self=shift; + my $nx=$self->object_get_attribute('noc_param','T1'); + my $ny=$self->object_get_attribute('noc_param','T2'); + my $nc= $nx * $ny; + my @tasks=get_all_merged_tasks($self); + my @tiles= get_tiles_name($self); + my $n_tasks = scalar @tasks; + my @unmapped_tasks_set=@tasks; # unmapped set of tasks + my @unallocated_tiles_set=@tiles; # tile ids which are not allocated yet + # print "@unmapped_tasks_set *** @unallocated_tiles_set\n"; + #------ step 1: find the task with highest weighted communication volume + # find the max of com_vol + # consider all incoming and outgoing connections of each tasks + my %com_tasks= $self->get_communication_task('merge'); + #print Data::Dumper->Dump([\%com_tasks],['mpsoc']); + my $max_com_task; + my $max_com =0; + foreach my $p (sort keys %com_tasks){ + #print "**$p\n"; + if(defined $com_tasks{$p}{'total'}){ + if ($com_tasks{$p}{'total'} >$max_com){ + $max_com = $com_tasks{$p}{'total'}; + $max_com_task = $p; + }} + } + #print "m=$max_com t=$max_com_task\n"; + #------ step 2: find the tile with max number of neighbors + # normally, this tile is in the middle of the array + my $max_neighbors_tile_id = find_max_neighbor_tile($self); + print "\$max_neighbors_tile_id = $max_neighbors_tile_id\n"; + my %map=get_locked_map ($self); + $self->remove_nlock_mapping(); + foreach my $mapped_task (sort keys %map){ + my $mapped_tile=$map{$mapped_task}; + @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$mapped_task); + @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$mapped_tile); + } + # add this task with highest weighted communication volume to the mapped task set + #push(@mapped_tasks_set,$max_com_task); + #task_mapping[max_com_task] = max_neighbors_tile_id; + if(!defined $map{$max_com_task}){ + $map{$max_com_task}=$max_neighbors_tile_id; + @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_task); + @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$max_neighbors_tile_id); + } + #------ step 3: map all unmapped tasks + while(scalar @unmapped_tasks_set){ + $max_com =0; + my $max_com_unmapped_task; + my $max_overall_com=0; + #--------- step 3.1: + # find the unmapped task which communicates most with mapped_tasks_set + # among many tasks which have the same communication volume with mapped_tasks, + # choose the task with highest communication volume with others + foreach my $unmapped_task (@unmapped_tasks_set){ + my $com_vol=0; + foreach my $mapped_task (sort keys %map){ + $com_vol += $com_tasks{$unmapped_task}{$mapped_task}; + $com_vol += $com_tasks{$mapped_task}{$unmapped_task}; + } + my $overall_com_vol = 0; + foreach my $p (@tasks){ + $overall_com_vol += $com_tasks{$unmapped_task}{$p}; + $overall_com_vol += $com_tasks{$p}{$unmapped_task}; + } + if ($com_vol > $max_com){ + $max_com = $com_vol; + $max_com_unmapped_task = $unmapped_task; + $max_overall_com = $overall_com_vol; + } + elsif ($com_vol == $max_com){ # choose if it have higher comm volume + if ($overall_com_vol > $max_overall_com){ + $max_com_unmapped_task = $unmapped_task; + $max_overall_com = $overall_com_vol; + } + } + }#foreach my $unmapped_task (@unmapped_tasks_set) + #--------- step 3.2, find the unallocated tile with lowest communication cost to/from allocated_tile_set + my $min_com_cost; + my $min_com_cost_tile_id; + foreach my $unallocated_tile(@unallocated_tiles_set){ + my $com_cost = 0; + #my ($unallocated_x,$unallocated_y)=tile_id_to_loc($unallocated_tile); + my $unallocated_tile_num = tile_id_number($unallocated_tile); + # scan all mapped tasks + foreach my $mapped_task (sort keys %map){ + # get location of this mapped task + my $mapped_tile=$map{$mapped_task}; + #my ($allocated_x,$allocated_y)=tile_id_to_loc($mapped_tile); + my $mapped_tile_num = tile_id_number($mapped_tile); + # mahattan distance of 2 tiles + my $mah_distance=get_endpoints_mah_distance($self,$unallocated_tile_num,$mapped_tile_num); + $com_cost += $com_tasks{$max_com_unmapped_task}{$mapped_task} * $mah_distance; + $com_cost += $com_tasks{$mapped_task}{$max_com_unmapped_task} * $mah_distance; + + } + $min_com_cost = $com_cost+1 if(!defined $min_com_cost); + if ($com_cost < $min_com_cost){ + $min_com_cost = $com_cost; + $min_com_cost_tile_id = $unallocated_tile; + } + } + # add max_com_unmapped_task to the mapped_tasks_set set + #task_mapping[max_com_unmapped_task] = min_com_cost_tile_id; + $map{$max_com_unmapped_task}=$min_com_cost_tile_id; + @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_unmapped_task); + @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$min_com_cost_tile_id); + } + foreach my $mapped_task (sort keys %map){ + my $mapped_tile=$map{$mapped_task}; + #print "$mapped_tile=\$map{$mapped_task};\n"; + #$self->object_add_attribute('MAP_TILE',"$mapped_task", $mapped_tile) if(defined $mapped_tile); + $self->object_add_attribute('MAP_TASK',"$mapped_tile",$mapped_task) if(defined $mapped_tile); + my @l = ($mapped_task); + $self->object_add_attribute('mapping',"$mapped_tile",\@l) if(defined $mapped_tile); + #print "\$self->object_add_attribute('mapping',$mapped_tile,@l) if(defined $mapped_tile);\n"; + } + set_gui_status($self,"ref",1); +} sub worst_map_algorithm{ - - my $self=shift; - - - my $nx=$self->object_get_attribute('noc_param','T1'); - my $ny=$self->object_get_attribute('noc_param','T2'); - my $nc= $nx * $ny; - - my @tasks=get_all_merged_tasks($self); - my @tiles= get_tiles_name($self); - - my $n_tasks = scalar @tasks; - - - - - my @unmapped_tasks_set=@tasks; # unmapped set of tasks - my @unallocated_tiles_set=@tiles; # tile ids which are not allocated yet - - - - - #------ step 1: find the task with highest weighted communication volume - # find the max of com_vol - # consider all incoming and outgoing connections of each tasks - - my %com_tasks= $self->get_communication_task('merge'); - #print Data::Dumper->Dump([\%com_tasks],['mpsoc']); - - my $max_com_task; - my $max_com =0; - foreach my $p (sort keys %com_tasks){ - #print "$p\n"; - if(defined $com_tasks{$p}{'total'}){ - if ($com_tasks{$p}{'total'} >$max_com){ - $max_com = $com_tasks{$p}{'total'}; - $max_com_task = $p; - }} - } - - - - - #------ step 2: find the tile with min number of neighbors - # normally, this tile is in the corners - my $min_neighbors_tile_id = find_min_neighbor_tile($self); - - - - - my %map=get_locked_map ($self); - $self->remove_nlock_mapping(); - foreach my $mapped_task (sort keys %map){ - my $mapped_tile=$map{$mapped_task}; - @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$mapped_task); - @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$mapped_tile); - } - - - - - # add this task with highest weighted communication volume to the mapped task set - #push(@mapped_tasks_set,$max_com_task); - #task_mapping[max_com_task] = max_neighbors_tile_id; - - if(!defined $map{$max_com_task}){ - $map{$max_com_task}=$min_neighbors_tile_id; - @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_task); - @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$min_neighbors_tile_id); - } - - - - - - - - #------ step 3: map all unmapped tasks - while(scalar @unmapped_tasks_set){ - $max_com =0; - my $max_com_unmapped_task; - my $max_overall_com=0; - #--------- step 3.1: - # find the unmapped task which communicates most with mapped_tasks_set - # among many tasks which have the same communication volume with mapped_tasks, - # choose the task with highest communication volume with others - - foreach my $unmapped_task (@unmapped_tasks_set){ - - my $com_vol=0; - foreach my $mapped_task (sort keys %map){ - $com_vol += $com_tasks{$unmapped_task}{$mapped_task}; - $com_vol += $com_tasks{$mapped_task}{$unmapped_task}; - } - - my $overall_com_vol = 0; - foreach my $p (@tasks){ - $overall_com_vol += $com_tasks{$unmapped_task}{$p}; - $overall_com_vol += $com_tasks{$p}{$unmapped_task}; - } - - - if ($com_vol > $max_com){ - $max_com = $com_vol; - $max_com_unmapped_task = $unmapped_task; - $max_overall_com = $overall_com_vol; - } - elsif ($com_vol == $max_com){ # choose if it have higher comm volume - if ($overall_com_vol > $max_overall_com){ - $max_com_unmapped_task = $unmapped_task; - $max_overall_com = $overall_com_vol; - } - } - }#foreach my $unmapped_task (@unmapped_tasks_set) - - #--------- step 3.2, find the unallocated tile with highest communication cost to/from allocated_tile_set - my $max_com_cost; - my $max_com_cost_tile_id; - - - foreach my $unallocated_tile(@unallocated_tiles_set){ - my $com_cost = 0; - #my ($unallocated_x,$unallocated_y)=tile_id_to_loc($unallocated_tile); - my $unallocated_tile_num = tile_id_number($unallocated_tile); - # scan all mapped tasks - foreach my $mapped_task (sort keys %map){ - # get location of this mapped task - my $mapped_tile=$map{$mapped_task}; - #my ($allocated_x,$allocated_y)=tile_id_to_loc($mapped_tile); - my $mapped_tile_num = tile_id_number($mapped_tile); - # mahattan distance of 2 tiles - my $mah_distance=get_endpoints_mah_distance($self,$unallocated_tile_num,$mapped_tile_num); - - $com_cost += $com_tasks{$max_com_unmapped_task}{$mapped_task} * $mah_distance; - $com_cost += $com_tasks{$mapped_task}{$max_com_unmapped_task} * $mah_distance; - - } - $max_com_cost = $com_cost-1 if(!defined $max_com_cost); - if ($com_cost > $max_com_cost){ - $max_com_cost = $com_cost; - $max_com_cost_tile_id = $unallocated_tile; - } - } - - # add max_com_unmapped_task to the mapped_tasks_set set - #task_mapping[max_com_unmapped_task] = min_com_cost_tile_id; - $map{$max_com_unmapped_task}=$max_com_cost_tile_id; - @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_unmapped_task); - @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$max_com_cost_tile_id); - - } - - - foreach my $mapped_task (sort keys %map){ - my $mapped_tile=$map{$mapped_task}; - #print "$mapped_tile=\$map{$mapped_task};\n"; - #$self->object_add_attribute('MAP_TILE',"$mapped_task", $mapped_tile) if(defined $mapped_tile); - - $self->object_add_attribute('MAP_TASK',"$mapped_tile",$mapped_task) if(defined $mapped_tile); - my @l=($mapped_task); - $self->object_add_attribute("mapping","$mapped_tile",\@l) if(defined $mapped_tile); - #print "$self->object_add_attribute(\"mapping\",\"$mapped_tile\",$mapped_task);\n"; - } - set_gui_status($self,"ref",1); - -} - - - - + my $self=shift; + my $nx=$self->object_get_attribute('noc_param','T1'); + my $ny=$self->object_get_attribute('noc_param','T2'); + my $nc= $nx * $ny; + my @tasks=get_all_merged_tasks($self); + my @tiles= get_tiles_name($self); + my $n_tasks = scalar @tasks; + my @unmapped_tasks_set=@tasks; # unmapped set of tasks + my @unallocated_tiles_set=@tiles; # tile ids which are not allocated yet + #------ step 1: find the task with highest weighted communication volume + # find the max of com_vol + # consider all incoming and outgoing connections of each tasks + my %com_tasks= $self->get_communication_task('merge'); + #print Data::Dumper->Dump([\%com_tasks],['mpsoc']); + my $max_com_task; + my $max_com =0; + foreach my $p (sort keys %com_tasks){ + #print "$p\n"; + if(defined $com_tasks{$p}{'total'}){ + if ($com_tasks{$p}{'total'} >$max_com){ + $max_com = $com_tasks{$p}{'total'}; + $max_com_task = $p; + }} + } + #------ step 2: find the tile with min number of neighbors + # normally, this tile is in the corners + my $min_neighbors_tile_id = find_min_neighbor_tile($self); + my %map=get_locked_map ($self); + $self->remove_nlock_mapping(); + foreach my $mapped_task (sort keys %map){ + my $mapped_tile=$map{$mapped_task}; + @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$mapped_task); + @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$mapped_tile); + } + # add this task with highest weighted communication volume to the mapped task set + #push(@mapped_tasks_set,$max_com_task); + #task_mapping[max_com_task] = max_neighbors_tile_id; + if(!defined $map{$max_com_task}){ + $map{$max_com_task}=$min_neighbors_tile_id; + @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_task); + @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$min_neighbors_tile_id); + } + #------ step 3: map all unmapped tasks + while(scalar @unmapped_tasks_set){ + $max_com =0; + my $max_com_unmapped_task; + my $max_overall_com=0; + #--------- step 3.1: + # find the unmapped task which communicates most with mapped_tasks_set + # among many tasks which have the same communication volume with mapped_tasks, + # choose the task with highest communication volume with others + foreach my $unmapped_task (@unmapped_tasks_set){ + my $com_vol=0; + foreach my $mapped_task (sort keys %map){ + $com_vol += $com_tasks{$unmapped_task}{$mapped_task}; + $com_vol += $com_tasks{$mapped_task}{$unmapped_task}; + } + my $overall_com_vol = 0; + foreach my $p (@tasks){ + $overall_com_vol += $com_tasks{$unmapped_task}{$p}; + $overall_com_vol += $com_tasks{$p}{$unmapped_task}; + } + if ($com_vol > $max_com){ + $max_com = $com_vol; + $max_com_unmapped_task = $unmapped_task; + $max_overall_com = $overall_com_vol; + } + elsif ($com_vol == $max_com){ # choose if it have higher comm volume + if ($overall_com_vol > $max_overall_com){ + $max_com_unmapped_task = $unmapped_task; + $max_overall_com = $overall_com_vol; + } + } + }#foreach my $unmapped_task (@unmapped_tasks_set) + #--------- step 3.2, find the unallocated tile with highest communication cost to/from allocated_tile_set + my $max_com_cost; + my $max_com_cost_tile_id; + foreach my $unallocated_tile(@unallocated_tiles_set){ + my $com_cost = 0; + #my ($unallocated_x,$unallocated_y)=tile_id_to_loc($unallocated_tile); + my $unallocated_tile_num = tile_id_number($unallocated_tile); + # scan all mapped tasks + foreach my $mapped_task (sort keys %map){ + # get location of this mapped task + my $mapped_tile=$map{$mapped_task}; + #my ($allocated_x,$allocated_y)=tile_id_to_loc($mapped_tile); + my $mapped_tile_num = tile_id_number($mapped_tile); + # mahattan distance of 2 tiles + my $mah_distance=get_endpoints_mah_distance($self,$unallocated_tile_num,$mapped_tile_num); + $com_cost += $com_tasks{$max_com_unmapped_task}{$mapped_task} * $mah_distance; + $com_cost += $com_tasks{$mapped_task}{$max_com_unmapped_task} * $mah_distance; + } + $max_com_cost = $com_cost-1 if(!defined $max_com_cost); + if ($com_cost > $max_com_cost){ + $max_com_cost = $com_cost; + $max_com_cost_tile_id = $unallocated_tile; + } + } + # add max_com_unmapped_task to the mapped_tasks_set set + #task_mapping[max_com_unmapped_task] = min_com_cost_tile_id; + $map{$max_com_unmapped_task}=$max_com_cost_tile_id; + @unmapped_tasks_set=remove_scolar_from_array(\@unmapped_tasks_set,$max_com_unmapped_task); + @unallocated_tiles_set=remove_scolar_from_array(\@unallocated_tiles_set,$max_com_cost_tile_id); + } + foreach my $mapped_task (sort keys %map){ + my $mapped_tile=$map{$mapped_task}; + #print "$mapped_tile=\$map{$mapped_task};\n"; + #$self->object_add_attribute('MAP_TILE',"$mapped_task", $mapped_tile) if(defined $mapped_tile); + $self->object_add_attribute('MAP_TASK',"$mapped_tile",$mapped_task) if(defined $mapped_tile); + my @l=($mapped_task); + $self->object_add_attribute("mapping","$mapped_tile",\@l) if(defined $mapped_tile); + #print "$self->object_add_attribute(\"mapping\",\"$mapped_tile\",$mapped_task);\n"; + } + set_gui_status($self,"ref",1); +} sub get_task_assigned_to_tile { - my ($self,$i)=@_; - #my $p= $self->object_get_attribute("MAP_TASK","tile($i)"); - my $r=$self->object_get_attribute("mapping","tile($i)"); - return undef if(!defined $r); - my @l=@{$r}; - return $l[0]; + my ($self,$i)=@_; + #my $p= $self->object_get_attribute("MAP_TASK","tile($i)"); + my $r=$self->object_get_attribute("mapping","tile($i)"); + return undef if(!defined $r); + my @l=@{$r}; + return $l[0]; } - - sub get_assigned_tiles{ - my $self=shift; - my @assigned_tiles; - my @tiles=get_tiles_name($self); - foreach my $p (@tiles){ - my @l=@{$self->object_get_attribute("mapping","$p")}; - push(@assigned_tiles,$p)if(defined $l[0] ); - } - #my @assigned_tiles = sort keys %{$self->{'MAP_TASK'}}; - return @assigned_tiles; + my $self=shift; + my @assigned_tiles; + my @tiles=get_tiles_name($self); + foreach my $p (@tiles){ + my @l=@{$self->object_get_attribute("mapping","$p")}; + push(@assigned_tiles,$p)if(defined $l[0] ); + } + #my @assigned_tiles = sort keys %{$self->{'MAP_TASK'}}; + return @assigned_tiles; } sub map_task { - my ($self,$task,$tile)=@_; - #my $oldtile= $self->{"MAP_TILE"}{$task}; - my $oldtile=get_task_give_tile($self,$task); - if($tile eq "-"){ - #delete $self->{"MAP_TILE"}{$task}; - }else{ - #$self->{"MAP_TILE"}{$task}= $tile; - $self->{'MAP_TASK'}{$tile}= $task; - my @l=($task); - $self->object_add_attribute("mapping","$tile",\@l); - } - delete $self->{"MAP_TASK"}{$oldtile} if(defined $oldtile); - $self->object_add_attribute("mapping",$oldtile,undef) if(defined $oldtile); + my ($self,$task,$tile)=@_; + #my $oldtile= $self->{"MAP_TILE"}{$task}; + my $oldtile=get_task_give_tile($self,$task); + if($tile eq "-"){ + #delete $self->{"MAP_TILE"}{$task}; + }else{ + #$self->{"MAP_TILE"}{$task}= $tile; + $self->{'MAP_TASK'}{$tile}= $task; + my @l=($task); + $self->object_add_attribute("mapping","$tile",\@l); + } + delete $self->{"MAP_TASK"}{$oldtile} if(defined $oldtile); + $self->object_add_attribute("mapping",$oldtile,undef) if(defined $oldtile); } sub remove_selected_traces{ - my ($self,$category)=@_; - my @traces= get_trace_list($self,$category); - foreach my $p (@traces) { - my $select=$self->object_get_attribute("${category}_$p",'selected', 0); - - if($select){ - $self->remove_trace($category,"$p"); - - } - } - set_gui_status($self,"ref",1); + my ($self,$category)=@_; + my @traces= get_trace_list($self,$category); + foreach my $p (@traces) { + my $select=$self->object_get_attribute("${category}_$p",'selected', 0); + if($select){ + $self->remove_trace($category,"$p"); + } + } + set_gui_status($self,"ref",1); } - - sub auto_generate_injtratio{ - my ($self,$category)=@_; - my %com_tasks= $self->get_communication_task($category); - my @traces= get_trace_list($self,'raw'); - foreach my $p (@traces) { - my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,$category,$p); - my $max= $com_tasks{$file_id}{'maxsent'}; - my $sent= $com_tasks{$src}{'sent'}; - my $ratio = ($sent*100)/$max; - $self->object_add_attribute("raw_$p",'injct_rate',$ratio); - - my $minpck = $self->object_get_attribute("raw_$p",'min_pck_size'); - my $maxpck = $self->object_get_attribute("raw_$p",'max_pck_size' ); - my $avg_pck_size =($minpck+ $maxpck)/2; - my $pck_num = ($Mbytes*8) /($avg_pck_size*64); - - - my $burst =$pck_num/ $com_tasks{$src}{'min_pck_num'} ; - $self->object_add_attribute("raw_$p",'burst_size',ceil($burst)); - - #my $burst_size = gen_spin_object ($self,"raw_$p",'burst_size',"1,1024,1", 1,undef,undef); - - - - } - set_gui_status($self,"ref",1); - - + my ($self,$category)=@_; + my %com_tasks= $self->get_communication_task($category); + my @traces= get_trace_list($self,'raw'); + foreach my $p (@traces) { + my ($src,$dst, $Mbytes, $file_id, $file_name)=get_trace($self,$category,$p); + my $max= $com_tasks{$file_id}{'maxsent'}; + my $sent= $com_tasks{$src}{'sent'}; + my $ratio = ($sent*100)/$max; + $self->object_add_attribute("raw_$p",'injct_rate',$ratio); + my $minpck = $self->object_get_attribute("raw_$p",'min_pck_size'); + my $maxpck = $self->object_get_attribute("raw_$p",'max_pck_size' ); + my $avg_pck_size =($minpck+ $maxpck)/2; + my $pck_num = ($Mbytes*8) /($avg_pck_size*64); + my $burst =$pck_num/ $com_tasks{$src}{'min_pck_num'} ; + $self->object_add_attribute("raw_$p",'burst_size',ceil($burst)); + #my $burst_size = gen_spin_object ($self,"raw_$p",'burst_size',"1,1024,1", 1,undef,undef); + } + set_gui_status($self,"ref",1); } sub trace_merger{ - my ($self,$tview,$mode)=@_; - my $table= def_table(2,10,FALSE); - my $row=0; - my $col=0; - - my $m= ($mode eq 'task')? "Task" :"Actor"; - - - my $label = gen_label_in_center(' '); - $label->set_markup ("Group ${m}s "); - $table->attach ($label,$col, $col+5, $row, $row+1,'shrink','shrink',2,2);$col+=5; - my ($Ebox,$entry)=def_h_labeled_entry ("New group name:",undef); - $table->attach ($Ebox,$col, $col+4, $row, $row+1,'shrink','shrink',2,2);$col+=5; - my $add=def_image_button('icons/plus.png'); - $table->attach ($add,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col+=1; - - $row++; - $col=0; - - #my @info = ( - #{ label=>'Number of Group', param_name=>'GROUP_NUM', type=>"Spin-button", default_val=>1, content=>"1,1000,1", info=>"Several ${m}s can be grouped and mapped on the same tile. Define the number of groups which ${m} can be categorized to.", param_parent=>'noc_param', ref_delay=>1,placement=>'vertical'} - #); - - #foreach my $d (@info) { - # ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},'ref',$d->{placement}); - #} - - - return add_widget_to_scrolled_win($table); - + my ($self,$tview,$mode)=@_; + my $table= def_table(2,10,FALSE); + my $row=0; + my $col=0; + my $m= ($mode eq 'task')? "Task" :"Actor"; + my $label = gen_label_in_center(' '); + $label->set_markup ("Group ${m}s "); + $table->attach ($label,$col, $col+5, $row, $row+1,'shrink','shrink',2,2);$col+=5; + my ($Ebox,$entry)=def_h_labeled_entry ("New group name:",undef); + $table->attach ($Ebox,$col, $col+4, $row, $row+1,'shrink','shrink',2,2);$col+=5; + my $add=def_image_button('icons/plus.png'); + $table->attach ($add,$col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col+=1; + $row++; + $col=0; + #my @info = ( + #{ label=>'Number of Group', param_name=>'GROUP_NUM', type=>"Spin-button", default_val=>1, content=>"1,1000,1", info=>"Several ${m}s can be grouped and mapped on the same tile. Define the number of groups which ${m} can be categorized to.", param_parent=>'noc_param', ref_delay=>1,placement=>'vertical'} + #); + #foreach my $d (@info) { + # ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},'ref',$d->{placement}); + #} + return add_widget_to_scrolled_win($table); } - - - sub select_trace_file { - my ($self,$tview,$mode)=@_; - my $traces=trace_pad($self,$tview,$mode); - my $traces_ctrl=trace_pad_ctrl($self,$tview,$mode); - my $h=gen_hpaned_adj($self,$traces_ctrl,.20,$traces,'trace-hpan'); - return $h; + my ($self,$tview,$mode)=@_; + my $traces=trace_pad($self,$tview,$mode); + my $traces_ctrl=trace_pad_ctrl($self,$tview,$mode); + my $h=gen_hpaned_adj($self,$traces_ctrl,.20,$traces,'trace-hpan'); + return $h; } - sub trace_maker_notebook{ - my ($self,$mode,$tview)=@_; - my $notebook = gen_notebook(); - my $lb= ($mode eq 'orcc')? 'Actor' : 'Trace'; - my $group_num=16; - - - $notebook->set_tab_pos ('left'); - $notebook->set_scrollable(TRUE); - - my $page1=select_trace_file($self,$tview,$mode); - $notebook->append_page ($page1,gen_label_in_center ("1-Select $mode file")); - - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - - #group tasks - $self->object_add_attribute('grouping','group_name_root','group'); - $self->object_add_attribute('grouping','group_name_editble','YES'); - $self->object_add_attribute('grouping','trace_icon','icons/cd.png'); - $self->object_add_attribute('grouping','group_num',$NE); - $self->object_add_attribute('grouping','map_limit',1024); - $self->object_add_attribute('grouping','lable',"${lb}s: Drag and drop ${lb}s to bottom group list"); - my $group_ctrl =gen_group_ctrl_box($self,$tview,$mode); - - my @tasks=get_all_tasks($self,'raw'); - my $page2=drag_and_drop_page($self,$tview,'grouping',\@tasks,$group_ctrl); - $notebook->append_page ($page2,gen_label_in_center ("2-Group ${lb}s ")); - - #map tasks - $self->object_add_attribute('mapping','group_name_root','tile'); - $self->object_add_attribute('mapping','group_name_editble','NO'); - $self->object_add_attribute('mapping','trace_icon','icons/cd2.png'); - $self->object_add_attribute('mapping','lable',"${lb}s: Drag and drop ${lb}s/grouped ${lb}s to bottom tile list"); - $self->object_add_attribute('mapping','map_limit',1); - $self->object_add_attribute('mapping','group_num',$NE); - - #get list of non-empty groups - my @merged_tasks=get_all_merged_tasks($self); - my $map_ctrl =gen_mapping_ctrl_box($self,$tview,$mode); - - # check task names to be uniq - my @r= return_not_unique_names_in_array(@merged_tasks); + my ($self,$mode,$tview)=@_; + my $notebook = gen_notebook(); + my $lb= ($mode eq 'orcc')? 'Actor' : 'Trace'; + my $group_num=16; + $notebook->set_tab_pos ('left'); + $notebook->set_scrollable(TRUE); + my $page1=select_trace_file($self,$tview,$mode); + $notebook->append_page ($page1,gen_label_in_center ("1-Select $mode file")); + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); + #group tasks + $self->object_add_attribute('grouping','group_name_root','group'); + $self->object_add_attribute('grouping','group_name_editble','YES'); + $self->object_add_attribute('grouping','trace_icon','icons/cd.png'); + $self->object_add_attribute('grouping','group_num',$NE); + $self->object_add_attribute('grouping','map_limit',1024); + $self->object_add_attribute('grouping','lable',"${lb}s: Drag and drop ${lb}s to bottom group list"); + my $group_ctrl =gen_group_ctrl_box($self,$tview,$mode); + my @tasks=get_all_tasks($self,'raw'); + my $page2=drag_and_drop_page($self,$tview,'grouping',\@tasks,$group_ctrl); + $notebook->append_page ($page2,gen_label_in_center ("2-Group ${lb}s ")); + #map tasks + $self->object_add_attribute('mapping','group_name_root','tile'); + $self->object_add_attribute('mapping','group_name_editble','NO'); + $self->object_add_attribute('mapping','trace_icon','icons/cd2.png'); + $self->object_add_attribute('mapping','lable',"${lb}s: Drag and drop ${lb}s/grouped ${lb}s to bottom tile list"); + $self->object_add_attribute('mapping','map_limit',1); + $self->object_add_attribute('mapping','group_num',$NE); + #get list of non-empty groups + my @merged_tasks=get_all_merged_tasks($self); + my $map_ctrl =gen_mapping_ctrl_box($self,$tview,$mode); + # check task names to be uniq + my @r= return_not_unique_names_in_array(@merged_tasks); foreach my $p (@r){ - add_colored_info($tview,"$lb name $p is not unique!\n",'red'); + add_colored_info($tview,"$lb name $p is not unique!\n",'red'); } - - - my $page3=drag_and_drop_page($self,$tview,'mapping',\@merged_tasks,$map_ctrl); - $notebook->append_page ($page3,gen_label_in_center ("3-Map ${lb}s")); - - - - - #my $page4=routing_page($self,$tview); - #$notebook->append_page ($page4,gen_label_in_center ("Route Selection")); - - - - $notebook->show_all; - - my $first=1; - my $page_num=$self->object_get_attribute ("process_notebook","currentpage"); - $notebook->set_current_page ($page_num) if(defined $page_num); - $notebook->signal_connect( 'switch-page'=> sub{ - $self->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber - }); - $notebook->signal_connect("switch-page" => sub{ - if(!$first){ - - set_gui_status($self,"ref",1); - }else { - set_gui_status($self,"ref",1); - } - $first=0; - }); - - return $notebook; - + my $page3=drag_and_drop_page($self,$tview,'mapping',\@merged_tasks,$map_ctrl); + $notebook->append_page ($page3,gen_label_in_center ("3-Map ${lb}s")); + #my $page4=routing_page($self,$tview); + #$notebook->append_page ($page4,gen_label_in_center ("Route Selection")); + $notebook->show_all; + my $first=1; + my $page_num=$self->object_get_attribute ("process_notebook","currentpage"); + $notebook->set_current_page ($page_num) if(defined $page_num); + $notebook->signal_connect( 'switch-page'=> sub{ + $self->object_add_attribute ("process_notebook","currentpage",$_[2]); #save the new pagenumber + }); + $notebook->signal_connect("switch-page" => sub{ + if(!$first){ + set_gui_status($self,"ref",1); + }else { + set_gui_status($self,"ref",1); + } + $first=0; + }); + return $notebook; } sub get_all_merged_tasks { - my($self)=@_; - my @merged; - my $group_num=$self->object_get_attribute('mapping','group_num'); - $group_num = 0 if(!defined $group_num); - for(my $i=0;$i<$group_num;$i=$i+1){ - my $gref = $self->object_get_attribute('grouping',"group($i)"); - next if(! defined $gref); - next if (scalar @{$gref} == 0); - - my $label = $self->object_get_attribute('grouping',"group($i)"."_name"); - $label = "group($i)" if(!defined $label); - push (@merged,"$label"); - } - my $uref= $self->object_get_attribute('grouping','ungrouped'); - push (@merged, @{$uref}) if(defined $uref); - return @merged; + my($self)=@_; + my @merged; + my $group_num=$self->object_get_attribute('mapping','group_num'); + $group_num = 0 if(!defined $group_num); + for(my $i=0;$i<$group_num;$i=$i+1){ + my $gref = $self->object_get_attribute('grouping',"group($i)"); + next if(! defined $gref); + next if (scalar @{$gref} == 0); + + my $label = $self->object_get_attribute('grouping',"group($i)"."_name"); + $label = "group($i)" if(!defined $label); + push (@merged,"$label"); + } + my $uref= $self->object_get_attribute('grouping','ungrouped'); + push (@merged, @{$uref}) if(defined $uref); + return @merged; } - - sub gen_mapping_ctrl_box{ - my ($self,$tview,$mode)=@_; - my $map_ctrl= trace_map_ctrl($self,$tview,$mode); - my $map_info=map_info($self); - my $v_paned=gen_vpaned($map_ctrl,.4,$map_info); - return $v_paned; + my ($self,$tview,$mode)=@_; + my $map_ctrl= trace_map_ctrl($self,$tview,$mode); + my $map_info=map_info($self); + my $v_paned=gen_vpaned($map_ctrl,.4,$map_info); + return $v_paned; } sub gen_group_ctrl_box{ - my ($self,$tview,$mode)=@_; - my $group_ctrl= trace_group_ctrl($self,$tview,$mode); - #my $map_info=map_info($self); - #my $v_paned=gen_vpaned($map_ctrl,.5,$map_info); - #return $v_paned; - - my $group_info = group_info ($self,$tview,$mode); - my $v_paned=gen_vpaned($group_ctrl,0.2,$group_info); - return $v_paned; - - #return $group_ctrl; + my ($self,$tview,$mode)=@_; + my $group_ctrl= trace_group_ctrl($self,$tview,$mode); + #my $map_info=map_info($self); + #my $v_paned=gen_vpaned($map_ctrl,.5,$map_info); + #return $v_paned; + my $group_info = group_info ($self,$tview,$mode); + my $v_paned=gen_vpaned($group_ctrl,0.2,$group_info); + return $v_paned; + #return $group_ctrl; } - - - - sub build_trace_gui { - my ($self,$mode,$ref,$w) = @_; - set_gui_status($self,"ideal",0); - $self->object_add_attribute ("process_notebook","currentpage",0); - if($mode eq 'task'){ - $self->object_add_attribute('noc_param','T1',2); - $self->object_add_attribute('noc_param','T2',2); - $self->object_add_attribute('noc_param','T3',1); - $self->object_add_attribute('noc_param','Fpay',32); - $self->object_add_attribute('noc_param','V',1); - $self->object_add_attribute('noc_param','C',1); - $self->object_add_attribute('noc_param','TOPOLOGY','"MESH"'); - } - - $self->object_add_attribute("file_id",undef,'a'); - $self->object_add_attribute("trace_id",undef,0); - $self->object_add_attribute('select_multiple','action',"_"); - $self->object_add_attribute('Auto','Auto_inject',"1\'b1"); - if(defined $ref){ - # add noc parameters - my %params=%{$ref}; - foreach my $p (sort keys %params){ - $self->{$p}=$params{$p}; - - } - - } - - - my ($scwin_info,$tview)= create_txview(); - my $notebook = trace_maker_notebook($self,$mode,$tview); - my $tt = ($mode eq 'task') ? 0.65 : 0.55; - - my $v2=gen_vpaned($notebook,$tt,$scwin_info); - - - - - - - - - set_gui_status($self,"ideal",0); - - my $main_table= def_table(2,10,FALSE); - - - - - my $generate = def_image_button('icons/gen.png','Generate'); - my $open = def_image_button('icons/browse.png','Load'); - my ($entrybox,$entry) = def_h_labeled_entry('Save as:',undef); - $entry->signal_connect( 'changed'=> sub{ - my $name=$entry->get_text(); - $self->object_add_attribute ("save_as",undef,$name); - }); - - my $entry2=gen_entry_object($self,'out_name',undef,undef,undef,undef); - my $entrybox2=gen_label_info(" Output file name:",$entry2); - - my $save = def_image_button('icons/save.png','Save'); - $entrybox->pack_end($save, FALSE, FALSE,0); - - $main_table->attach_defaults ($v2 , 0, 12, 0,24); - $main_table->attach ($open,0, 3, 24,25,'expand','shrink',2,2); - $main_table->attach ($entrybox,3, 5, 24,25,'expand','shrink',2,2); - $main_table->attach ($entrybox2,5,6 , 24,25,'expand','shrink',2,2) if ($mode eq 'task'); - $main_table->attach ($generate, 6, 9, 24,25,'expand','shrink',2,2); - - - my $sc_win =add_widget_to_scrolled_win($main_table); - - - - $open-> signal_connect("clicked" => sub{ - - load_workspace($self); - set_gui_status($self,"ref",5); - - }); - - $save-> signal_connect("clicked" => sub{ - save_as($self); - set_gui_status($self,"ref",5); - - - }); - - $generate->signal_connect("clicked" => sub{ - genereate_output_tasks($self) if ($mode eq 'task'); - genereate_output_orcc ($self,$tview,$w) if ($mode eq 'orcc'); - - }); - - - - - - - #check soc status every 0.5 second. refresh device table if there is any changes - Glib::Timeout->add (100, sub{ - - my ($state,$timeout)= get_gui_status($self); - - if ($timeout>0){ - $timeout--; - set_gui_status($self,$state,$timeout); - return TRUE; - - } - if($state eq "ideal"){ - return TRUE; - - } - - - - #refresh GUI - my $saved_name=$self->object_get_attribute('save_as'); - if(defined $saved_name) {$entry->set_text($saved_name);} - - $saved_name=$self->object_get_attribute('out_name'); - if(defined $saved_name) {$entry2->set_text($saved_name);} - - - $notebook->destroy; - $notebook = trace_maker_notebook($self,$mode,$tview); - $v2 -> pack1($notebook, TRUE, TRUE); - - set_gui_status($self,"ideal",0); - - return TRUE; - - } ); - - return $sc_win; - -} - - - + my ($self,$mode,$ref,$w) = @_; + set_gui_status($self,"ideal",0); + $self->object_add_attribute ("process_notebook","currentpage",0); + if($mode eq 'task'){ + $self->object_add_attribute('noc_param','T1',2); + $self->object_add_attribute('noc_param','T2',2); + $self->object_add_attribute('noc_param','T3',1); + $self->object_add_attribute('noc_param','Fpay',32); + $self->object_add_attribute('noc_param','V',1); + $self->object_add_attribute('noc_param','C',1); + $self->object_add_attribute('noc_param','TOPOLOGY','"MESH"'); + } + $self->object_add_attribute("file_id",undef,'a'); + $self->object_add_attribute("trace_id",undef,0); + $self->object_add_attribute('select_multiple','action',"_"); + $self->object_add_attribute('Auto','Auto_inject',"1\'b1"); + if(defined $ref){ + # add noc parameters + my %params=%{$ref}; + foreach my $p (sort keys %params){ + $self->{$p}=$params{$p}; + } + } + my ($scwin_info,$tview)= create_txview(); + my $notebook = trace_maker_notebook($self,$mode,$tview); + my $tt = ($mode eq 'task') ? 0.65 : 0.55; + my $v2=gen_vpaned($notebook,$tt,$scwin_info); + set_gui_status($self,"ideal",0); + my $main_table= def_table(2,10,FALSE); + my $generate = def_image_button('icons/gen.png','Generate'); + my $open = def_image_button('icons/browse.png','Load'); + my ($entrybox,$entry) = def_h_labeled_entry('Save as:',undef); + $entry->signal_connect( 'changed'=> sub{ + my $name=$entry->get_text(); + $self->object_add_attribute ("save_as",undef,$name); + }); + my $entry2=gen_entry_object($self,'out_name',undef,undef,undef,undef); + my $entrybox2=gen_label_info(" Output file name:",$entry2); + my $save = def_image_button('icons/save.png','Save'); + $entrybox->pack_end($save, FALSE, FALSE,0); + $main_table->attach_defaults ($v2 , 0, 12, 0,24); + $main_table->attach ($open,0, 3, 24,25,'expand','shrink',2,2); + $main_table->attach ($entrybox,3, 5, 24,25,'expand','shrink',2,2); + $main_table->attach ($entrybox2,5,6 , 24,25,'expand','shrink',2,2) if ($mode eq 'task'); + $main_table->attach ($generate, 6, 9, 24,25,'expand','shrink',2,2); + my $sc_win =add_widget_to_scrolled_win($main_table); + $open-> signal_connect("clicked" => sub{ + load_workspace($self); + set_gui_status($self,"ref",5); + }); + $save-> signal_connect("clicked" => sub{ + save_as($self); + set_gui_status($self,"ref",5); + }); + $generate->signal_connect("clicked" => sub{ + genereate_output_tasks($self) if ($mode eq 'task'); + genereate_output_orcc ($self,$tview,$w) if ($mode eq 'orcc'); + }); + #check soc status every 0.5 second. refresh device table if there is any changes + Glib::Timeout->add (100, sub{ + my ($state,$timeout)= get_gui_status($self); + if ($timeout>0){ + $timeout--; + set_gui_status($self,$state,$timeout); + return TRUE; + } + if($state eq "ideal"){ + return TRUE; + } + #refresh GUI + my $saved_name=$self->object_get_attribute('save_as'); + if(defined $saved_name) {$entry->set_text($saved_name);} + $saved_name=$self->object_get_attribute('out_name'); + if(defined $saved_name) {$entry2->set_text($saved_name);} + $notebook->destroy; + $notebook = trace_maker_notebook($self,$mode,$tview); + $v2 -> pack1($notebook, TRUE, TRUE); + set_gui_status($self,"ideal",0); + return TRUE; + } ); + return $sc_win; +} \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/traffic_pattern.pl b/mpsoc/perl_gui/lib/perl/traffic_pattern.pl index 0cc4d67..ec017d8 100644 --- a/mpsoc/perl_gui/lib/perl/traffic_pattern.pl +++ b/mpsoc/perl_gui/lib/perl/traffic_pattern.pl @@ -5,223 +5,189 @@ use FindBin; use lib $FindBin::Bin; - sub get_sample_emulation_param { - my ($emulate,$sample)=@_; - my $ref=$emulate->object_get_attribute($sample,"noc_info"); - my %noc_info= %$ref; - my $topology=$noc_info{'TOPOLOGY'}; - my $C=$noc_info{C}; - my $T1=$noc_info{'T1'}; - my $T2=$noc_info{'T2'}; - my $T3=$noc_info{'T3'}; - my $V =$noc_info{'V'}; - my $Fpay = $noc_info{'Fpay'}; - return ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($emulate,$sample)=@_; + my $ref=$emulate->object_get_attribute($sample,"noc_info"); + my %noc_info= %$ref; + my $topology=$noc_info{'TOPOLOGY'}; + my $C=$noc_info{C}; + my $T1=$noc_info{'T1'}; + my $T2=$noc_info{'T2'}; + my $T3=$noc_info{'T3'}; + my $V =$noc_info{'V'}; + my $Fpay = $noc_info{'Fpay'}; + return ($topology, $T1, $T2, $T3, $V, $Fpay); } - - sub getBit{ - my ($num, $b, $W)=@_; - while($b<0) {$b=$b+$W; } - $b=$b % $W; - return ($num >> $b) & 1; + my ($num, $b, $W)=@_; + while($b<0) {$b=$b+$W; } + $b=$b % $W; + return ($num >> $b) & 1; } # number; b:bit location; W: number width log2(num); v: 1 assert the bit, 0 de-assert the bit; sub setBit{ - my ($num ,$b,$W,$v)=@_; - while($b<0) {$b=$b+$W;} - $b=$b % $W; - + my ($num ,$b,$W,$v)=@_; + while($b<0) {$b=$b+$W;} + $b=$b % $W; my $mask = 1 << $b; if ($v == 0) {$$num = $$num & ~$mask;} # assert bit else {$$num = $$num | $mask;} #de-assert bit } sub pck_dst_gen_2D { - my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - - my $NEw=log2($NE); - #for mesh-tori - my ($current_l,$current_x, $current_y); - my ($dest_l,$dest_x,$dest_y); - - ($current_x,$current_y,$current_l)=mesh_tori_addrencod_sep($core_num,$T1, $T2,$T3); - - if( $traffic eq "random") { - my @randoms=@{$rnd}; - my $tmp = @{$randoms[$core_num]}[$line_num-1]; - return endp_addr_encoder($self,$tmp); - } - - if( $traffic eq "transposed 1"){ - $dest_x = $T1-$current_y-1; - $dest_y = $T2-$current_x-1; - $dest_l = $T3-$current_l-1; - return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); - } - - if( $traffic eq "transposed 2"){ - $dest_x = $current_y; - $dest_y = $current_x; - $dest_l = $current_l; - return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); - } - - if( $traffic eq "bit reverse"){ - #di = sb−i−1 - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) {setBit(\$tmp, $i, $NEw, getBit($core_num, $NEw-$i-1, $NEw));} - return endp_addr_encoder($self,$tmp); - } - - if( $traffic eq "bit complement") { - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i, $NEw)==0)}; - return endp_addr_encoder($self,$tmp); - } - - if( $traffic eq "tornado") { - #[(x+(k/2-1)) mod k, (y+(k/2-1)) mod k], - $dest_x = (($current_x + (int($T1/2)-1)) % $T1); - $dest_y = (($current_y + (int($T2/2)-1)) % $T2); - $dest_l = $current_l; - return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); - } - + my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my $NEw=log2($NE); + #for mesh-tori + my ($current_l,$current_x, $current_y); + my ($dest_l,$dest_x,$dest_y); + ($current_x,$current_y,$current_l)=mesh_tori_addrencod_sep($core_num,$T1, $T2,$T3); + if( $traffic eq "random") { + my @randoms=@{$rnd}; + my $tmp = @{$randoms[$core_num]}[$line_num-1]; + return endp_addr_encoder($self,$tmp); + } + if( $traffic eq "transposed 1"){ + $dest_x = $T1-$current_y-1; + $dest_y = $T2-$current_x-1; + $dest_l = $T3-$current_l-1; + return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); + } + if( $traffic eq "transposed 2"){ + $dest_x = $current_y; + $dest_y = $current_x; + $dest_l = $current_l; + return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); + } + if( $traffic eq "bit reverse"){ + #di = sb−i−1 + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) {setBit(\$tmp, $i, $NEw, getBit($core_num, $NEw-$i-1, $NEw));} + return endp_addr_encoder($self,$tmp); + } + if( $traffic eq "bit complement") { + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i, $NEw)==0)}; + return endp_addr_encoder($self,$tmp); + } + if( $traffic eq "tornado") { + #[(x+(k/2-1)) mod k, (y+(k/2-1)) mod k], + $dest_x = (($current_x + (int($T1/2)-1)) % $T1); + $dest_y = (($current_y + (int($T2/2)-1)) % $T2); + $dest_l = $current_l; + return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); + } if($traffic eq "shuffle"){ - #di = si−1 mod b - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i-1, $NEw));} - return endp_addr_encoder($self,$tmp); - } - + #di = si−1 mod b + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i-1, $NEw));} + return endp_addr_encoder($self,$tmp); + } if($traffic eq "bit rotation"){ - #di = si+1 mod b - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i+1, $NEw));} - return endp_addr_encoder($self,$tmp); - } - - if($traffic eq "neighbor"){ - #dx = sx + 1 mod k - #if ($current_x==0 && $current_y==0 && $current_l ==0) { - # $dest_x = 2; - # $dest_y = 2; - # $dest_l = 0; - #}else { - # $dest_x = $current_x; - # $dest_y = $current_y; - # $dest_l = $current_l; - #} - #return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); - - $dest_x = ($current_x + 1) % $T1; - $dest_y = ($current_y + 1) % $T2; - $dest_l = $current_l; - return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); - } - if($traffic eq "custom"){ - my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); - for (my $i=0;$i<$num;$i++){ - my $src = $self->object_get_attribute($sample,"SRC_$i"); - my $dst = $self->object_get_attribute($sample,"DST_$i"); - return endp_addr_encoder($self,$dst) if($src == $core_num); - } - return endp_addr_encoder($self,$core_num);#off - } - - print ("ERROR: $traffic is an unsupported traffic pattern\n"); - $dest_x = $current_x; - $dest_y = $current_y; - $dest_l = $current_l; - return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); + #di = si+1 mod b + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i+1, $NEw));} + return endp_addr_encoder($self,$tmp); + } + if($traffic eq "neighbor"){ + #dx = sx + 1 mod k + #if ($current_x==0 && $current_y==0 && $current_l ==0) { + # $dest_x = 2; + # $dest_y = 2; + # $dest_l = 0; + #}else { + # $dest_x = $current_x; + # $dest_y = $current_y; + # $dest_l = $current_l; + #} + #return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); + $dest_x = ($current_x + 1) % $T1; + $dest_y = ($current_y + 1) % $T2; + $dest_l = $current_l; + return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); + } + if($traffic eq "custom"){ + my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); + for (my $i=0;$i<$num;$i++){ + my $src = $self->object_get_attribute($sample,"SRC_$i"); + my $dst = $self->object_get_attribute($sample,"DST_$i"); + return endp_addr_encoder($self,$dst) if($src == $core_num); + } + return endp_addr_encoder($self,$core_num);#off + } + print ("ERROR: $traffic is an unsupported traffic pattern\n"); + $dest_x = $current_x; + $dest_y = $current_y; + $dest_l = $current_l; + return mesh_tori_addr_join($dest_x,$dest_y,$dest_l,$T1, $T2,$T3); } - - - sub pck_dst_gen_1D { - my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); - my $NEw=log2($NE); - - if( $traffic eq "random") { - my @randoms=@{$rnd}; - my $tmp = @{$randoms[$core_num]}[$line_num-1]; - return endp_addr_encoder($self,$tmp); - } - - if( $traffic eq "transposed 1"){ - return endp_addr_encoder($self,$NE-$core_num-1); - } - - if( $traffic eq "transposed 2"){ - return endp_addr_encoder($self,$NE-$core_num-1); - } - - if( $traffic eq "bit reverse"){ - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) {setBit(\$tmp, $i, $NEw, getBit($core_num, $NEw-$i-1, $NEw));} - return endp_addr_encoder($self,$tmp); - } - - if( $traffic eq "bit complement") { - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i, $NEw)==0)}; - return endp_addr_encoder($self,$tmp); - } - - if( $traffic eq "tornado") { - #[(x+(k/2-1)) mod k, (y+(k/2-1)) mod k], - return endp_addr_encoder($self, ($core_num + (int($NE/2)-1)) % $NE); - } - - if($traffic eq "shuffle"){ - #di = si−1 mod b - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i-1, $NEw));} - return endp_addr_encoder($self,$tmp); - } - + my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my $NEw=log2($NE); + if( $traffic eq "random") { + my @randoms=@{$rnd}; + my $tmp = @{$randoms[$core_num]}[$line_num-1]; + return endp_addr_encoder($self,$tmp); + } + if( $traffic eq "transposed 1"){ + return endp_addr_encoder($self,$NE-$core_num-1); + } + if( $traffic eq "transposed 2"){ + return endp_addr_encoder($self,$NE-$core_num-1); + } + if( $traffic eq "bit reverse"){ + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) {setBit(\$tmp, $i, $NEw, getBit($core_num, $NEw-$i-1, $NEw));} + return endp_addr_encoder($self,$tmp); + } + if( $traffic eq "bit complement") { + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i, $NEw)==0)}; + return endp_addr_encoder($self,$tmp); + } + if( $traffic eq "tornado") { + #[(x+(k/2-1)) mod k, (y+(k/2-1)) mod k], + return endp_addr_encoder($self, ($core_num + (int($NE/2)-1)) % $NE); + } + if($traffic eq "shuffle"){ + #di = si−1 mod b + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i-1, $NEw));} + return endp_addr_encoder($self,$tmp); + } if($traffic eq "bit rotation"){ - #di = si+1 mod b - my $tmp=0; - for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i+1, $NEw));} - return endp_addr_encoder($self,$tmp); - } - - if($traffic eq "neighbor"){ - #dx = sx + 1 mod k - return endp_addr_encoder($self,($core_num + 1) % $NE); - } - - if($traffic eq "custom"){ - my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); - for (my $i=0;$i<$num;$i++){ - my $src = $self->object_get_attribute($sample,"SRC_$i"); - my $dst = $self->object_get_attribute($sample,"DST_$i"); - return endp_addr_encoder($self,$dst) if($src == $core_num); - } - return endp_addr_encoder($self,$core_num);#off - } - - printf ("ERROR: $traffic is an unsupported traffic pattern\n"); - return endp_addr_encoder($self,$core_num); + #di = si+1 mod b + my $tmp=0; + for(my $i=0; $i< $NEw; $i++) { setBit(\$tmp, $i, $NEw, getBit($core_num, $i+1, $NEw));} + return endp_addr_encoder($self,$tmp); + } + if($traffic eq "neighbor"){ + #dx = sx + 1 mod k + return endp_addr_encoder($self,($core_num + 1) % $NE); + } + if($traffic eq "custom"){ + my $num=$self->object_get_attribute($sample,"CUSTOM_SRC_NUM"); + for (my $i=0;$i<$num;$i++){ + my $src = $self->object_get_attribute($sample,"SRC_$i"); + my $dst = $self->object_get_attribute($sample,"DST_$i"); + return endp_addr_encoder($self,$dst) if($src == $core_num); + } + return endp_addr_encoder($self,$core_num);#off + } + printf ("ERROR: $traffic is an unsupported traffic pattern\n"); + return endp_addr_encoder($self,$core_num); } - sub pck_dst_gen{ - my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - return pck_dst_gen_2D ($self,$sample,$traffic,$core_num,$line_num,$rnd) if(( $topology eq '"MESH"') ||( $topology eq '"TORUS"')); - return pck_dst_gen_1D ($self,$sample,$traffic,$core_num,$line_num,$rnd); + my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; + my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); + return pck_dst_gen_2D ($self,$sample,$traffic,$core_num,$line_num,$rnd) if(( $topology eq '"MESH"') ||( $topology eq '"TORUS"')); + return pck_dst_gen_1D ($self,$sample,$traffic,$core_num,$line_num,$rnd); } - - 1; - +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/tsort.pm b/mpsoc/perl_gui/lib/perl/tsort.pm index cdaa055..2592202 100644 --- a/mpsoc/perl_gui/lib/perl/tsort.pm +++ b/mpsoc/perl_gui/lib/perl/tsort.pm @@ -1,30 +1,23 @@ #!/usr/bin/perl - - - package Algorithm::TSort; use 5.007003; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); - # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. - -# This allows declaration use Algorithm::TSort ':all'; +# This allows declaration use Algorithm::TSort ':all'; # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( - tsort - Graph + tsort + Graph ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); - our @EXPORT = qw( tsort ); - our $VERSION = '0.05'; { package Algorithm::TSort::ADJ; @@ -36,7 +29,6 @@ our $VERSION = '0.05'; } return (); } - sub nodes { return keys %{ $_[0] }; } @@ -48,12 +40,12 @@ our $VERSION = '0.05'; } package Algorithm::TSort::ADJSUB_ARRAYREF; sub adj_nodes { - my $array = $_[0]->( $_[1] ); - return $array ? @$array : (); + my $array = $_[0]->( $_[1] ); + return $array ? @$array : (); } package Algorithm::TSort::Guard; sub new{ - return bless $_[1], $_[0]; + return bless $_[1], $_[0]; } sub DESTROY { $_[0]->() }; } @@ -116,10 +108,8 @@ sub tsort($;@) { } } $guard = Algorithm::TSort::Guard->new(sub { - $req_sub = undef; # remove circular dependency; + $req_sub = undef; # remove circular dependency; }); - - $req_sub = sub { my $node = shift; if ( $seen{$node} ) { @@ -133,7 +123,6 @@ sub tsort($;@) { $seen{$node} = 2; push @sorted, $node; }; - for (@nodes) { next if $seen{$_}; $req_sub->($_); @@ -141,9 +130,6 @@ sub tsort($;@) { return reverse @sorted; } - - - sub cicle_detect($;@) { my $object = shift; my @nodes = @_; @@ -162,16 +148,14 @@ sub cicle_detect($;@) { } } $guard = Algorithm::TSort::Guard->new(sub { - $req_sub = undef; # remove circular dependency; + $req_sub = undef; # remove circular dependency; }); - - $req_sub = sub { my $node = shift; if ( $seen{$node} ) { #die "Algorithm::TSort - can't tsort cicle detected" if ( $seen{$node} == 1 ); - $cyclic=1 if ( $seen{$node} == 1 ); - return; + $cyclic=1 if ( $seen{$node} == 1 ); + return; } $seen{$node} = 1; for ( $object->adj_nodes($node) ) { @@ -180,7 +164,6 @@ sub cicle_detect($;@) { $seen{$node} = 2; push @sorted, $node; }; - for (@nodes) { next if $seen{$_}; $req_sub->($_); @@ -188,18 +171,6 @@ sub cicle_detect($;@) { return $cyclic; } - - - - - - - - - - - - 1; __END__ # Below is stub documentation for your module. You'd better edit it! @@ -218,12 +189,12 @@ Algorithm::TSort - Perl extension for topological sort say for @sorted; # -- OR -- - + # $adj_sub = sub { return unless $adj->{ $_[0] } ; return @{$adj->{$_[0]}}; }; my (@sorted) = tsort( Graph( ADJSUB => $adj_sub ), @nodes_for_sort ); # -- OR -- - + # $sub_arrayref = sub { $adj->{ $_[0] } }; my (@sorted) = tsort( Graph( ADJSUB_ARRAYREF => $adj_sub ), @nodes_for_sort ); diff --git a/mpsoc/perl_gui/lib/perl/uart.pl b/mpsoc/perl_gui/lib/perl/uart.pl index 547c1d1..3d72e2a 100644 --- a/mpsoc/perl_gui/lib/perl/uart.pl +++ b/mpsoc/perl_gui/lib/perl/uart.pl @@ -1,27 +1,18 @@ #!/usr/bin/perl -w - use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - require "widget.pl"; - - use constant::boolean; - - use Data::Dumper; use File::Which; use File::Basename; - use IPC::Run qw( harness start pump finish timeout ); use String::Scanf; # imports sscanf() use base 'Class::Accessor::Fast'; - - use Consts; + BEGIN { my $module = (Consts::GTK_VERSION==2) ? 'Gtk2' : 'Gtk3'; my $file = $module; @@ -31,261 +22,204 @@ BEGIN $module->import; } - - __PACKAGE__->mk_accessors(qw{ - window - sourceview + window + sourceview }); my $NAME = 'Uart Terminal'; -my $path = ""; +my $path = ""; our $FONT_SIZE='default'; our $ICON_SIZE='default'; - - - sub uart_stand_alone(){ - $path = "../../"; - set_path_env(); - my $project_dir = get_project_dir(); #mpsoc dir addr - my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; - if (-f $paths_file){#} && defined $ENV{PRONOC_WORK} ) { - my $paths= do $paths_file; - my %p=%{$paths}; - $FONT_SIZE= $p{'GUI_SETTING'}{'FONT_SIZE'} if (defined $p{'GUI_SETTING'}{'FONT_SIZE'}); - $ICON_SIZE= $p{'GUI_SETTING'}{'ICON_SIZE'} if (defined $p{'GUI_SETTING'}{'ICON_SIZE'}); - } - - set_defualt_font_size(); - my $window=uart_main(); - $window->signal_connect (destroy => sub { gui_quite();}); + $path = "../../"; + set_path_env(); + my $project_dir = get_project_dir(); #mpsoc dir addr + my $paths_file= "$project_dir/mpsoc/perl_gui/lib/Paths"; + if (-f $paths_file){#} && defined $ENV{PRONOC_WORK} ) { + my $paths= do $paths_file; + my %p=%{$paths}; + $FONT_SIZE= $p{'GUI_SETTING'}{'FONT_SIZE'} if (defined $p{'GUI_SETTING'}{'FONT_SIZE'}); + $ICON_SIZE= $p{'GUI_SETTING'}{'ICON_SIZE'} if (defined $p{'GUI_SETTING'}{'ICON_SIZE'}); + } + set_defualt_font_size(); + my $window=uart_main(); + $window->signal_connect (destroy => sub { gui_quite();}); } exit gtk_gui_run(\&uart_stand_alone) unless caller; - - - sub create_rsv_box { - my ($self,$num)=@_; - my ($sw,$tview) =create_txview(); + my ($self,$num)=@_; + my ($sw,$tview) =create_txview(); $sw->set_policy('never','automatic'); $sw->set_border_width(3); my($width,$hight)=max_win_size(); - $sw->set_size_request($width/10,$hight/10); + $sw->set_size_request($width/10,$hight/10); my $frame = gen_frame(); - $frame->set_shadow_type ('in'); - $frame->add ($sw); - my $def = 126-$num; - my $spin=gen_spin_object($self,'CTRL',"INDEX_$num",'0,128,1',$def,undef,undef); - my $label=gen_label_in_center("INDEX#"); - my $box=def_pack_hbox( FALSE, 0 , $label,$spin); - $frame->set_label_widget ($box); - return ($frame,$tview); + $frame->set_shadow_type ('in'); + $frame->add ($sw); + my $def = 126-$num; + my $spin=gen_spin_object($self,'CTRL',"INDEX_$num",'0,128,1',$def,undef,undef); + my $label=gen_label_in_center("INDEX#"); + my $box=def_pack_hbox( FALSE, 0 , $label,$spin); + $frame->set_label_widget ($box); + return ($frame,$tview); } - - sub receive_boxes{ - my $self=shift; - my $table= def_table(2,10,FALSE); - my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); - add_widget_to_scrolled_win($table,$scrolled_win); - my $num = $self->object_get_attribute('CTRL','UART_NUM'); - my $dim_y = floor(sqrt($num)); - my @tviews; - for (my $i=0; $i<$num; $i+=1){ - my ($box,$tview) = create_rsv_box($self,$i); - $tviews[$i]=$tview; - my $y= int($i/$dim_y); - my $x= $i % $dim_y; - $table->attach_defaults ($box, $x, $x+1 , $y, $y+1); - } - return ($scrolled_win,\@tviews); + my $self=shift; + my $table= def_table(2,10,FALSE); + my $scrolled_win=gen_scr_win_with_adjst ($self,"receive_box"); + add_widget_to_scrolled_win($table,$scrolled_win); + my $num = $self->object_get_attribute('CTRL','UART_NUM'); + my $dim_y = floor(sqrt($num)); + my @tviews; + for (my $i=0; $i<$num; $i+=1){ + my ($box,$tview) = create_rsv_box($self,$i); + $tviews[$i]=$tview; + my $y= int($i/$dim_y); + my $x= $i % $dim_y; + $table->attach_defaults ($box, $x, $x+1 , $y, $y+1); + } + return ($scrolled_win,\@tviews); } sub ctrl_boxes{ - my ($self,$main_tview)=@_; - - my $state=$self->object_get_attribute("CTRL","RUN"); - if (!defined $state){ - $state='OFF' ; - $self->object_add_attribute("CTRL","RUN",$state); - } - - - my $table= def_table(2,10,FALSE); - my $scrolled_win=add_widget_to_scrolled_win ($table); - my ($row,$col)=(0,0); - my @info = ( - #TODO add Altera_Qsys_UART - { label=>" UART name ", param_name=>'UART_NAME', type=>"Combo-box", default_val=>'ProNoC_XILINX_UART', content=>"ProNoC_XILINX_UART,ProNoC_ALTERA_UART", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}, - { label=>" Number of UART", param_name=>'UART_NUM', type=>"Spin-button", default_val=>1, content=>"1,128,1", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_all', loc=>'vertical'} - - ); - - - my $uname= $self->object_get_attribute('CTRL','UART_NAME'); - $uname = 'ProNoC_XILINX_UART' if(!defined $uname); - if ($uname eq "ProNoC_XILINX_UART" ) { - push (@info,{ label=>" JTAG CHAIN ", param_name=>'JTAG_CHAIN', type=>"Combo-box", default_val=>3, content=>"1,2,3,4", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}) ; - push (@info,{ label=>" JTAG TARGET ", param_name=>'JTAG_TARGET', type=>"Spin-button", default_val=>3, content=>"1,128,1", info=>"The FPGA device target number in the Jtag chain. Click on the front magnifier Icon to see the list of devices in your board JTAG chain.", param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}) ; - }elsif ($uname eq "ProNoC_ALTERA_UART" ) { - my $list= $self->object_get_attribute('CTRL','quartus_device_list'); - push (@info,{ label=>" Hardware Name", param_name=>'quartus_hardware', type=>"Entry", default_val=>undef, content=>undef, info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>undef, loc=>'vertical'}) ; - push (@info,{ label=>" Device Number", param_name=>'quartus_device', type=>"EntryCombo", default_val=>undef, content=>$list, info=>undef,param_parent=>'CTRL', ref_delay=> 1, new_status=>undef, loc=>'vertical'}) ; - } - - - my @restricted_params= ('UART_NAME','JTAG_TARGET','quartus_hardware','quartus_device'); - - foreach my $d (@info) { - my $wiget; - ($row,$col,$wiget)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); - - #the following parameter should not be changed while the jtag connection is stablished - if($state eq "ON"){ - $wiget->set_sensitive (FALSE) if (check_scolar_exist_in_array($d->{param_name},\@restricted_params )); - } - - - if($d->{param_name} eq 'JTAG_TARGET' || $d->{param_name} eq "quartus_hardware"){ - my $search=def_image_button($path."icons/browse.png"); - $table->attach ($search, 4, 5,$row-1,$row,'shrink','shrink',2,2); - set_tip($search, "Display all Jtag targets. You need to connect your FPGA device to your PC first."); - $search-> signal_connect("clicked" => sub{ - show_all_xilinx_targets ($self,$main_tview) if($uname eq "ProNoC_XILINX_UART"); - capture_altera_jtag_info($self,$main_tview) if($uname eq "ProNoC_ALTERA_UART"); - }); - - } - } - - - - $col=0; - my $label=gen_label_in_left(" JTAG Connect "); - my $run= ($state eq 'ON')? def_colored_button('ON',17): def_colored_button('OFF',4); - $table->attach ($label, $col, $col+1,$row,$row+1,'fill','shrink',2,2); $col+=1; - $table->attach ($run, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++;$col=0; - $run -> signal_connect("clicked" => sub{ - my $state=$self->object_get_attribute("CTRL","RUN"); - my $new = ($state eq "ON")? "OFF" : "ON"; - $self->object_add_attribute("CTRL","CONNECT",1) if($new eq 'ON'); - $self->object_add_attribute("CTRL","DISCONNECT",1) if($new eq 'OFF'); - set_gui_status($self,"ON-OFF",1); - }); - - return $scrolled_win; + my ($self,$main_tview)=@_; + my $state=$self->object_get_attribute("CTRL","RUN"); + if (!defined $state){ + $state='OFF' ; + $self->object_add_attribute("CTRL","RUN",$state); + } + my $table= def_table(2,10,FALSE); + my $scrolled_win=add_widget_to_scrolled_win ($table); + my ($row,$col)=(0,0); + my @info = ( + #TODO add Altera_Qsys_UART + { label=>" UART name ", param_name=>'UART_NAME', type=>"Combo-box", default_val=>'ProNoC_XILINX_UART', content=>"ProNoC_XILINX_UART,ProNoC_ALTERA_UART", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}, + { label=>" Number of UART", param_name=>'UART_NUM', type=>"Spin-button", default_val=>1, content=>"1,128,1", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_all', loc=>'vertical'} + ); + my $uname= $self->object_get_attribute('CTRL','UART_NAME'); + $uname = 'ProNoC_XILINX_UART' if(!defined $uname); + if ($uname eq "ProNoC_XILINX_UART" ) { + push (@info,{ label=>" JTAG CHAIN ", param_name=>'JTAG_CHAIN', type=>"Combo-box", default_val=>3, content=>"1,2,3,4", info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}) ; + push (@info,{ label=>" JTAG TARGET ", param_name=>'JTAG_TARGET', type=>"Spin-button", default_val=>3, content=>"1,128,1", info=>"The FPGA device target number in the Jtag chain. Click on the front magnifier Icon to see the list of devices in your board JTAG chain.", param_parent=>'CTRL', ref_delay=> 1, new_status=>'ref_ctrl', loc=>'vertical'}) ; + }elsif ($uname eq "ProNoC_ALTERA_UART" ) { + my $list= $self->object_get_attribute('CTRL','quartus_device_list'); + push (@info,{ label=>" Hardware Name", param_name=>'quartus_hardware', type=>"Entry", default_val=>undef, content=>undef, info=>undef, param_parent=>'CTRL', ref_delay=> 1, new_status=>undef, loc=>'vertical'}) ; + push (@info,{ label=>" Device Number", param_name=>'quartus_device', type=>"EntryCombo", default_val=>undef, content=>$list, info=>undef,param_parent=>'CTRL', ref_delay=> 1, new_status=>undef, loc=>'vertical'}) ; + } + my @restricted_params= ('UART_NAME','JTAG_TARGET','quartus_hardware','quartus_device'); + foreach my $d (@info) { + my $wiget; + ($row,$col,$wiget)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay}, $d->{new_status}, $d->{loc}); + #the following parameter should not be changed while the jtag connection is stablished + if($state eq "ON"){ + $wiget->set_sensitive (FALSE) if (check_scolar_exist_in_array($d->{param_name},\@restricted_params )); + } + if($d->{param_name} eq 'JTAG_TARGET' || $d->{param_name} eq "quartus_hardware"){ + my $search=def_image_button($path."icons/browse.png"); + $table->attach ($search, 4, 5,$row-1,$row,'shrink','shrink',2,2); + set_tip($search, "Display all Jtag targets. You need to connect your FPGA device to your PC first."); + $search-> signal_connect("clicked" => sub{ + show_all_xilinx_targets ($self,$main_tview) if($uname eq "ProNoC_XILINX_UART"); + capture_altera_jtag_info($self,$main_tview) if($uname eq "ProNoC_ALTERA_UART"); + }); + } + } + $col=0; + my $label=gen_label_in_left(" JTAG Connect "); + my $run= ($state eq 'ON')? def_colored_button('ON',17): def_colored_button('OFF',4); + $table->attach ($label, $col, $col+1,$row,$row+1,'fill','shrink',2,2); $col+=1; + $table->attach ($run, $col, $col+1,$row,$row+1,'shrink','shrink',2,2); $row++;$col=0; + $run -> signal_connect("clicked" => sub{ + my $state=$self->object_get_attribute("CTRL","RUN"); + my $new = ($state eq "ON")? "OFF" : "ON"; + $self->object_add_attribute("CTRL","CONNECT",1) if($new eq 'ON'); + $self->object_add_attribute("CTRL","DISCONNECT",1) if($new eq 'OFF'); + set_gui_status($self,"ON-OFF",1); + }); + return $scrolled_win; } - - sub select_uart_board { - my ($self,$table,$vendor,$row,$col)=@_; - - #get the list of boards located in "boards/*" folder - my @dirs = grep {-d} glob("$path/../boards/$vendor/*"); - my ($fpgas,$init); - $fpgas=""; - - foreach my $dir (@dirs) { - my ($name,$fpath,$suffix) = fileparse("$dir",qr"\..[^.]*$"); - - $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; - $init="$name"; - } - my $button=def_image_button("$path/icons/help.png"); - my $help1= "The list of supported boards are obtained from \"mpsoc/boards/$vendor\" path. You can add your boards by adding its required files in aforementioned path"; - $button->signal_connect("clicked" => sub {message_dialog($help1);}); - my $combo=gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef); - $table->attach(gen_label_in_left('Targeted Board:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - $table->attach($button,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; - $table->attach($combo, $col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; - - #do not change the board when the connection is ON - my $state=$self->object_get_attribute("CTRL","RUN"); - $combo->set_sensitive (FALSE) if($state eq "ON" ); - - + my ($self,$table,$vendor,$row,$col)=@_; + #get the list of boards located in "boards/*" folder + my @dirs = grep {-d} glob("$path/../boards/$vendor/*"); + my ($fpgas,$init); + $fpgas=""; + foreach my $dir (@dirs) { + my ($name,$fpath,$suffix) = fileparse("$dir",qr"\..[^.]*$"); + $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name"; + $init="$name"; + } + my $button=def_image_button("$path/icons/help.png"); + my $help1= "The list of supported boards are obtained from \"mpsoc/boards/$vendor\" path. You can add your boards by adding its required files in aforementioned path"; + $button->signal_connect("clicked" => sub {message_dialog($help1);}); + my $combo=gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef); + $table->attach(gen_label_in_left('Targeted Board:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; + $table->attach($button,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; + $table->attach($combo, $col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++; + #do not change the board when the connection is ON + my $state=$self->object_get_attribute("CTRL","RUN"); + $combo->set_sensitive (FALSE) if($state eq "ON" ); } - - sub capture_altera_jtag_info { - my ($self,$tview) = @_; - my $command= "$ENV{QUARTUS_BIN}/jtagconfig"; - #add_info($tview,"$command\n"); - my $stdout= run_cmd_textview_errors($command,$tview); - if(!defined $stdout){ - add_colored_info($tview,"No JTAG Hardware is detected\n",'red'); - return 1; - } - #add_info($tview,"$stdout\n"); - my @a=split /1\)\s+/, $stdout; - if(!defined $a[1]){ - add_colored_info($tview,"No JTAG Hardware is detected\n",'red'); - return 1; - } - my @b=split /\s+/, $a[1]; - my $hw=$b[0]; - - - - - my @devs=split /\n/, $stdout; - - $self->object_add_attribute('CTRL','quartus_hardware',$hw); - add_colored_info($tview,"Detected Hardware: $hw\n",'blue'); - - #capture device name in JTAG chain - - my $i=0; - my $info=""; - my $list; - foreach my $p (@devs){ - next if ($p =~/^\s*1\)/); - $i++; - $info .= "\t $i : $p\n"; - $list= (defined $list) ? "$list,$i" : $i; - - } - - $info = "There are total of $i devices in JTAG chain:\n $info. Select the corresponding Jtag device number which the serial port is connected to\n"; - - - my $names = join (',',@devs); - add_colored_info($tview,"$info",'blue'); - $self->object_add_attribute('CTRL','quartus_device_list',$list); - $self->object_add_attribute('CTRL','quartus_device',$i); - set_gui_status($self,'ref_ctrl',1); - return 0; + my ($self,$tview) = @_; + my $command= "$ENV{QUARTUS_BIN}/jtagconfig"; + #add_info($tview,"$command\n"); + my $stdout= run_cmd_textview_errors($command,$tview); + if(!defined $stdout){ + add_colored_info($tview,"No JTAG Hardware is detected\n",'red'); + return 1; + } + #add_info($tview,"$stdout\n"); + my @a=split /1\)\s+/, $stdout; + if(!defined $a[1]){ + add_colored_info($tview,"No JTAG Hardware is detected\n",'red'); + return 1; + } + my @b=split /\s+/, $a[1]; + my $hw=$b[0]; + my @devs=split /\n/, $stdout; + $self->object_add_attribute('CTRL','quartus_hardware',$hw); + add_colored_info($tview,"Detected Hardware: $hw\n",'blue'); + #capture device name in JTAG chain + my $i=0; + my $info=""; + my $list; + foreach my $p (@devs){ + next if ($p =~/^\s*1\)/); + $i++; + $info .= "\t $i : $p\n"; + $list= (defined $list) ? "$list,$i" : $i; + } + $info = "There are total of $i devices in JTAG chain:\n $info. Select the corresponding Jtag device number which the serial port is connected to\n"; + my $names = join (',',@devs); + add_colored_info($tview,"$info",'blue'); + $self->object_add_attribute('CTRL','quartus_device_list',$list); + $self->object_add_attribute('CTRL','quartus_device',$i); + set_gui_status($self,'ref_ctrl',1); + return 0; } - - - - - - sub show_all_xilinx_targets{ - my ($self,$tview) =@_; - my ($pipe,$in, $out, $err,$r); - my $xsct = which('xsct'); - - #check if $xsct exits - unless(-f $xsct){ - add_colored_info($tview,"Error xsct not found. Please add the path to xilinx/SDK/bin to your \$PATH environment\n",'red'); - return 0; - } - my @cat = ( $xsct ); - $pipe =start \@cat, \$in, \$out, \$err or $r=$?; - if(defined $r){ - add_colored_info($tview," quartus_stp got an Error: $r\n",'red'); - return 0; - } - + my ($self,$tview) =@_; + my ($pipe,$in, $out, $err,$r); + my $xsct = which('xsct'); + #check if $xsct exits + unless(-f $xsct){ + add_colored_info($tview,"Error xsct not found. Please add the path to xilinx/SDK/bin to your \$PATH environment\n",'red'); + return 0; + } + my @cat = ( $xsct ); + $pipe =start \@cat, \$in, \$out, \$err or $r=$?; + if(defined $r){ + add_colored_info($tview," quartus_stp got an Error: $r\n",'red'); + return 0; + } $in = ""; return 0 unless run_xsct_pipe($self,\$pipe,\$in,\$out,\$err,$tview); $in = "set jseq [jtag sequence]\n connect\n"; @@ -293,404 +227,325 @@ sub show_all_xilinx_targets{ $in = "set R [jtag targets]\n puts \$R \n"; return 0 unless run_xsct_pipe($self,\$pipe,\$in,\$out,\$err,$tview); if (length ($out)> 10){ - add_colored_info($tview,"targets are:\n $out .\n",'blue'); + add_colored_info($tview,"targets are:\n $out .\n",'blue'); }else { - add_colored_info($tview,"No Jtag target is detected. Make sure your FPGA board is connected to the PC and it is powered on.\n",'red'); - } - close_xsct($self,\$pipe,$tview,\$in, \$out, \$err); - return $out; + add_colored_info($tview,"No Jtag target is detected. Make sure your FPGA board is connected to the PC and it is powered on.\n",'red'); + } + close_xsct($self,\$pipe,$tview,\$in, \$out, \$err); + return $out; } - - sub sender_box{ - my ($self,$main_tview)=@_; - my $table= def_table(2,10,FALSE); - my $scrolled_win=add_widget_to_scrolled_win ($table); - my ($sw,$tview) =create_txview(); + my ($self,$main_tview)=@_; + my $table= def_table(2,10,FALSE); + my $scrolled_win=add_widget_to_scrolled_win ($table); + my ($sw,$tview) =create_txview(); $sw->set_policy('never','automatic'); $sw->set_border_width(3); my($width,$hight)=max_win_size(); - $sw->set_size_request($width/10,$hight/10); + $sw->set_size_request($width/10,$hight/10); my $frame = gen_frame(); - $frame->set_shadow_type ('in'); - $frame->add ($sw); - my $num = $self->object_get_attribute('CTRL','UART_NUM'); - my @indexs; - my $def; - for (my $i=0; $i<$num; $i+=1){ - my $index= $self->object_get_attribute("CTRL","INDEX_$i"); - $def= $index if(!defined $def); - $indexs[$i]=$index; - } - my $indexs = join(',',@indexs); - my $comb=gen_combobox_object($self,'CTRL',"SEND_TO_INDEX",$indexs,$def,undef,undef); - my $label=gen_label_in_center("SEND_TO INDEX#"); - my $send = def_image_button($path.'icons/run.png'); - my $box=def_pack_hbox( FALSE, 0 , $label,$comb,$send); - $frame->set_label_widget ($box); - $table->attach_defaults ($frame, 0, 1 , 0,1); - $send-> signal_connect("clicked" => sub{ - my $st =$self->object_get_attribute("CTRL","RUN"); - my $index =$self->object_get_attribute("CTRL","SEND_TO_INDEX"); - if ($st eq 'OFF'){ - add_colored_info($main_tview,"Error: Cannot send the data. Jtag connection is not established yet.\n",'red'); - return; - } - my $text_buffer = $tview->get_buffer; - my $txt=$text_buffer->get_text($text_buffer->get_bounds, TRUE); - if(length ($txt) >0 ){ - my $buf=$self->object_get_attribute("SEND","TXT_$index"); - $txt= $buf.$txt if(length $buf); - $self->object_add_attribute("SEND","TXT_$index",$txt); - set_gui_status($self,"REF_SEND",1); - - } - }); - - - return ($scrolled_win,$tview); + $frame->set_shadow_type ('in'); + $frame->add ($sw); + my $num = $self->object_get_attribute('CTRL','UART_NUM'); + my @indexs; + my $def; + for (my $i=0; $i<$num; $i+=1){ + my $index= $self->object_get_attribute("CTRL","INDEX_$i"); + $def= $index if(!defined $def); + $indexs[$i]=$index; + } + my $indexs = join(',',@indexs); + my $comb=gen_combobox_object($self,'CTRL',"SEND_TO_INDEX",$indexs,$def,undef,undef); + my $label=gen_label_in_center("SEND_TO INDEX#"); + my $send = def_image_button($path.'icons/run.png'); + my $box=def_pack_hbox( FALSE, 0 , $label,$comb,$send); + $frame->set_label_widget ($box); + $table->attach_defaults ($frame, 0, 1 , 0,1); + $send-> signal_connect("clicked" => sub{ + my $st =$self->object_get_attribute("CTRL","RUN"); + my $index =$self->object_get_attribute("CTRL","SEND_TO_INDEX"); + if ($st eq 'OFF'){ + add_colored_info($main_tview,"Error: Cannot send the data. Jtag connection is not established yet.\n",'red'); + return; + } + my $text_buffer = $tview->get_buffer; + my $txt=$text_buffer->get_text($text_buffer->get_bounds, TRUE); + if(length ($txt) >0 ){ + my $buf=$self->object_get_attribute("SEND","TXT_$index"); + $txt= $buf.$txt if(length $buf); + $self->object_add_attribute("SEND","TXT_$index",$txt); + set_gui_status($self,"REF_SEND",1); + } + }); + return ($scrolled_win,$tview); } - - sub check_jtag_connect { - my ($self,$pipe,$tview,$in, $out, $err,$pipe_name)=@_; - my $run =$self->object_get_attribute("CTRL","RUN"); - my $connect = $self->object_get_attribute("CTRL","CONNECT"); - my $disconnect = $self->object_get_attribute("CTRL","DISCONNECT"); - - - - my $r; - if($connect){ - - $r=start_xsct($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'xsct' ); - $r=start_stp ($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'stp' ); - if($r){ - $self->object_add_attribute("CTRL","RUN",'ON'); - add_info($tview,"Connected!\n"); - set_gui_status($self,"ref",1); - - - }else{ - $self->object_add_attribute("CTRL","RUN",'OFF'); - add_colored_info($tview,"failed to connect!\n",'red'); - set_gui_status($self,"ref",1); - - } - $self->object_add_attribute("CTRL","CONNECT",0); - }if($disconnect){ - close_xsct($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'xsct' ); - close_stp ($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'stp' ); - $self->object_add_attribute("CTRL","RUN",'OFF'); - $self->object_add_attribute("CTRL","DISCONNECT",0); - add_info($tview,"disconnected!\n"); - set_gui_status($self,"ref",1); - } -} - - + my ($self,$pipe,$tview,$in, $out, $err,$pipe_name)=@_; + my $run =$self->object_get_attribute("CTRL","RUN"); + my $connect = $self->object_get_attribute("CTRL","CONNECT"); + my $disconnect = $self->object_get_attribute("CTRL","DISCONNECT"); + my $r; + if($connect){ + $r=start_xsct($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'xsct' ); + $r=start_stp ($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'stp' ); + if($r){ + $self->object_add_attribute("CTRL","RUN",'ON'); + add_info($tview,"Connected!\n"); + set_gui_status($self,"ref",1); + }else{ + $self->object_add_attribute("CTRL","RUN",'OFF'); + add_colored_info($tview,"failed to connect!\n",'red'); + set_gui_status($self,"ref",1); + } + $self->object_add_attribute("CTRL","CONNECT",0); + }if($disconnect){ + close_xsct($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'xsct' ); + close_stp ($self,$pipe,$tview,$in, $out, $err) if($pipe_name eq 'stp' ); + $self->object_add_attribute("CTRL","RUN",'OFF'); + $self->object_add_attribute("CTRL","DISCONNECT",0); + add_info($tview,"disconnected!\n"); + set_gui_status($self,"ref",1); + } +} use constant UART_UPDATE_WB_ADDR => 7; use constant UART_UPDATE_WB_WR_DATA=> 6; -use constant UART_UPDATE_WB_RD_DATA => 5; - +use constant UART_UPDATE_WB_RD_DATA => 5; # Converts pairs of hex digits to asci sub hex_to_ascii { # $ascii ($hex) - my $s = shift; - - return pack 'H*', $s; + my $s = shift; + return pack 'H*', $s; } - - sub nop{ - #no oprtstion - return + #no oprtstion + return } ########## -# Quartus stp +# Quartus stp ########## - - sub run_stp_pipe{ - my ($self,$pipe,$in,$out,$err,$tview)=@_; - $$out=''; - $$in .= "puts done\n"; - - #print $$in; - - pump $$pipe while (length $$in); + my ($self,$pipe,$in,$out,$err,$tview)=@_; + $$out=''; + $$in .= "puts done\n"; + #print $$in; + pump $$pipe while (length $$in); until ($$out =~ /done/ || (length $$err)){ - - pump $$pipe; - refresh_gui(); - } + pump $$pipe; + refresh_gui(); + } if(length $$err){ - add_colored_info($tview,"Got an Error: $$err\n",'red'); - $self->object_add_attribute("CTRL","DISCONNECT",1); - set_gui_status($self,"ON-OFF",0); - return 0; + add_colored_info($tview,"Got an Error: $$err\n",'red'); + $self->object_add_attribute("CTRL","DISCONNECT",1); + set_gui_status($self,"ON-OFF",0); + return 0; } - # stp does not print on stderr. we need to check stdout manually for error + # stp does not print on stderr. we need to check stdout manually for error my @error_list=("ERROR:","can't read"); foreach my $err (@error_list) { - if( $$out =~ /$err/){ - add_colored_info($tview,"Got an Error: $$out\n",'red'); - $self->object_add_attribute("CTRL","DISCONNECT",1); - set_gui_status($self,"ON-OFF",0); - return 0; - } - + if( $$out =~ /$err/){ + add_colored_info($tview,"Got an Error: $$out\n",'red'); + $self->object_add_attribute("CTRL","DISCONNECT",1); + set_gui_status($self,"ON-OFF",0); + return 0; + } } - refresh_gui(); #print $$out; - return 1; + return 1; } sub start_stp{ - my ($self,$pipe,$tview,$in, $out, $err)=@_; - - - my $stp = which('quartus_stp'); - - #check if $xsct exits - unless(-f $stp){ - add_colored_info($tview,"Error quartus_stp not found. Please add the path to QuartusII/bin to your \$PATH environment\n",'red'); - return 0; - } - my @run = ( "$stp" ); - my @run_args = ( "-s" ); - - my $r; - - $$pipe =start [@run, @run_args], $in, $out, $err or $r=$?; - if(defined $r){ - add_colored_info($tview," quartus_stp got an Error: $r\n",'red'); - return 0; - } - - my $hdw= $self->object_get_attribute('CTRL','quartus_hardware'); - my $dev= $self->object_get_attribute('CTRL','quartus_device'); - - $hdw="" if(!defined $hdw); - $dev="" if(!defined $dev); - - - if(length ($hdw) ==0){ - add_colored_info($tview,"Error: Cannot initial the quartus_stp. the hardware name is not defined!\n",'red'); - return 0; - } - - if(length ($dev)==0) { - add_colored_info($tview,"Error: Cannot initial the quartus_stp. the device number is not defined!\n",'red'); - return 0; - } - - my $HARDWARE_NAME="$hdw *"; - my $DEVICE_NAME="\@$dev*"; - - - $$in = " "; - + my ($self,$pipe,$tview,$in, $out, $err)=@_; + my $stp = which('quartus_stp'); + #check if $xsct exits + unless(-f $stp){ + add_colored_info($tview,"Error quartus_stp not found. Please add the path to QuartusII/bin to your \$PATH environment\n",'red'); + return 0; + } + my @run = ( "$stp" ); + my @run_args = ( "-s" ); + my $r; + $$pipe =start [@run, @run_args], $in, $out, $err or $r=$?; + if(defined $r){ + add_colored_info($tview," quartus_stp got an Error: $r\n",'red'); + return 0; + } + my $hdw= $self->object_get_attribute('CTRL','quartus_hardware'); + my $dev= $self->object_get_attribute('CTRL','quartus_device'); + $hdw="" if(!defined $hdw); + $dev="" if(!defined $dev); + if(length ($hdw) ==0){ + add_colored_info($tview,"Error: Cannot initial the quartus_stp. the hardware name is not defined!\n",'red'); + return 0; + } + if(length ($dev)==0) { + add_colored_info($tview,"Error: Cannot initial the quartus_stp. the device number is not defined!\n",'red'); + return 0; + } + my $HARDWARE_NAME="$hdw *"; + my $DEVICE_NAME="\@$dev*"; + $$in = " "; return 0 unless run_stp_pipe($self,$pipe,$in,$out,$err,$tview); $$in = " foreach name [get_hardware_names] { - if { [string match \"*${HARDWARE_NAME}*\" \$name] } { - set hardware_name \$name\n - } - } - puts \"\\nhardware_name is \$hardware_name\" - foreach name [get_device_names -hardware_name \$hardware_name] { - if { [string match \"*$DEVICE_NAME*\" \$name] } { - set chip_name \$name - } - } - puts \"device_name is \$chip_name\\n\"; - open_device -hardware_name \$hardware_name -device_name \$chip_name\n"; - return 0 unless run_stp_pipe($self,$pipe,$in,$out,$err,$tview); - + if { [string match \"*${HARDWARE_NAME}*\" \$name] } { + set hardware_name \$name\n + } + } + puts \"\\nhardware_name is \$hardware_name\" + foreach name [get_device_names -hardware_name \$hardware_name] { + if { [string match \"*$DEVICE_NAME*\" \$name] } { + set chip_name \$name + } + } + puts \"device_name is \$chip_name\\n\"; + open_device -hardware_name \$hardware_name -device_name \$chip_name\n"; + return 0 unless run_stp_pipe($self,$pipe,$in,$out,$err,$tview); return 1; } sub close_stp{ - my ($self,$pipe,$tview,$in, $out, $err)=@_; - $$in = + my ($self,$pipe,$tview,$in, $out, $err)=@_; + $$in = "device_unlock close_device exit "; - pump $$pipe while (length $$in); - finish $$pipe; + pump $$pipe while (length $$in); + finish $$pipe; } - sub stp_jtag_vir { - my ($index,$ir)=@_; - my $hex = sprintf("%X", $ir); - my $in = + my ($index,$ir)=@_; + my $hex = sprintf("%X", $ir); + my $in = "device_lock -timeout 10000 device_virtual_ir_shift -instance_index $index -ir_value $hex -no_captured_ir_value catch {device_unlock} "; -return $in; +return $in; } - sub stp_jtag_vdr{ - my ($index,$dat,$width)=@_; - my $digits= $width>>2; - my $hex = sprintf("%0${digits}X", $dat); - my $in= + my ($index,$dat,$width)=@_; + my $digits= $width>>2; + my $hex = sprintf("%0${digits}X", $dat); + my $in= "device_lock -timeout 10000 set data [device_virtual_dr_shift -dr_value $hex -instance_index $index -length $width -value_in_hex] catch {device_unlock} puts R:\$data:R "; - return $in; + return $in; } - sub run_stp_jtag_scaner{ - my ($self,$tview,$tv_ref,$pipe,$in, $out, $err)=@_; - - my $num = $self->object_get_attribute('CTRL','UART_NUM'); - - - my @tviews=@{$tv_ref}; - - for (my $i=0; $i<$num; $i+=1){ - my $index= $self->object_get_attribute("CTRL","INDEX_$i"); - next if (!defined $index); - - - - my $txt= $self->object_get_attribute("SEND","TXT_$index"); - my $send_char =0; - my $l=length $txt; - if ($l){ - $send_char = substr $txt, 0,1; - $send_char = ord($send_char); #convert a character to a number - $txt = substr $txt, 1,$l; - $self->object_add_attribute("SEND","TXT_$index",$txt ); - } - - - - #select instruction - $$in=stp_jtag_vir ($index,UART_UPDATE_WB_RD_DATA); - return unless run_stp_pipe($self,$pipe,$in,$out,$err,$tview); - - - #read uart reg 0 - my $str=stp_jtag_vdr ($index,$send_char,32); - $$in=$str; - nop(); - return unless run_stp_pipe($self,$pipe,$in,$out,$err,$tview); - nop(); - my ($tmp,$hex)= sscanf("%sR:%s:R",$$out); - #print "capture $hex\n"; - my $char= substr($hex, -2); - #print "char = $char\n"; - if($char ne '00'){ - $char =hex_to_ascii($char); - add_info($tviews[$i],$char) if(defined $tviews[$i]); - } - } + my ($self,$tview,$tv_ref,$pipe,$in, $out, $err)=@_; + my $num = $self->object_get_attribute('CTRL','UART_NUM'); + my @tviews=@{$tv_ref}; + for (my $i=0; $i<$num; $i+=1){ + my $index= $self->object_get_attribute("CTRL","INDEX_$i"); + next if (!defined $index); + my $txt= $self->object_get_attribute("SEND","TXT_$index"); + my $send_char =0; + my $l=length $txt; + if ($l){ + $send_char = substr $txt, 0,1; + $send_char = ord($send_char); #convert a character to a number + $txt = substr $txt, 1,$l; + $self->object_add_attribute("SEND","TXT_$index",$txt ); + } + #select instruction + $$in=stp_jtag_vir ($index,UART_UPDATE_WB_RD_DATA); + return unless run_stp_pipe($self,$pipe,$in,$out,$err,$tview); + #read uart reg 0 + my $str=stp_jtag_vdr ($index,$send_char,32); + $$in=$str; + nop(); + return unless run_stp_pipe($self,$pipe,$in,$out,$err,$tview); + nop(); + my ($tmp,$hex)= sscanf("%sR:%s:R",$$out); + #print "capture $hex\n"; + my $char= substr($hex, -2); + #print "char = $char\n"; + if($char ne '00'){ + $char =hex_to_ascii($char); + add_info($tviews[$i],$char) if(defined $tviews[$i]); + } + } } - ############### -# xsct +# xsct ############## - use constant UPDATE_INDEX => "01"; use constant UPDATE_IR => "02"; use constant UPDATE_DAT => "04"; - #USER1 000010 Access user-defined register 1. #USER2 000011 Access user-defined register 2. #USER3 100010 Access user-defined register 3. #USER4 100011 Access user-defined register 4 - sub run_xsct_pipe{ - my ($self,$pipe,$in,$out,$err,$tview)=@_; - $$out=''; - $$in .= "puts done\n"; - - pump $$pipe while (length $$in); + my ($self,$pipe,$in,$out,$err,$tview)=@_; + $$out=''; + $$in .= "puts done\n"; + pump $$pipe while (length $$in); until ($$out =~ /done/ || (length $$err)){ - - pump $$pipe; - refresh_gui(); - } + pump $$pipe; + refresh_gui(); + } if(length $$err){ - add_colored_info($tview,"Got an Error: $$err\n",'red'); - $self->object_add_attribute("CTRL","DISCONNECT",1); - set_gui_status($self,"ON-OFF",0); - return 0; + add_colored_info($tview,"Got an Error: $$err\n",'red'); + $self->object_add_attribute("CTRL","DISCONNECT",1); + set_gui_status($self,"ON-OFF",0); + return 0; } refresh_gui(); - - return 1; + return 1; } - sub start_xsct{ - my ($self,$pipe,$tview,$in, $out, $err)=@_; - - - my $xsct = which('xsct'); - - #check if $xsct exits - unless(-f $xsct){ - add_colored_info($tview,"Error xsct not found. Please add the path to xilinx/SDK/bin to your \$PATH environment\n",'red'); - return 0; - } - my @cat = ( $xsct ); - my $r; - - $$pipe =start \@cat, $in, $out, $err or $r=$?; - if(defined $r){ - add_colored_info($tview,"XSCT got an Error: $r\n",'red'); - return 0; - } - - - my $target= $self->object_get_attribute('CTRL','JTAG_TARGET'); - - $$in = ""; + my ($self,$pipe,$tview,$in, $out, $err)=@_; + my $xsct = which('xsct'); + #check if $xsct exits + unless(-f $xsct){ + add_colored_info($tview,"Error xsct not found. Please add the path to xilinx/SDK/bin to your \$PATH environment\n",'red'); + return 0; + } + my @cat = ( $xsct ); + my $r; + $$pipe =start \@cat, $in, $out, $err or $r=$?; + if(defined $r){ + add_colored_info($tview,"XSCT got an Error: $r\n",'red'); + return 0; + } + my $target= $self->object_get_attribute('CTRL','JTAG_TARGET'); + $$in = ""; return 0 unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); $$in = "set jseq [jtag sequence]\n connect\n jtag targets $target\n"; return 0 unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); - return 1; } - - - sub close_xsct{ - my ($self,$pipe,$tview,$in, $out, $err)=@_; - $$in = "exit\n"; - pump $$pipe while (length $$in); - finish $$pipe; + my ($self,$pipe,$tview,$in, $out, $err)=@_; + $$in = "exit\n"; + pump $$pipe while (length $$in); + finish $$pipe; } - sub jtag_reorder{ - my ( $string_in ) =@_; - my @chars =( $string_in =~ m/../g );#split a string into chunks of two characters - return join("", reverse @chars); + my ( $string_in ) =@_; + my @chars =( $string_in =~ m/../g );#split a string into chunks of two characters + return join("", reverse @chars); } - - sub xsct_send_to_jtag{ - my ($hex,$width,$chain) =@_; - my $siz = $width+4; - #print "$chain\n"; - my $str="\$jseq clear + my ($hex,$width,$chain) =@_; + my $siz = $width+4; + #print "$chain\n"; + my $str="\$jseq clear \$jseq irshift -state IDLE -hex 6 $chain \$jseq drshift -state IDLE -hex $siz $hex \$jseq run @@ -698,186 +553,146 @@ sub xsct_send_to_jtag{ return $str; } - sub xsct_send_capture_jtag { - my ($hex,$width,$chain) =@_; - my $siz = $width+4; - my $str="\$jseq clear -\$jseq irshift -state IDLE -hex 6 $chain -\$jseq drshift -state IDLE -capture -hex $siz $hex + my ($hex,$width,$chain) =@_; + my $siz = $width+4; + my $str="\$jseq clear +\$jseq irshift -state IDLE -hex 6 $chain +\$jseq drshift -state IDLE -capture -hex $siz $hex set data [\$jseq run] puts R:\$data:R -"; -return $str; +"; +return $str; } - sub xsct_jtag_vdr{ - my ($dat,$width,$chain)=@_; - my $digits= $width>>2; - my $hex = UPDATE_DAT.sprintf("%0${digits}X", $dat); - $hex=jtag_reorder($hex); - return xsct_send_capture_jtag($hex,$width,$chain); + my ($dat,$width,$chain)=@_; + my $digits= $width>>2; + my $hex = UPDATE_DAT.sprintf("%0${digits}X", $dat); + $hex=jtag_reorder($hex); + return xsct_send_capture_jtag($hex,$width,$chain); } - sub xsct_jtag_vir { - my ($ir,$width,$chain)=@_; - my $digits= $width>>2; - my $hex = UPDATE_IR.sprintf("%0${digits}X", $ir); - $hex=jtag_reorder($hex); - return xsct_send_to_jtag($hex,$width,$chain); + my ($ir,$width,$chain)=@_; + my $digits= $width>>2; + my $hex = UPDATE_IR.sprintf("%0${digits}X", $ir); + $hex=jtag_reorder($hex); + return xsct_send_to_jtag($hex,$width,$chain); } sub xsct_jtag_vindex { - my ($index,$width,$chain)=@_; - my $digits= $width>>2; - my $hex = UPDATE_INDEX.sprintf("%0${digits}X", $index); - $hex=jtag_reorder($hex); - return xsct_send_to_jtag($hex,$width,$chain); + my ($index,$width,$chain)=@_; + my $digits= $width>>2; + my $hex = UPDATE_INDEX.sprintf("%0${digits}X", $index); + $hex=jtag_reorder($hex); + return xsct_send_to_jtag($hex,$width,$chain); } sub run_xsct_jtag_scaner{ - my ($self,$tview,$tv_ref,$pipe,$in, $out, $err)=@_; - - my $num = $self->object_get_attribute('CTRL','UART_NUM'); - my $chain= $self->object_get_attribute('CTRL','JTAG_CHAIN'); - my $chain_code= - ($chain==1)? '02': - ($chain==2)? '03': - ($chain==3)? '22': - '23'; - - my @tviews=@{$tv_ref}; - - for (my $i=0; $i<$num; $i+=1){ - my $index= $self->object_get_attribute("CTRL","INDEX_$i"); - next if (!defined $index); - my $txt= $self->object_get_attribute("SEND","TXT_$index"); - my $send_char =0; - my $l=length $txt; - if ($l){ - $send_char = substr $txt, 0,1; - $send_char = ord($send_char); #convert a character to a number - $txt = substr $txt, 1,$l; - $self->object_add_attribute("SEND","TXT_$index",$txt ); - } - - - #select index - #print"select index\n"; - $$in=xsct_jtag_vindex ($index,32,$chain_code); - return unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); - - - #select instruction - #print"select instruction\n"; - $$in=xsct_jtag_vir (UART_UPDATE_WB_RD_DATA,32,$chain_code); - return unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); - - - #read uart reg 0 - #print"read reg 0\n"; - my $str=xsct_jtag_vdr ($send_char,32,$chain_code); - $$in=$str; - nop(); - return unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); - nop(); - my ($hex)= sscanf("R:%s:R",$$out); - my $char= substr $hex, 0, 2; - if($char ne '00'){ - $char =hex_to_ascii(substr $hex, 0, 2); - add_info($tviews[$i],$char) if(defined $tviews[$i]); - } - - - - } + my ($self,$tview,$tv_ref,$pipe,$in, $out, $err)=@_; + my $num = $self->object_get_attribute('CTRL','UART_NUM'); + my $chain= $self->object_get_attribute('CTRL','JTAG_CHAIN'); + my $chain_code= + ($chain==1)? '02': + ($chain==2)? '03': + ($chain==3)? '22': + '23'; + my @tviews=@{$tv_ref}; + for (my $i=0; $i<$num; $i+=1){ + my $index= $self->object_get_attribute("CTRL","INDEX_$i"); + next if (!defined $index); + my $txt= $self->object_get_attribute("SEND","TXT_$index"); + my $send_char =0; + my $l=length $txt; + if ($l){ + $send_char = substr $txt, 0,1; + $send_char = ord($send_char); #convert a character to a number + $txt = substr $txt, 1,$l; + $self->object_add_attribute("SEND","TXT_$index",$txt ); + } + #select index + #print"select index\n"; + $$in=xsct_jtag_vindex ($index,32,$chain_code); + return unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); + #select instruction + #print"select instruction\n"; + $$in=xsct_jtag_vir (UART_UPDATE_WB_RD_DATA,32,$chain_code); + return unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); + #read uart reg 0 + #print"read reg 0\n"; + my $str=xsct_jtag_vdr ($send_char,32,$chain_code); + $$in=$str; + nop(); + return unless run_xsct_pipe($self,$pipe,$in,$out,$err,$tview); + nop(); + my ($hex)= sscanf("R:%s:R",$$out); + my $char= substr $hex, 0, 2; + if($char ne '00'){ + $char =hex_to_ascii(substr $hex, 0, 2); + add_info($tviews[$i],$char) if(defined $tviews[$i]); + } + } } - - - ############ -# main +# main ############ - - - sub uart_main { - my $self = __PACKAGE__->new(); - set_gui_status($self,"ideal",0); - my $window = def_popwin_size (85,85,'UART Terminal','percent'); - my ($sw,$tview) =create_txview();# a textveiw for showing the info, erro messages etc - my $ctrl= ctrl_boxes($self,$tview); - my ($rsv,$tv_ref) = receive_boxes($self); - my ($send,$send_tv) = sender_box($self,$tview); - - my $v1 = gen_vpaned ($ctrl,0.3,$send); - my $v2 = gen_vpaned ($v1,0.5,$sw); - my $h1 = gen_hpaned ($rsv,0.55,$v2); - - my ($pipe,$in, $out, $err); - my $counter=5; - #check soc status every 0.5 second. referesh device table if there is any changes - Glib::Timeout->add (10, sub{ + my $self = __PACKAGE__->new(); + set_gui_status($self,"ideal",0); + my $window = def_popwin_size (85,85,'UART Terminal','percent'); + my ($sw,$tview) =create_txview();# a textveiw for showing the info, erro messages etc + my $ctrl= ctrl_boxes($self,$tview); + my ($rsv,$tv_ref) = receive_boxes($self); + my ($send,$send_tv) = sender_box($self,$tview); + my $v1 = gen_vpaned ($ctrl,0.3,$send); + my $v2 = gen_vpaned ($v1,0.5,$sw); + my $h1 = gen_hpaned ($rsv,0.55,$v2); + my ($pipe,$in, $out, $err); + my $counter=5; + #check soc status every 0.5 second. referesh device table if there is any changes + Glib::Timeout->add (10, sub{ my ($state,$timeout)= get_gui_status($self); - if ($timeout>0){ $timeout--; - set_gui_status($self,$state,$timeout); + set_gui_status($self,$state,$timeout); } - elsif( $state ne "ideal" ){ + elsif( $state ne "ideal" ){ if($state eq 'ref_all') { - $rsv->destroy(); - ($rsv,$tv_ref) = receive_boxes($self); - $h1-> pack1($rsv, TRUE, TRUE); - } - - - + $rsv->destroy(); + ($rsv,$tv_ref) = receive_boxes($self); + $h1-> pack1($rsv, TRUE, TRUE); + } $ctrl->destroy(); $send->destroy(); - - ($send,$send_tv) = sender_box($self,$tview); + ($send,$send_tv) = sender_box($self,$tview); $ctrl= ctrl_boxes($self,$tview); - $v1-> pack1($ctrl, TRUE, TRUE); $v1-> pack2($send, TRUE, TRUE); $h1->show_all(); - set_gui_status($self,"ideal",0); - if($state eq 'ON-OFF') { - my $uname= $self->object_get_attribute('CTRL','UART_NAME'); - my $pipe_name = ($uname eq 'ProNoC_XILINX_UART') ? 'xsct' : 'stp'; - check_jtag_connect ($self,\$pipe,$tview,\$in, \$out, \$err,$pipe_name); - my $st =$self->object_get_attribute("CTRL","RUN"); - $counter=5 if ($st eq 'OFF'); - #print "ON-OFF\n"; + set_gui_status($self,"ideal",0); + if($state eq 'ON-OFF') { + my $uname= $self->object_get_attribute('CTRL','UART_NAME'); + my $pipe_name = ($uname eq 'ProNoC_XILINX_UART') ? 'xsct' : 'stp'; + check_jtag_connect ($self,\$pipe,$tview,\$in, \$out, \$err,$pipe_name); + my $st =$self->object_get_attribute("CTRL","RUN"); + $counter=5 if ($st eq 'OFF'); + #print "ON-OFF\n"; } - # print "ref\n"; - - - } + # print "ref\n"; + } my $st =$self->object_get_attribute("CTRL","RUN"); $counter-- if ($st eq 'ON' && $counter>0); if($counter ==0 ){ - my $uname= $self->object_get_attribute('CTRL','UART_NAME'); - run_xsct_jtag_scaner($self,$tview,$tv_ref,\$pipe,\$in, \$out, \$err) if($uname eq 'ProNoC_XILINX_UART' ); - run_stp_jtag_scaner($self,$tview,$tv_ref,\$pipe,\$in, \$out, \$err) if($uname eq 'ProNoC_ALTERA_UART' ); + my $uname= $self->object_get_attribute('CTRL','UART_NAME'); + run_xsct_jtag_scaner($self,$tview,$tv_ref,\$pipe,\$in, \$out, \$err) if($uname eq 'ProNoC_XILINX_UART' ); + run_stp_jtag_scaner($self,$tview,$tv_ref,\$pipe,\$in, \$out, \$err) if($uname eq 'ProNoC_ALTERA_UART' ); } - return TRUE; - + return TRUE; } ); - - - $window->add($h1); - $window->show_all(); - return $window; -} - - - - - - -1; + $window->add($h1); + $window->show_all(); + return $window; +} +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/verilog_gen.pl b/mpsoc/perl_gui/lib/perl/verilog_gen.pl index d6c506a..fa4514b 100755 --- a/mpsoc/perl_gui/lib/perl/verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/verilog_gen.pl @@ -1,101 +1,77 @@ use constant::boolean; - use lib 'lib/perl'; - use strict; use warnings; - - use FindBin; use lib $FindBin::Bin; - use soc; use ip; use ip_gen; use Cwd; - - - - ###################### # soc_generate_verilog ##################### - -sub soc_generate_verilog{ - my ($soc,$sw_path,$txview)= @_; - my $soc_name=$soc->object_get_attribute('soc_name'); - #my $top_ip=ip_gen->ip_gen_new(); - my $top_ip=ip_gen->top_gen_new(); - if(!defined $soc_name){$soc_name='soc'}; - - my @instances=$soc->soc_get_all_instances(); - my $io_sim_v; - my $top_io_short; - my $core_id= $soc->object_get_attribute('global_param','CORE_ID'); - $core_id= 0 if(!defined $core_id); - my $param_as_in_v_all="\tparameter\tCORE_ID=$core_id, +sub soc_generate_verilog{ + my ($soc,$sw_path,$txview)= @_; + my $soc_name=$soc->object_get_attribute('soc_name'); + #my $top_ip=ip_gen->ip_gen_new(); + my $top_ip=ip_gen->top_gen_new(); + if(!defined $soc_name){$soc_name='soc'}; + my @instances=$soc->soc_get_all_instances(); + my $io_sim_v; + my $top_io_short; + my $core_id= $soc->object_get_attribute('global_param','CORE_ID'); + $core_id= 0 if(!defined $core_id); + my $param_as_in_v_all="\tparameter\tCORE_ID=$core_id, \tparameter\tSW_LOC=\"$sw_path\""; - - - my $system_v_all=""; - my $param_pass_v_all="\t\t.CORE_ID(CORE_ID),\n\t\t.SW_LOC(SW_LOC)"; - my $body_v; - - my ($param_v_all, $local_param_v_all, $wire_def_v_all, $inst_v_all, $plugs_assign_v_all, $sockets_assign_v_all,$io_full_v_all,$top_io_pass_all,$io_sim_v_all); - my $top_io_short_all="\tjtag_debug_reset_in"; - my $top_io_full_all="\tinput \tjtag_debug_reset_in;\n"; - my $wires=soc->new_wires(); - my $intfc=interface->interface_new(); - - - foreach my $id (@instances){ - my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, - $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires); - my $inst = $soc->soc_get_instance_name($id); - add_text_to_string(\$body_v,"/*******************\n*\n*\t$inst\n*\n*\n*********************/\n"); - add_text_to_string(\$param_as_in_v_all,",\n$param_as_in_v") if(defined($param_as_in_v)); - add_text_to_string(\$local_param_v_all,"$local_param_v\n") if(defined($local_param_v)); - add_text_to_string(\$param_pass_v_all,",\n$param_pass_v") if(defined($param_pass_v)); - add_text_to_string(\$system_v_all,"$system_v\n") if(defined($system_v)); - add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); - add_text_to_string(\$inst_v_all,$inst_v) if(defined($inst_v)); - add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); - add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); - add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); - add_text_to_string(\$top_io_full_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); - $top_io_pass_all = (defined $top_io_pass_all )? "$top_io_pass_all,\n$top_io_pass" : $top_io_pass if(defined($top_io_pass)); - $io_sim_v_all = (defined $io_sim_v_all )? "$io_sim_v_all,\n$io_sim_v" : $io_sim_v if(defined($io_sim_v)); - $top_io_short_all = (defined $top_io_short_all)? "$top_io_short_all,\n$top_io_short" : $top_io_short if(defined($top_io_short)); - - - #print "$param_v $local_param_v $wire_def_v $inst_v $plugs_assign_v $sockets_assign_v $io_full_v"; - - } - my ($addr_map,$addr_localparam,$module_addr_localparam)= generate_address_cmp($soc,$wires); - - #add functions - my $dir = Cwd::getcwd(); - open my $file1, "<", "$dir/lib/verilog/functions.v" or die; - my $functions_all=''; - while (my $f1 = readline ($file1)) { - $functions_all="$functions_all $f1 "; - } - close($file1); - my $unused_wiers_v=assign_unconnected_wires($wires,$intfc); - - $unused_wiers_v="" if(!defined $unused_wiers_v); - $sockets_assign_v_all="" if(!defined $sockets_assign_v_all); - -my $has_ni =check_for_ni($soc); -my $import = ($has_ni)? "\n\t`NOC_CONF\n" : ""; -my $tscale = ($has_ni)? "`include \"pronoc_def.v\"\n" : "`timescale 1ns / 1ps\n"; - -my $global_localparam=get_golal_param_v(); - my $soc_v = (defined $param_as_in_v_all )? "$tscale module $soc_name #(\n $param_as_in_v_all\n)(\n$io_sim_v_all\n);\n$import\n": "$tscale module $soc_name (\n$io_sim_v_all\n);\n $import\n"; - $soc_v = $soc_v." -$functions_all + my $param_pass_v_all="\t\t.CORE_ID(CORE_ID),\n\t\t.SW_LOC(SW_LOC)"; + my $body_v; + my ($param_v_all, $local_param_v_all, $wire_def_v_all, $inst_v_all, $plugs_assign_v_all, $sockets_assign_v_all,$io_full_v_all,$top_io_pass_all,$io_sim_v_all); + my $top_io_short_all="\tjtag_debug_reset_in"; + my $top_io_full_all="\tinput \tjtag_debug_reset_in;\n"; + my $wires=soc->new_wires(); + my $intfc=interface->interface_new(); + foreach my $id (@instances){ + my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, + $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires); + my $inst = $soc->soc_get_instance_name($id); + add_text_to_string(\$body_v,"/*******************\n*\n*\t$inst\n*\n*\n*********************/\n"); + add_text_to_string(\$param_as_in_v_all,",\n$param_as_in_v") if(defined($param_as_in_v)); + add_text_to_string(\$local_param_v_all,"$local_param_v\n") if(defined($local_param_v)); + add_text_to_string(\$param_pass_v_all,",\n$param_pass_v") if(defined($param_pass_v)); + add_text_to_string(\$system_v_all,"$system_v\n") if(defined($system_v)); + add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); + add_text_to_string(\$inst_v_all,$inst_v) if(defined($inst_v)); + add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); + add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); + add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); + add_text_to_string(\$top_io_full_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); + $top_io_pass_all = (defined $top_io_pass_all )? "$top_io_pass_all,\n$top_io_pass" : $top_io_pass if(defined($top_io_pass)); + $io_sim_v_all = (defined $io_sim_v_all )? "$io_sim_v_all,\n$io_sim_v" : $io_sim_v if(defined($io_sim_v)); + $top_io_short_all = (defined $top_io_short_all)? "$top_io_short_all,\n$top_io_short" : $top_io_short if(defined($top_io_short)); + #print "$param_v $local_param_v $wire_def_v $inst_v $plugs_assign_v $sockets_assign_v $io_full_v"; + } + my ($addr_map,$addr_localparam,$module_addr_localparam)= generate_address_cmp($soc,$wires); + #add functions + my $dir = Cwd::getcwd(); + open my $file1, "<", "$dir/lib/verilog/functions.v" or die; + my $functions_all=''; + while (my $f1 = readline ($file1)) { + $functions_all="$functions_all $f1 "; + } + close($file1); + my $unused_wiers_v=assign_unconnected_wires($wires,$intfc); + $unused_wiers_v="" if(!defined $unused_wiers_v); + $sockets_assign_v_all="" if(!defined $sockets_assign_v_all); + my $has_ni =check_for_ni($soc); + my $import = ($has_ni)? "\n\t`NOC_CONF\n" : ""; + my $tscale = ($has_ni)? "`include \"pronoc_def.v\"\n" : "`timescale 1ns / 1ps\n"; + my $global_localparam=get_golal_param_v(); + my $soc_v = (defined $param_as_in_v_all )? "$tscale module $soc_name #(\n $param_as_in_v_all\n)(\n$io_sim_v_all\n);\n$import\n": "$tscale module $soc_name (\n$io_sim_v_all\n);\n $import\n"; + $soc_v = $soc_v." +$functions_all $system_v_all $global_localparam $local_param_v_all @@ -109,1234 +85,913 @@ sub soc_generate_verilog{ $sockets_assign_v_all $addr_map endmodule - "; - - - $soc->object_add_attribute('top_ip',undef,$top_ip); - #print @assigned_wires; - - #generate top module - my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($soc); - $top_io_short_all=(defined $top_io_short_all)? "$top_io_short_all,\n$clk_io_sim" : $clk_io_sim; - $top_io_full_all=$top_io_full_all."\n$clk_io_full"; + $soc->object_add_attribute('top_ip',undef,$top_ip); + #print @assigned_wires; + #generate top module + my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($soc); + $top_io_short_all=(defined $top_io_short_all)? "$top_io_short_all,\n$clk_io_sim" : $clk_io_sim; + $top_io_full_all=$top_io_full_all."\n$clk_io_full"; $top_io_pass_all=$top_io_pass_all.",\n$clk_assigned_port"; my %jtag_info= get_soc_jtag_v($soc,$soc_name,$txview); - my $jtag_v=add_jtag_ctrl (\%jtag_info,$txview); + my $jtag_v=add_jtag_ctrl (\%jtag_info,$txview); my @chains = (sort { $b <=> $a } keys %jtag_info); - $soc->object_add_attribute('JTAG','M_CHAIN',$chains[0]); - - my $top_v = (defined $param_as_in_v_all )? "module ${soc_name}_top #(\n $param_as_in_v_all\n)(\n$top_io_short_all\n);\n": "module ${soc_name}_top (\n $top_io_short_all\n);\n $import "; - - - #my $ins= gen_soc_instance_v($soc,$soc_name,$param_pass_v,$txview); - - my $pass = (defined $param_pass_v_all )? "#(\n$param_pass_v_all\n\t)\n": ""; - - - $top_v=$top_v." -$functions_all + $soc->object_add_attribute('JTAG','M_CHAIN',$chains[0]); + my $top_v = (defined $param_as_in_v_all )? "module ${soc_name}_top #(\n $param_as_in_v_all\n)(\n$top_io_short_all\n);\n": "module ${soc_name}_top (\n $top_io_short_all\n);\n $import "; + #my $ins= gen_soc_instance_v($soc,$soc_name,$param_pass_v,$txview); + my $pass = (defined $param_pass_v_all )? "#(\n$param_pass_v_all\n\t)\n": ""; + $top_v=$top_v." +$functions_all $global_localparam $local_param_v_all $top_io_full_all $clk_set -$jtag_v -\t${soc_name}${pass}\tthe_${soc_name} +$jtag_v +\t${soc_name}${pass}\tthe_${soc_name} \t( $top_io_pass_all \t); endmodule "; - - my ($readme,$prog)=gen_system_info($soc,$param_as_in_v_all); - return ("$soc_v",$top_v,$readme,$prog); - - -} - - - + my ($readme,$prog)=gen_system_info($soc,$param_as_in_v_all); + return ("$soc_v",$top_v,$readme,$prog); +} sub append_to_hash { - my ($ref,$att1,$att2,$data)=@_; - my %hash= %{$ref}; - my $r = $hash{$att1}{$att2}; - my @array= (defined $r)? @{$r} : (); - push (@array,$data); - $hash{$att1}{$att2} = \@array; - return %hash; + my ($ref,$att1,$att2,$data)=@_; + my %hash= %{$ref}; + my $r = $hash{$att1}{$att2}; + my @array= (defined $r)? @{$r} : (); + push (@array,$data); + $hash{$att1}{$att2} = \@array; + return %hash; } - sub get_soc_jtag_v{ - my ($soc,$soc_name,$txview)=@_; - - my $processor_en=0; - #my $jtag_insts=""; - #my $altera_jtag_ctrl=0; - #my $xilinx_jtag_ctrl=0; - #my $xilinx_jtag_ctrl_in; - #my $xilinx_jtag_ctrl_out; - my $jtag_inst_name=""; - - - my $top=$soc->soc_get_top(); - my @intfcs=$top->top_get_intfc_list(); - - my %jtag_info; - - foreach my $intfc (@intfcs){ - if( $intfc =~ /socket:jtag_to_wb\[/){ #check JTAG connect parameter. if it is XILINX then connect it to jtag tap - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - my $JTAG_CONNECT=$soc->soc_get_module_param_value ($id,'JTAG_CONNECT'); - $JTAG_CONNECT=remove_all_white_spaces($JTAG_CONNECT); - if($JTAG_CONNECT =~ /XILINX_JTAG_WB/){ - my $chain=$soc->soc_get_module_param_value ($id,'JTAG_CHAIN'); - my $index=$soc->soc_get_module_param_value ($id,'JTAG_INDEX'); - $jtag_inst_name= $soc->soc_get_instance_name($id); - my %params = $soc->soc_get_module_param($id); - my $new_range = add_instantc_name_to_parameters(\%params,$id,$range); - %jtag_info=append_to_hash (\%jtag_info,$chain,'wire',"\twire [ $new_range ] ${p};"); - # $jtag_def=$jtag_def."\twire [ $new_range ] ${p};\n"; - if($type eq 'input'){ - # $jtag_insts=$jtag_insts."$id XILINX JTAG,"; - %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id XILINX JTAG"); - # $xilinx_jtag_ctrl++; - %jtag_info=append_to_hash (\%jtag_info,$chain,'xilinx_num',1); - # $xilinx_jtag_ctrl_in=(defined $xilinx_jtag_ctrl_in)? "$xilinx_jtag_ctrl_in,$p" : "$p"; - %jtag_info=append_to_hash (\%jtag_info,$chain,'input',$p); - %jtag_info=check_jtag_indexs(\%jtag_info,$chain,$index,$txview,$jtag_inst_name,0); - #print "\%jtag_info=check_jtag_indexs(\%jtag_info,$chain,$index,$txview,$jtag_inst_name);\n" - - }else { - # $xilinx_jtag_ctrl_out=(defined $xilinx_jtag_ctrl_out)? "$xilinx_jtag_ctrl_out,$p" : "$p"; - %jtag_info=append_to_hash (\%jtag_info,$chain,'output',$p); - } - }#'"XILINX_JTAG_WB"' - - elsif($JTAG_CONNECT eq '"ALTERA_JTAG_WB"'){ - my $index=$soc->soc_get_module_param_value ($id,'JTAG_INDEX'); - if($type eq 'input'){ - # $jtag_insts=$jtag_insts."$id ALTERA JTAG,"; - %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id ALTERA JTAG"); - %jtag_info=append_to_hash (\%jtag_info,0,'altera_num',1); - %jtag_info=check_jtag_indexs(\%jtag_info,0,$index,$txview,$jtag_inst_name,0); - # $altera_jtag_ctrl++; - - } - }#'"ALTERA_JTAG_WB"' - - } #$p - }#if - - } - #print Dumper \%jtag_info; - return %jtag_info; + my ($soc,$soc_name,$txview)=@_; + my $processor_en=0; + #my $jtag_insts=""; + #my $altera_jtag_ctrl=0; + #my $xilinx_jtag_ctrl=0; + #my $xilinx_jtag_ctrl_in; + #my $xilinx_jtag_ctrl_out; + my $jtag_inst_name=""; + my $top=$soc->soc_get_top(); + my @intfcs=$top->top_get_intfc_list(); + my %jtag_info; + foreach my $intfc (@intfcs){ + if( $intfc =~ /socket:jtag_to_wb\[/){ #check JTAG connect parameter. if it is XILINX then connect it to jtag tap + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + my $JTAG_CONNECT=$soc->soc_get_module_param_value ($id,'JTAG_CONNECT'); + $JTAG_CONNECT=remove_all_white_spaces($JTAG_CONNECT); + if($JTAG_CONNECT =~ /XILINX_JTAG_WB/){ + my $chain=$soc->soc_get_module_param_value ($id,'JTAG_CHAIN'); + my $index=$soc->soc_get_module_param_value ($id,'JTAG_INDEX'); + $jtag_inst_name= $soc->soc_get_instance_name($id); + my %params = $soc->soc_get_module_param($id); + my $new_range = add_instantc_name_to_parameters(\%params,$id,$range); + %jtag_info=append_to_hash (\%jtag_info,$chain,'wire',"\twire [ $new_range ] ${p};"); + # $jtag_def=$jtag_def."\twire [ $new_range ] ${p};\n"; + if($type eq 'input'){ + # $jtag_insts=$jtag_insts."$id XILINX JTAG,"; + %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id XILINX JTAG"); + # $xilinx_jtag_ctrl++; + %jtag_info=append_to_hash (\%jtag_info,$chain,'xilinx_num',1); + # $xilinx_jtag_ctrl_in=(defined $xilinx_jtag_ctrl_in)? "$xilinx_jtag_ctrl_in,$p" : "$p"; + %jtag_info=append_to_hash (\%jtag_info,$chain,'input',$p); + %jtag_info=check_jtag_indexs(\%jtag_info,$chain,$index,$txview,$jtag_inst_name,0); + #print "\%jtag_info=check_jtag_indexs(\%jtag_info,$chain,$index,$txview,$jtag_inst_name);\n" + }else { + # $xilinx_jtag_ctrl_out=(defined $xilinx_jtag_ctrl_out)? "$xilinx_jtag_ctrl_out,$p" : "$p"; + %jtag_info=append_to_hash (\%jtag_info,$chain,'output',$p); + } + }#'"XILINX_JTAG_WB"' + elsif($JTAG_CONNECT eq '"ALTERA_JTAG_WB"'){ + my $index=$soc->soc_get_module_param_value ($id,'JTAG_INDEX'); + if($type eq 'input'){ + # $jtag_insts=$jtag_insts."$id ALTERA JTAG,"; + %jtag_info=append_to_hash (\%jtag_info,0,'inst',"$id ALTERA JTAG"); + %jtag_info=append_to_hash (\%jtag_info,0,'altera_num',1); + %jtag_info=check_jtag_indexs(\%jtag_info,0,$index,$txview,$jtag_inst_name,0); + # $altera_jtag_ctrl++; + } + }#'"ALTERA_JTAG_WB"' + } #$p + }#if + } + #print Dumper \%jtag_info; + return %jtag_info; } - ################# -# gen_module_inst +# gen_module_inst ############### - sub get_io_nc_info { - my($soc,$port,$inst,$intfc_name,$id)=@_; - my $IO='no'; - my $NC='no'; - my($i_type,$i_name,$i_num) =split("[:\[ \\]]", $intfc_name); - if($i_type eq 'plug'){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$i_name,$i_num); - if($connect_id eq 'IO'){ $IO='yes';} - if($connect_id eq 'NC'){ $NC='yes';} - } - if($i_type eq 'socket' && $i_name ne'wb_addr_map'){ - - my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$i_name,$i_num); - my %connected_plugs=%$ref1; - my %connected_plug_nums=%$ref2; - if(!%connected_plugs ){ - my ($s_type,$s_value,$s_connection_num)=$soc->soc_get_socket_of_instance($id,$i_name); - my $v=$soc->soc_get_module_param_value($id,$s_value); - if ( length( $v || '' )){ $IO='no';} else { - my $con= $soc->object_get_attribute("Unset-intfc" ,"$inst-$port"); - if(!defined $con){ $IO='yes';} - else{ - $IO='yes' if $con eq 'IO'; - } - } - } - } - - - - return ($IO ,$NC); + my($soc,$port,$inst,$intfc_name,$id)=@_; + my $IO='no'; + my $NC='no'; + my($i_type,$i_name,$i_num) =split("[:\[ \\]]", $intfc_name); + if($i_type eq 'plug'){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$i_name,$i_num); + if($connect_id eq 'IO'){ $IO='yes';} + if($connect_id eq 'NC'){ $NC='yes';} + } + if($i_type eq 'socket' && $i_name ne'wb_addr_map'){ + my ($ref1,$ref2)= $soc->soc_get_modules_plug_connected_to_socket($id,$i_name,$i_num); + my %connected_plugs=%$ref1; + my %connected_plug_nums=%$ref2; + if(!%connected_plugs ){ + my ($s_type,$s_value,$s_connection_num)=$soc->soc_get_socket_of_instance($id,$i_name); + my $v=$soc->soc_get_module_param_value($id,$s_value); + if ( length( $v || '' )){ $IO='no';} else { + my $con= $soc->object_get_attribute("Unset-intfc" ,"$inst-$port"); + if(!defined $con){ $IO='yes';} + else{ + $IO='yes' if $con eq 'IO'; + } + } + } + } + return ($IO ,$NC); } - - sub gen_module_inst { - my ($id,$soc,$top_ip,$intfc,$wires, $sim_only)=@_; - $sim_only = 0 if (!defined $sim_only); - my ($io_sim_v,$top_io_short,$param_as_in_v,$param_pass_v,$system_v); - my $top_io_pass; - my $src_io_short; - my $src_io_full=""; - my $module =$soc->soc_get_module($id); - my $module_name =$soc->soc_get_module_name($id); - my $category =$soc->soc_get_category($id); - - - my $inst = $soc->soc_get_instance_name($id); - my %params = $soc->soc_get_module_param($id); - my %params_type = $soc->soc_get_module_param_type($id); - - - - my $src_ip=$soc ->object_get_attribute('SOURCE_SET',"IP"); - my $ip = ip->lib_new (); - $ip->add_ip($src_ip) if defined $src_ip; - - - my @ports=$ip->ip_list_ports($category,$module); - my ($inst_v,$intfc_v,$plugs_assign_v,$sockets_assign_v); - my $wire_def_v=""; - my $io_full_v=""; - my $io_top_full_v=""; - $plugs_assign_v="\n"; - - - my $counter=0; - my @param_order=$soc->soc_get_instance_param_order($id); - - my ($param_v,$local_param_v,$instance_param_v)= gen_parameter_v(\%params,$id,$inst,$category,$module,$ip,\$param_as_in_v,\@param_order,$top_ip,\$param_pass_v,\%params_type); - - - - $top_ip->top_add_def_to_instance($id,'module',$module); - $top_ip->top_add_def_to_instance($id,'module_name',$module_name); - $top_ip->top_add_def_to_instance($id,'category',$category); - $top_ip->top_add_def_to_instance($id,'instance',$inst); - - # - my $assigned_ports=""; - - #module name - $inst_v=( defined $instance_param_v )? "$module_name #(\n": $module_name ; - #module parameters - $inst_v=( defined $instance_param_v)? "$inst_v $instance_param_v\n\t)": $inst_v; - #module instance name - $inst_v="$inst_v $inst \t(\n"; - #module ports - $counter=0; - foreach my $port (@ports){ - my ($type,$range,$intfc_name,$i_port)=$ip->ip_get_port($category,$module,$port); - my $assigned_port; - my($i_type,$i_name,$i_num) =split("[:\[ \\]]", $intfc_name); - - my ($IO ,$NC) =get_io_nc_info($soc,$port,$inst,$intfc_name,$id); - - - - if($NC eq 'yes'){ - - - } - elsif($IO eq 'yes' || !defined $i_type || !defined $i_name || !defined $i_num){ #its an IO port - if($i_port eq 'NC' ){ - $NC='yes'; - }else { - $i_name ='IO' if( !defined $i_name); - - - $assigned_port="$inst\_$port"; - $io_sim_v= (!defined $io_sim_v)? "\t$assigned_port" : "$io_sim_v,\n\t$assigned_port"; - my $new_range = add_instantc_name_to_parameters(\%params,$inst,$range); - my $r = (!defined $new_range)? 0 : (length ($new_range)>1 )? 1 : 0; - - my $str = (!defined $new_range) ? "\t\t\t" : - ($new_range =~ /:/ ) ? "\t[ $new_range ]\t" : "\t$new_range\t"; - - - my $port_def= "\t$type $str $assigned_port;\n"; - $io_full_v=$io_full_v.$port_def; - - if ($i_name eq 'RxD_sim' && $sim_only == 0){ - #do notthing - } - elsif($i_name eq 'enable'){ - $top_io_pass = (!defined $top_io_pass )? "\t\t.$assigned_port($assigned_port & jtag_cpu_en)" : "$top_io_pass,\n\t\t.$assigned_port($assigned_port & jtag_cpu_en)"; - $top_io_short= (!defined $top_io_short)? "\t$assigned_port" : "$top_io_short, \n\t$assigned_port"; - $io_top_full_v= $io_top_full_v.$port_def; - } elsif($i_name eq 'reset' || $i_name eq 'clk'){ - #connection done using get_top_clk_setting - $src_io_short= (!defined $src_io_short)? "\t$assigned_port" : "$src_io_short, \n\t$assigned_port"; - $src_io_full= $src_io_full.$port_def; - } elsif( $i_name eq 'jtag_to_wb' ){ - $top_io_pass = (!defined $top_io_pass )? "\t\t.$assigned_port($assigned_port)" : "$top_io_pass,\n\t\t.$assigned_port($assigned_port)"; - - }else{ - $top_io_short= (!defined $top_io_short)? "\t$assigned_port" : "$top_io_short, \n\t$assigned_port"; - $top_io_pass = (!defined $top_io_pass )? "\t\t.$assigned_port($assigned_port)" : "$top_io_pass,\n\t\t.$assigned_port($assigned_port)"; - $io_top_full_v= $io_top_full_v.$port_def; - } - - - - # $top_ip->ipgen_add_port($assigned_port, $new_range, $type ,$intfc_name,$i_port); - $top_ip->top_add_port($id,$assigned_port, $new_range, $type ,$intfc_name,$i_port); - } - - - } - else{ # port connected internally using interface - $assigned_port="$inst\_$i_type\_$i_name\_$i_num\_$i_port"; - - #create plug wires - my ($wire_string,$port_name)=generate_wire ($range,$assigned_port,$inst,\%params,$i_type,$i_name,$i_num,$i_port, $wires); - #add wire def if it is not defined before - - add_text_to_string(\$wire_def_v,$wire_string) if ($wire_def_v !~ /[\s\]]$port_name;/); - - - - if($i_type eq 'plug'){ - #read socket port name - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$i_name,$i_num); - my ($i_range,$t,$i_connect)=$intfc->get_port_info_of_plug($i_name,$i_port); - #my $connect_port= "socket_$i_name\_$i_num\_$i_connect"; - if(defined $connect_socket_num){ - my $connect_n=$soc->soc_get_instance_name($connect_id); - my $connect_port= "$connect_n\_socket_$i_name\_$connect_socket_num\_$i_connect"; - #connect plug port to socket port - my $new_range = add_instantc_name_to_parameters(\%params,$inst,$range); - my $r= (!defined $range)? 0 : (length ($range)>1 )? 1 :0; - - my $connect_port_range=($r==1)?"$connect_port\[$new_range\]":$connect_port; - - if($type eq 'input' ){ - $plugs_assign_v= "$plugs_assign_v \tassign $assigned_port = $connect_port_range;\n"; - $wires->wire_add($assigned_port,"connected",1); - - }else{ - $plugs_assign_v= "$plugs_assign_v \tassign $connect_port = $assigned_port;\n"; - $wires->wire_add($connect_port,"connected",1); - } - - - } - }#plug - else{ #socket - my ($s_type,$s_value,$s_connection_num)=$soc->soc_get_socket_of_instance($id,$i_name); - my $v=$soc->soc_get_module_param_value($id,$s_value); - my ($i_range,$t,$i_connect)=$intfc->get_port_info_of_socket($i_name,$i_port); - if ( length( $v || '' )) { - $v--; - my $name= $soc->soc_get_instance_name($id); - my $joint= "$name\_$i_type\_$i_name\_$v\_$i_port"; - - my ($wire_string,$port_name)=generate_wire ($i_range,"$name\_$i_type\_$i_name\_$v\_$i_port",$inst,\%params,$i_type,$i_name,$i_num,$i_port, $wires); - add_text_to_string(\$wire_def_v,$wire_string) if ($wire_def_v !~ /[\s\]]$port_name;/); - - for(my $i=$v-1; $i>=0; $i--) { - $joint= "$joint ,$name\_$i_type\_$i_name\_$i\_$i_port"; - #create socket wires - #create plug wires - my ($wire_string,$port_name)=generate_wire ($i_range,"$name\_$i_type\_$i_name\_$i\_$i_port",$inst,\%params,$i_type,$i_name,$i_num,$i_port, $wires); - add_text_to_string(\$wire_def_v,$wire_string) if ($wire_def_v !~ /[\s\]]$port_name;/); - - - - - - - } - $wires->wire_add($assigned_port,"connected",1) if($type eq 'input'); - if($type ne 'input' ){ - my @w=split('\s*,\s*',$joint); - foreach my $q (@w) { - $wires->wire_add($q,"connected",1); - } - - } - $joint=($v>0)? "\{ $joint\ }" : "$joint"; - my $text=($type eq 'input' )? "\tassign $assigned_port = $joint;\n": "\tassign $joint = $assigned_port;\n"; - - add_text_to_string(\$sockets_assign_v,$text); - } - - - - }#socket - - - } - - $i_name ='IO' if (!defined $i_name); - my $reset_jtag_ored = ($i_name eq 'reset')? '| jtag_system_reset' : ''; - my $reset_jtag_nc = ($i_name eq 'reset')? 'jtag_system_reset' : ''; - - - if (++$counter == scalar(@ports)){#last port def - - $inst_v=($NC eq 'yes')? "$inst_v\t\t.$port()\n": "$inst_v\t\t.$port($assigned_port)\n"; - $assigned_ports=($NC eq 'yes')? "$assigned_ports\t\t.$port($reset_jtag_nc)\n": "$assigned_ports\t\t.$port($assigned_port $reset_jtag_ored)\n"; - - } - else { - $inst_v=($NC eq 'yes')? "$inst_v\t\t.$port(),\n":"$inst_v\t\t.$port($assigned_port),\n"; - $assigned_ports=($NC eq 'yes')? "$assigned_ports\t\t.$port($reset_jtag_nc),\n":"$assigned_ports\t\t.$port($assigned_port $reset_jtag_ored),\n"; - } - - if($type ne 'input' && $NC ne 'yes' ){ - $wires->wire_add($assigned_port,"connected",1); - - } - - - - } - $inst_v="$inst_v\t);\n"; - - - - my $hdr =$ip->ip_get($category,$module,'system_v'); - if(defined $hdr){ - $hdr=replace_golb_var($hdr,\%params); - $system_v= "$system_v $hdr\n"; - } - - return ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v, $io_full_v, - $io_top_full_v,$io_sim_v,$top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass, - $src_io_short, $src_io_full); - #return ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$param_pass_v,$assigned_ports); - - -} - + my ($id,$soc,$top_ip,$intfc,$wires, $sim_only)=@_; + $sim_only = 0 if (!defined $sim_only); + my ($io_sim_v,$top_io_short,$param_as_in_v,$param_pass_v,$system_v); + my $top_io_pass; + my $src_io_short; + my $src_io_full=""; + my $module =$soc->soc_get_module($id); + my $module_name =$soc->soc_get_module_name($id); + my $category =$soc->soc_get_category($id); + my $inst = $soc->soc_get_instance_name($id); + my %params = $soc->soc_get_module_param($id); + my %params_type = $soc->soc_get_module_param_type($id); + my $src_ip=$soc ->object_get_attribute('SOURCE_SET',"IP"); + my $ip = ip->lib_new (); + $ip->add_ip($src_ip) if defined $src_ip; + my @ports=$ip->ip_list_ports($category,$module); + my ($inst_v,$intfc_v,$plugs_assign_v,$sockets_assign_v); + my $wire_def_v=""; + my $io_full_v=""; + my $io_top_full_v=""; + $plugs_assign_v="\n"; + my $counter=0; + my @param_order=$soc->soc_get_instance_param_order($id); + my ($param_v,$local_param_v,$instance_param_v)= gen_parameter_v(\%params,$id,$inst,$category,$module,$ip,\$param_as_in_v,\@param_order,$top_ip,\$param_pass_v,\%params_type); + $top_ip->top_add_def_to_instance($id,'module',$module); + $top_ip->top_add_def_to_instance($id,'module_name',$module_name); + $top_ip->top_add_def_to_instance($id,'category',$category); + $top_ip->top_add_def_to_instance($id,'instance',$inst); + # + my $assigned_ports=""; + #module name + $inst_v=( defined $instance_param_v )? "$module_name #(\n": $module_name ; + #module parameters + $inst_v=( defined $instance_param_v)? "$inst_v $instance_param_v\n\t)": $inst_v; + #module instance name + $inst_v="$inst_v $inst \t(\n"; + #module ports + $counter=0; + foreach my $port (@ports){ + my ($type,$range,$intfc_name,$i_port)=$ip->ip_get_port($category,$module,$port); + my $assigned_port; + my($i_type,$i_name,$i_num) =split("[:\[ \\]]", $intfc_name); + my ($IO ,$NC) =get_io_nc_info($soc,$port,$inst,$intfc_name,$id); + if($NC eq 'yes'){ + } + elsif($IO eq 'yes' || !defined $i_type || !defined $i_name || !defined $i_num){ #its an IO port + if($i_port eq 'NC' ){ + $NC='yes'; + }else { + $i_name ='IO' if( !defined $i_name); + $assigned_port="$inst\_$port"; + $io_sim_v= (!defined $io_sim_v)? "\t$assigned_port" : "$io_sim_v,\n\t$assigned_port"; + my $new_range = add_instantc_name_to_parameters(\%params,$inst,$range); + my $r = (!defined $new_range)? 0 : (length ($new_range)>1 )? 1 : 0; + my $str = (!defined $new_range) ? "\t\t\t" : + ($new_range =~ /:/ ) ? "\t[ $new_range ]\t" : "\t$new_range\t"; + my $port_def= "\t$type $str $assigned_port;\n"; + $io_full_v=$io_full_v.$port_def; + if ($i_name eq 'RxD_sim' && $sim_only == 0){ + #do notthing + } + elsif($i_name eq 'enable'){ + $top_io_pass = (!defined $top_io_pass )? "\t\t.$assigned_port($assigned_port & jtag_cpu_en)" : "$top_io_pass,\n\t\t.$assigned_port($assigned_port & jtag_cpu_en)"; + $top_io_short= (!defined $top_io_short)? "\t$assigned_port" : "$top_io_short, \n\t$assigned_port"; + $io_top_full_v= $io_top_full_v.$port_def; + } elsif($i_name eq 'reset' || $i_name eq 'clk'){ + #connection done using get_top_clk_setting + $src_io_short= (!defined $src_io_short)? "\t$assigned_port" : "$src_io_short, \n\t$assigned_port"; + $src_io_full= $src_io_full.$port_def; + } elsif( $i_name eq 'jtag_to_wb' ){ + $top_io_pass = (!defined $top_io_pass )? "\t\t.$assigned_port($assigned_port)" : "$top_io_pass,\n\t\t.$assigned_port($assigned_port)"; + }else{ + $top_io_short= (!defined $top_io_short)? "\t$assigned_port" : "$top_io_short, \n\t$assigned_port"; + $top_io_pass = (!defined $top_io_pass )? "\t\t.$assigned_port($assigned_port)" : "$top_io_pass,\n\t\t.$assigned_port($assigned_port)"; + $io_top_full_v= $io_top_full_v.$port_def; + } + # $top_ip->ipgen_add_port($assigned_port, $new_range, $type ,$intfc_name,$i_port); + $top_ip->top_add_port($id,$assigned_port, $new_range, $type ,$intfc_name,$i_port); + } + } + else{ # port connected internally using interface + $assigned_port="$inst\_$i_type\_$i_name\_$i_num\_$i_port"; + #create plug wires + my ($wire_string,$port_name)=generate_wire ($range,$assigned_port,$inst,\%params,$i_type,$i_name,$i_num,$i_port, $wires); + #add wire def if it is not defined before + add_text_to_string(\$wire_def_v,$wire_string) if ($wire_def_v !~ /[\s\]]$port_name;/); + if($i_type eq 'plug'){ + #read socket port name + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($id,$i_name,$i_num); + my ($i_range,$t,$i_connect)=$intfc->get_port_info_of_plug($i_name,$i_port); + #my $connect_port= "socket_$i_name\_$i_num\_$i_connect"; + if(defined $connect_socket_num){ + my $connect_n=$soc->soc_get_instance_name($connect_id); + my $connect_port= "$connect_n\_socket_$i_name\_$connect_socket_num\_$i_connect"; + #connect plug port to socket port + my $new_range = add_instantc_name_to_parameters(\%params,$inst,$range); + my $r= (!defined $range)? 0 : (length ($range)>1 )? 1 :0; + my $connect_port_range=($r==1)?"$connect_port\[$new_range\]":$connect_port; + if($type eq 'input' ){ + $plugs_assign_v= "$plugs_assign_v \tassign $assigned_port = $connect_port_range;\n"; + $wires->wire_add($assigned_port,"connected",1); + }else{ + $plugs_assign_v= "$plugs_assign_v \tassign $connect_port = $assigned_port;\n"; + $wires->wire_add($connect_port,"connected",1); + } + } + }#plug + else{ #socket + my ($s_type,$s_value,$s_connection_num)=$soc->soc_get_socket_of_instance($id,$i_name); + my $v=$soc->soc_get_module_param_value($id,$s_value); + my ($i_range,$t,$i_connect)=$intfc->get_port_info_of_socket($i_name,$i_port); + if ( length( $v || '' )) { + $v--; + my $name= $soc->soc_get_instance_name($id); + my $joint= "$name\_$i_type\_$i_name\_$v\_$i_port"; + my ($wire_string,$port_name)=generate_wire ($i_range,"$name\_$i_type\_$i_name\_$v\_$i_port",$inst,\%params,$i_type,$i_name,$i_num,$i_port, $wires); + add_text_to_string(\$wire_def_v,$wire_string) if ($wire_def_v !~ /[\s\]]$port_name;/); + for(my $i=$v-1; $i>=0; $i--) { + $joint= "$joint ,$name\_$i_type\_$i_name\_$i\_$i_port"; + #create socket wires + #create plug wires + my ($wire_string,$port_name)=generate_wire ($i_range,"$name\_$i_type\_$i_name\_$i\_$i_port",$inst,\%params,$i_type,$i_name,$i_num,$i_port, $wires); + add_text_to_string(\$wire_def_v,$wire_string) if ($wire_def_v !~ /[\s\]]$port_name;/); + } + $wires->wire_add($assigned_port,"connected",1) if($type eq 'input'); + if($type ne 'input' ){ + my @w=split('\s*,\s*',$joint); + foreach my $q (@w) { + $wires->wire_add($q,"connected",1); + } + } + $joint=($v>0)? "\{ $joint\ }" : "$joint"; + my $text=($type eq 'input' )? "\tassign $assigned_port = $joint;\n": "\tassign $joint = $assigned_port;\n"; + add_text_to_string(\$sockets_assign_v,$text); + } + }#socket + } + $i_name ='IO' if (!defined $i_name); + my $reset_jtag_ored = ($i_name eq 'reset')? '| jtag_system_reset' : ''; + my $reset_jtag_nc = ($i_name eq 'reset')? 'jtag_system_reset' : ''; + if (++$counter == scalar(@ports)){#last port def + $inst_v=($NC eq 'yes')? "$inst_v\t\t.$port()\n": "$inst_v\t\t.$port($assigned_port)\n"; + $assigned_ports=($NC eq 'yes')? "$assigned_ports\t\t.$port($reset_jtag_nc)\n": "$assigned_ports\t\t.$port($assigned_port $reset_jtag_ored)\n"; + } + else { + $inst_v=($NC eq 'yes')? "$inst_v\t\t.$port(),\n":"$inst_v\t\t.$port($assigned_port),\n"; + $assigned_ports=($NC eq 'yes')? "$assigned_ports\t\t.$port($reset_jtag_nc),\n":"$assigned_ports\t\t.$port($assigned_port $reset_jtag_ored),\n"; + } + if($type ne 'input' && $NC ne 'yes' ){ + $wires->wire_add($assigned_port,"connected",1); + } + } + $inst_v="$inst_v\t);\n"; + my $hdr =$ip->ip_get($category,$module,'system_v'); + if(defined $hdr){ + $hdr=replace_golb_var($hdr,\%params); + $system_v= "$system_v $hdr\n"; + } + return ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v, $io_full_v, + $io_top_full_v,$io_sim_v,$top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass, + $src_io_short, $src_io_full); + #return ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$param_pass_v,$assigned_ports); +} sub add_instantc_name_to_parameters{ - my ($params_ref,$inst,$range)=@_; - my $new_range=$range; - #print "$new_range\n"; - return $new_range if(!defined $range); - my @list=sort keys%{$params_ref}; - foreach my $param (@list){ - my $new_param= "$inst\_$param"; - ($new_range=$new_range)=~ s/\b$param\b/$new_param/g; - #print "$new_range= s/\b$param\b/$new_param/g\n"; - } - return $new_range; -} - + my ($params_ref,$inst,$range)=@_; + my $new_range=$range; + #print "$new_range\n"; + return $new_range if(!defined $range); + my @list=sort keys%{$params_ref}; + foreach my $param (@list){ + my $new_param= "$inst\_$param"; + ($new_range=$new_range)=~ s/\b$param\b/$new_param/g; + #print "$new_range= s/\b$param\b/$new_param/g\n"; + } + return $new_range; +} sub gen_parameter_v{ - my ($param_ref,$id,$inst,$category,$module,$ip,$param_as_in_v,$ref_ordered,$top_ip,$param_pass_v,$param_type_ref)=@_; - my %params=%{$param_ref}; - my %params_type=%{$param_type_ref}; - my @param_order; - @param_order=@{$ref_ordered} if(defined $ref_ordered); - - my ($param_v,$local_param_v,$instance_param_v); - my @list; - @list= (@param_order)? @param_order : sort keys%params; - my $first_param=1; - - $local_param_v=""; - $param_v=""; - - #add instance name to parameter value - foreach my $param (@list){ - $params{$param}=add_instantc_name_to_parameters(\%params,$inst,$params{$param}); - #%params_type{$param}=add_instantc_name_to_parameters(\%params_type,$inst,$params_type{$param}); - } - - - #print parameters - foreach my $param (@list){ - my $inst_param= "$inst\_$param"; - my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$param); - $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); - if ($vfile_param_type eq "Localparam"){ - my $type = $params_type{$param}; - $type = "Localparam" if (! defined $type); - $vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam"; - } - - - - #$vfile_param_type= "Parameter" if ($vfile_param_type eq 1); - #$vfile_param_type= "Localparam" if ($vfile_param_type eq 0); - $redefine_param=1 if (! defined $redefine_param); - $redefine_param=0 if ($vfile_param_type eq "Don't include"); - if($redefine_param eq 1){ - $instance_param_v=($first_param eq 1)? "\t\t.$param($inst_param)" : "$instance_param_v,\n\t\t.$param($inst_param)"; - $first_param=0; - - } - - - - if($vfile_param_type eq "Localparam"){ - $local_param_v="$local_param_v\tlocalparam\t$inst_param=$params{$param};\n"; - $top_ip->top_add_localparam($id,$inst_param,$params{$param},$type,$content,$info,$vfile_param_type,$redefine_param); - } - elsif($vfile_param_type eq "Parameter"){ - #print "$inst_param($inst_param)\n"; - $param_v="$param_v\tparameter\t$inst_param=$params{$param};\n"; - $$param_pass_v =(defined ($$param_pass_v ))? "$$param_pass_v,\n\t\t.$inst_param($inst_param)": "\t\t.$inst_param($inst_param)"; - $$param_as_in_v=(defined ($$param_as_in_v))? "$$param_as_in_v ,\n\tparameter\t$inst_param=$params{$param}": - " \tparameter\t$inst_param=$params{$param}"; - #add parameter to top - #$top_ip $inst_param - $top_ip->top_add_parameter($id,$inst_param,$params{$param},$type,$content,$info,$vfile_param_type,$redefine_param); - - } - - - - } - - return ($param_v,$local_param_v,$instance_param_v); - - -} + my ($param_ref,$id,$inst,$category,$module,$ip,$param_as_in_v,$ref_ordered,$top_ip,$param_pass_v,$param_type_ref)=@_; + my %params=%{$param_ref}; + my %params_type=%{$param_type_ref}; + my @param_order; + @param_order=@{$ref_ordered} if(defined $ref_ordered); + my ($param_v,$local_param_v,$instance_param_v); + my @list; + @list= (@param_order)? @param_order : sort keys%params; + my $first_param=1; + $local_param_v=""; + $param_v=""; + #add instance name to parameter value + foreach my $param (@list){ + $params{$param}=add_instantc_name_to_parameters(\%params,$inst,$params{$param}); + #%params_type{$param}=add_instantc_name_to_parameters(\%params_type,$inst,$params_type{$param}); + } + #print parameters + foreach my $param (@list){ + my $inst_param= "$inst\_$param"; + my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$param); + $vfile_param_type= "Don't include" if (!defined $vfile_param_type ); + if ($vfile_param_type eq "Localparam"){ + my $type = $params_type{$param}; + $type = "Localparam" if (! defined $type); + $vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam"; + } + #$vfile_param_type= "Parameter" if ($vfile_param_type eq 1); + #$vfile_param_type= "Localparam" if ($vfile_param_type eq 0); + $redefine_param=1 if (! defined $redefine_param); + $redefine_param=0 if ($vfile_param_type eq "Don't include"); + if($redefine_param eq 1){ + $instance_param_v=($first_param eq 1)? "\t\t.$param($inst_param)" : "$instance_param_v,\n\t\t.$param($inst_param)"; + $first_param=0; + } + if($vfile_param_type eq "Localparam"){ + $local_param_v="$local_param_v\tlocalparam\t$inst_param=$params{$param};\n"; + $top_ip->top_add_localparam($id,$inst_param,$params{$param},$type,$content,$info,$vfile_param_type,$redefine_param); + } + elsif($vfile_param_type eq "Parameter"){ + #print "$inst_param($inst_param)\n"; + $param_v="$param_v\tparameter\t$inst_param=$params{$param};\n"; + $$param_pass_v =(defined ($$param_pass_v ))? "$$param_pass_v,\n\t\t.$inst_param($inst_param)": "\t\t.$inst_param($inst_param)"; + $$param_as_in_v=(defined ($$param_as_in_v))? "$$param_as_in_v ,\n\tparameter\t$inst_param=$params{$param}": + " \tparameter\t$inst_param=$params{$param}"; + #add parameter to top + #$top_ip $inst_param + $top_ip->top_add_parameter($id,$inst_param,$params{$param},$type,$content,$info,$vfile_param_type,$redefine_param); + } + } + return ($param_v,$local_param_v,$instance_param_v); +} ############### -# generate_address_cmp +# generate_address_cmp ############## - sub generate_address_cmp{ - my ($soc,$wires)=@_; - my $number=0; - my $addr_mp_v="\n//Wishbone slave address match\n"; - my $instance_addr_localparam="\n//Wishbone slave base address based on instance name\n"; - my $module_addr_localparam="\n//Wishbone slave base address based on module name. \n"; - - my @all_instances=$soc->soc_get_all_instances(); - foreach my $instance_id (@all_instances){ - my $instance_name=$soc->soc_get_instance_name($instance_id); - my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); - foreach my $plug (@plugs){ - my @nums=$soc->soc_list_plug_nums($instance_id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); - if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ - #read wishbone bus address and data width size - my $Aw=$soc->soc_get_module_param_value ($connect_id,'Aw'); - my $Dw=$soc->soc_get_module_param_value ($connect_id,'Dw'); - $Aw=32 if (!defined $Aw); - $Dw=32 if (!defined $Dw); - add_text_to_string(\$addr_mp_v,"/* $instance_name wb_slave $num */\n"); - #count how many nibbles we have in address size - my $hh= ($Aw % 4)? ($Aw >> 2)+1 : ($Aw >> 2); - $hh= "'h%0${hh}x";#hex address nibble num - #change addresses to word as the assign addresses by ProNoC GUI are in bytes - my $bytenum=($Dw/8); - my $base_hex=$Aw.sprintf($hh, ($base/$bytenum)); - my $end_hex=$Aw.sprintf($hh, ($end/$bytenum)); - #my $base_hex=sprintf("32'h%08x", ($base>>2)); - #my $end_hex=sprintf("32'h%08x", ($end>>2)); - add_text_to_string(\$instance_addr_localparam,"\tlocalparam \t$instance_name\_WB$num\_BASE_ADDR\t=\t$base_hex;\n"); - add_text_to_string(\$instance_addr_localparam,"\tlocalparam \t$instance_name\_WB$num\_END_ADDR\t=\t$end_hex;\n"); - if($instance_name ne $instance_id){ - add_text_to_string(\$module_addr_localparam,"\tlocalparam \t$instance_id\_WB$num\_BASE_ADDR\t=\t$base_hex;\n"); - add_text_to_string(\$module_addr_localparam,"\tlocalparam \t$instance_id\_WB$num\_END_ADDR\t=\t$end_hex;\n"); - } - - my $connect_name=$soc->soc_get_instance_name($connect_id); - $wires->wire_add("$connect_name\_socket_wb_addr_map_0_sel_one_hot","connected",1); - $addr_mp_v="$addr_mp_v \tassign $connect_name\_socket_wb_addr_map_0_sel_one_hot[$connect_socket_num\] = (($connect_name\_socket_wb_addr_map_0_grant_addr >= $instance_name\_WB$num\_BASE_ADDR) & ($connect_name\_socket_wb_addr_map_0_grant_addr <= $instance_name\_WB$num\_END_ADDR));\n"; - - $number++; - }#if - }#foreach my $num - }#foreach my $plug - }#foreach my $instance_id - - add_text_to_string(\$instance_addr_localparam,"\n"); - add_text_to_string(\$module_addr_localparam,"\n"); - return ($addr_mp_v,$instance_addr_localparam,$module_addr_localparam); -} - + my ($soc,$wires)=@_; + my $number=0; + my $addr_mp_v="\n//Wishbone slave address match\n"; + my $instance_addr_localparam="\n//Wishbone slave base address based on instance name\n"; + my $module_addr_localparam="\n//Wishbone slave base address based on module name. \n"; + my @all_instances=$soc->soc_get_all_instances(); + foreach my $instance_id (@all_instances){ + my $instance_name=$soc->soc_get_instance_name($instance_id); + my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); + foreach my $plug (@plugs){ + my @nums=$soc->soc_list_plug_nums($instance_id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); + if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ + #read wishbone bus address and data width size + my $Aw=$soc->soc_get_module_param_value ($connect_id,'Aw'); + my $Dw=$soc->soc_get_module_param_value ($connect_id,'Dw'); + $Aw=32 if (!defined $Aw); + $Dw=32 if (!defined $Dw); + add_text_to_string(\$addr_mp_v,"/* $instance_name wb_slave $num */\n"); + #count how many nibbles we have in address size + my $hh= ($Aw % 4)? ($Aw >> 2)+1 : ($Aw >> 2); + $hh= "'h%0${hh}x";#hex address nibble num + #change addresses to word as the assign addresses by ProNoC GUI are in bytes + my $bytenum=($Dw/8); + my $base_hex=$Aw.sprintf($hh, ($base/$bytenum)); + my $end_hex=$Aw.sprintf($hh, ($end/$bytenum)); + #my $base_hex=sprintf("32'h%08x", ($base>>2)); + #my $end_hex=sprintf("32'h%08x", ($end>>2)); + add_text_to_string(\$instance_addr_localparam,"\tlocalparam \t$instance_name\_WB$num\_BASE_ADDR\t=\t$base_hex;\n"); + add_text_to_string(\$instance_addr_localparam,"\tlocalparam \t$instance_name\_WB$num\_END_ADDR\t=\t$end_hex;\n"); + if($instance_name ne $instance_id){ + add_text_to_string(\$module_addr_localparam,"\tlocalparam \t$instance_id\_WB$num\_BASE_ADDR\t=\t$base_hex;\n"); + add_text_to_string(\$module_addr_localparam,"\tlocalparam \t$instance_id\_WB$num\_END_ADDR\t=\t$end_hex;\n"); + } + my $connect_name=$soc->soc_get_instance_name($connect_id); + $wires->wire_add("$connect_name\_socket_wb_addr_map_0_sel_one_hot","connected",1); + $addr_mp_v="$addr_mp_v \tassign $connect_name\_socket_wb_addr_map_0_sel_one_hot[$connect_socket_num\] = (($connect_name\_socket_wb_addr_map_0_grant_addr >= $instance_name\_WB$num\_BASE_ADDR) & ($connect_name\_socket_wb_addr_map_0_grant_addr <= $instance_name\_WB$num\_END_ADDR));\n"; + $number++; + }#if + }#foreach my $num + }#foreach my $plug + }#foreach my $instance_id + add_text_to_string(\$instance_addr_localparam,"\n"); + add_text_to_string(\$module_addr_localparam,"\n"); + return ($addr_mp_v,$instance_addr_localparam,$module_addr_localparam); +} sub add_text_to_string{ - my ($string,$text)=@_; - if(defined $text){ - $$string=(defined ($$string))? "$$string $text" : $text; - } -} - - + my ($string,$text)=@_; + if(defined $text){ + $$string=(defined ($$string))? "$$string $text" : $text; + } +} sub generate_wire { - my($range,$port_name,$inst_name,$params_ref,$i_type,$i_name,$i_num,$i_port, $wires)=@_; - my $wire_string; - my $new_range; - my $r= (!defined $range)? 0 : (length ($range)>1 )? 1 :0; - - if($r ==1 ){ - #replace parameter in range - $new_range = add_instantc_name_to_parameters($params_ref,$inst_name,$range); - $wire_string= "\twire\t[ $new_range ] $port_name;\n"; - } - else{ - $wire_string="\twire\t\t\t $port_name;\n"; - } - $wires->wire_add("$port_name","range",$new_range); - $wires->wire_add("$port_name","inst_name",$inst_name); - $wires->wire_add("$port_name","i_type",$i_type); - $wires->wire_add("$port_name","i_name",$i_name); - $wires->wire_add("$port_name","i_num",$i_num); - $wires->wire_add("$port_name","i_port",$i_port); - - return ($wire_string,$port_name); -} + my($range,$port_name,$inst_name,$params_ref,$i_type,$i_name,$i_num,$i_port, $wires)=@_; + my $wire_string; + my $new_range; + my $r= (!defined $range)? 0 : (length ($range)>1 )? 1 :0; + if($r ==1 ){ + #replace parameter in range + $new_range = add_instantc_name_to_parameters($params_ref,$inst_name,$range); + $wire_string= "\twire\t[ $new_range ] $port_name;\n"; + } + else{ + $wire_string="\twire\t\t\t $port_name;\n"; + } + $wires->wire_add("$port_name","range",$new_range); + $wires->wire_add("$port_name","inst_name",$inst_name); + $wires->wire_add("$port_name","i_type",$i_type); + $wires->wire_add("$port_name","i_name",$i_name); + $wires->wire_add("$port_name","i_num",$i_num); + $wires->wire_add("$port_name","i_port",$i_port); + return ($wire_string,$port_name); +} sub port_width_repeat{ - my ($range,$value)=@_; - return "$value" if (!defined $range); - $range= remove_all_white_spaces($range); - my ($h,$l)=split(':',$range); - return "$value" if(!defined $h ) ; # port width is 1 - return "$value" if($h eq "0" && "$l" eq "0"); # port width is 1 - $h=$l if($h eq "0" && "$l" ne "0"); - if($h =~ /-1$/){ # the address ranged is endup with -1 - $h =~ s/-1$//; # remove -1 - return "\{$h\{$value\}\}" if($h =~ /\)$/); - return "\{($h)\{$value\}\}" if($h =~ /[\*\.\+\-\^\%\&]/); - return "\{$h\{$value\}\}"; - } - return "\{($h+1){$value}}"; + my ($range,$value)=@_; + return "$value" if (!defined $range); + $range= remove_all_white_spaces($range); + my ($h,$l)=split(':',$range); + return "$value" if(!defined $h ) ; # port width is 1 + return "$value" if($h eq "0" && "$l" eq "0"); # port width is 1 + $h=$l if($h eq "0" && "$l" ne "0"); + if($h =~ /-1$/){ # the address ranged is endup with -1 + $h =~ s/-1$//; # remove -1 + return "\{$h\{$value\}\}" if($h =~ /\)$/); + return "\{($h)\{$value\}\}" if($h =~ /[\*\.\+\-\^\%\&]/); + return "\{$h\{$value\}\}"; + } + return "\{($h+1){$value}}"; } sub assign_unconnected_wires{ - my($wires,$intfc)=@_; - my $unused_wire_v=undef; - - my @all_wires=$wires->wires_list(); - foreach my $p (@all_wires ){ - if(!defined $wires->wire_get($p,"connected")){ # unconnected wires - # Take default value from interface definition - #$wires->wire_get("$p","inst_name"); - my $i_type=$wires->wire_get($p,"i_type"); - my $i_name= $wires->wire_get($p,"i_name"); - my $i_num=$wires->wire_get($p,"i_num"); - my $i_port=$wires->wire_get($p,"i_port"); - my $new_range=$wires->wire_get($p,"range"); - my ($range,$type,$connect,$default_out) = ($i_type eq "socket" )? $intfc->get_port_info_of_socket($i_name,$i_port): - $intfc->get_port_info_of_plug($i_name,$i_port); - #""Active high","Don't care" - - my $default=(!defined $default_out )? port_width_repeat($new_range,"1\'bx"): - ($default_out eq 'Active low' )? port_width_repeat($new_range,"1\'b0"): - ($default_out eq 'Active high')? port_width_repeat($new_range,"1\'b1"): - ($default_out eq 'Don\'t care')? port_width_repeat($new_range,"1\'bx"): $default_out; - - - $unused_wire_v= (defined $unused_wire_v)? "$unused_wire_v \tassign ${p} = $default;\n" : "\tassign ${p} = $default;\n"; - - } - - } - $unused_wire_v="\n//Take the default value for ports that defined by interfaces but did not assigned to any wires.\n $unused_wire_v\n\n" if(defined $unused_wire_v); - return $unused_wire_v; - - + my($wires,$intfc)=@_; + my $unused_wire_v=undef; + my @all_wires=$wires->wires_list(); + foreach my $p (@all_wires ){ + if(!defined $wires->wire_get($p,"connected")){ # unconnected wires + # Take default value from interface definition + #$wires->wire_get("$p","inst_name"); + my $i_type=$wires->wire_get($p,"i_type"); + my $i_name= $wires->wire_get($p,"i_name"); + my $i_num=$wires->wire_get($p,"i_num"); + my $i_port=$wires->wire_get($p,"i_port"); + my $new_range=$wires->wire_get($p,"range"); + my ($range,$type,$connect,$default_out) = + ($i_type eq "socket" )? $intfc->get_port_info_of_socket($i_name,$i_port): + $intfc->get_port_info_of_plug($i_name,$i_port); + #""Active high","Don't care" + my $default=(!defined $default_out )? port_width_repeat($new_range,"1\'bx"): + ($default_out eq 'Active low' )? port_width_repeat($new_range,"1\'b0"): + ($default_out eq 'Active high')? port_width_repeat($new_range,"1\'b1"): + ($default_out eq 'Don\'t care')? port_width_repeat($new_range,"1\'bx"): $default_out; + $unused_wire_v= (defined $unused_wire_v)? "$unused_wire_v \tassign ${p} = $default;\n" : "\tassign ${p} = $default;\n"; + } + } + $unused_wire_v="\n//Take the default value for ports that defined by interfaces but did not assigned to any wires.\n $unused_wire_v\n\n" if(defined $unused_wire_v); + return $unused_wire_v; } - - - sub gen_soc_instance_v{ - my ($soc,$soc_name,$param_pass_v,$txview)=@_; - - my $processor_en=0; - my $altera_jtag_ctrl=0; - my $xilinx_jtag_ctrl=0; #if it becomes larger than 0 then add jtag to wb module - my $jtag_insts=""; - my $xilinx_jtag_ctrl_in; - my $xilinx_jtag_ctrl_out; - my $rpin = "1\'b0"; - my $clkpin; - my $soc_v=" - // Allow software to remote reset/enable the cpu via jtag - wire jtag_cpu_en, jtag_system_reset; + my ($soc,$soc_name,$param_pass_v,$txview)=@_; + my $processor_en=0; + my $altera_jtag_ctrl=0; + my $xilinx_jtag_ctrl=0; #if it becomes larger than 0 then add jtag to wb module + my $jtag_insts=""; + my $xilinx_jtag_ctrl_in; + my $xilinx_jtag_ctrl_out; + my $rpin = "1\'b0"; + my $clkpin; + my $soc_v=" + // Allow software to remote reset/enable the cpu via jtag + wire jtag_cpu_en, jtag_system_reset; "; - - my $mm="$soc_name #(\n $param_pass_v \n\t)the_${soc_name}(\n"; - my $top=$soc->soc_get_top(); - my @intfcs=$top->top_get_intfc_list(); - my $i=0; - my $ss=""; - my $ww=""; - - my $jtag_inst_name=""; - - foreach my $intfc (@intfcs){ - - #reset - if( $intfc eq 'plug:reset[0]'){ - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - $mm="$mm," if ($i); - $mm="$mm\n\t\t.$p(${p}_ored_jtag)"; - $ss="$ss\tassign ${p}_ored_jtag = (jtag_system_reset | $p);\n"; - $ww="$ww\twire ${p}_ored_jtag;\n"; - $rpin = $p; - $i=1; - - } - } - - #enable - elsif( $intfc eq 'plug:enable[0]'){ - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - $mm="$mm," if ($i); - $mm="$mm\n\t\t.$p(${p}_anded_jtag)"; - $ss="$ss\tassign ${p}_anded_jtag= (jtag_cpu_en & $p);\n"; - $ww="$ww\twire ${p}_anded_jtag;\n"; - $processor_en=1; - $i=1; - - } - } - - #RxD_sim - elsif( $intfc eq 'socket:RxD_sim[0]'){ - #This interface is for simulation only donot include it in top module - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - $mm="$mm," if ($i); - $mm="$mm\n\t\t.$p( )"; - $i=1; - } - } - - - #jtag_to_wb - elsif( $intfc =~ /socket:jtag_to_wb\[/){ #check JTAG connect parameter. if it is XILINX then connect it to jtag tap - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - - - my $JTAG_CONNECT=remove_all_white_spaces($soc->soc_get_module_param_value ($id,'JTAG_CONNECT')); - - #print "$inst,$range,$type,$intfc_name,$intfc_port-> $JTAG_CONNECT;"; - if($JTAG_CONNECT eq '"XILINX_JTAG_WB"'){ - $jtag_inst_name= $soc->soc_get_instance_name($id); - - - my %params = $soc->soc_get_module_param($id); - my $new_range = add_instantc_name_to_parameters(\%params,$id,$range); - $ww="$ww\twire [ $new_range ] ${p};\n"; - - $mm="$mm," if ($i); - $mm="$mm\n\t\t.$p($p)"; - if($type eq 'input'){ - $jtag_insts=$jtag_insts."$id XILINX JTAG,"; - $xilinx_jtag_ctrl++; - $xilinx_jtag_ctrl_in=(defined $xilinx_jtag_ctrl_in)? "$xilinx_jtag_ctrl_in,$p" : "$p"; - }else { - $xilinx_jtag_ctrl_out=(defined $xilinx_jtag_ctrl_out)? "$xilinx_jtag_ctrl_out,$p" : "$p"; - } - - - }else{#Dont not connect - $mm="$mm," if ($i); - $mm="$mm\n\t\t.$p( )"; - } - - if($JTAG_CONNECT =~ /ALTERA_JTAG_WB/){ - - if($type eq 'input'){ - $jtag_insts=$jtag_insts."$id ALTERA JTAG,"; - $altera_jtag_ctrl++; - - } - } - $i=1; - } - - } - - - - else { - #other interface - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - $clkpin=$p if( $intfc eq 'plug:clk[0]'); - $mm="$mm," if ($i); - $mm="$mm\n\t\t.$p($p)"; - $i=1; - - } - } - - } - $mm="$mm\n\t);"; - add_text_to_string(\$soc_v,"$ww\n"); - add_text_to_string(\$soc_v,"$mm\n"); - add_text_to_string(\$soc_v,"$ss\n"); - - - if($altera_jtag_ctrl>0 && $xilinx_jtag_ctrl>0 ){ - add_colored_info($txview,"Found JTAG comminication ports from differnt FPGA vendors:$jtag_insts. ",'red'); - - }elsif ($xilinx_jtag_ctrl>0){ - $xilinx_jtag_ctrl_in ="{$xilinx_jtag_ctrl_in}" if($xilinx_jtag_ctrl != 1); - $xilinx_jtag_ctrl_out ="{$xilinx_jtag_ctrl_out}" if($xilinx_jtag_ctrl != 1); - - $soc_v = $soc_v." - xilinx_jtag_wb #( - .JWB_NUM($xilinx_jtag_ctrl), - .JDw(${jtag_inst_name}_JDw), - .JAw(${jtag_inst_name}_JAw) - )jwb( - - .reset($rpin), - .cpu_en(jtag_cpu_en), - .system_reset(jtag_system_reset), - .wb_to_jtag_all($xilinx_jtag_ctrl_out), - .jtag_to_wb_all($xilinx_jtag_ctrl_in) - ); - + my $mm="$soc_name #(\n $param_pass_v \n\t)the_${soc_name}(\n"; + my $top=$soc->soc_get_top(); + my @intfcs=$top->top_get_intfc_list(); + my $i=0; + my $ss=""; + my $ww=""; + my $jtag_inst_name=""; + foreach my $intfc (@intfcs){ + #reset + if( $intfc eq 'plug:reset[0]'){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + $mm="$mm," if ($i); + $mm="$mm\n\t\t.$p(${p}_ored_jtag)"; + $ss="$ss\tassign ${p}_ored_jtag = (jtag_system_reset | $p);\n"; + $ww="$ww\twire ${p}_ored_jtag;\n"; + $rpin = $p; + $i=1; + } + } + #enable + elsif( $intfc eq 'plug:enable[0]'){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + $mm="$mm," if ($i); + $mm="$mm\n\t\t.$p(${p}_anded_jtag)"; + $ss="$ss\tassign ${p}_anded_jtag= (jtag_cpu_en & $p);\n"; + $ww="$ww\twire ${p}_anded_jtag;\n"; + $processor_en=1; + $i=1; + } + } + #RxD_sim + elsif( $intfc eq 'socket:RxD_sim[0]'){ + #This interface is for simulation only donot include it in top module + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + $mm="$mm," if ($i); + $mm="$mm\n\t\t.$p( )"; + $i=1; + } + } + #jtag_to_wb + elsif( $intfc =~ /socket:jtag_to_wb\[/){ #check JTAG connect parameter. if it is XILINX then connect it to jtag tap + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($id,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + my $JTAG_CONNECT=remove_all_white_spaces($soc->soc_get_module_param_value ($id,'JTAG_CONNECT')); + #print "$inst,$range,$type,$intfc_name,$intfc_port-> $JTAG_CONNECT;"; + if($JTAG_CONNECT eq '"XILINX_JTAG_WB"'){ + $jtag_inst_name= $soc->soc_get_instance_name($id); + my %params = $soc->soc_get_module_param($id); + my $new_range = add_instantc_name_to_parameters(\%params,$id,$range); + $ww="$ww\twire [ $new_range ] ${p};\n"; + $mm="$mm," if ($i); + $mm="$mm\n\t\t.$p($p)"; + if($type eq 'input'){ + $jtag_insts=$jtag_insts."$id XILINX JTAG,"; + $xilinx_jtag_ctrl++; + $xilinx_jtag_ctrl_in=(defined $xilinx_jtag_ctrl_in)? "$xilinx_jtag_ctrl_in,$p" : "$p"; + }else { + $xilinx_jtag_ctrl_out=(defined $xilinx_jtag_ctrl_out)? "$xilinx_jtag_ctrl_out,$p" : "$p"; + } + }else{#Dont not connect + $mm="$mm," if ($i); + $mm="$mm\n\t\t.$p( )"; + } + if($JTAG_CONNECT =~ /ALTERA_JTAG_WB/){ + if($type eq 'input'){ + $jtag_insts=$jtag_insts."$id ALTERA JTAG,"; + $altera_jtag_ctrl++; + } + } + $i=1; + } + } + else { + #other interface + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + $clkpin=$p if( $intfc eq 'plug:clk[0]'); + $mm="$mm," if ($i); + $mm="$mm\n\t\t.$p($p)"; + $i=1; + } + } + } + $mm="$mm\n\t);"; + add_text_to_string(\$soc_v,"$ww\n"); + add_text_to_string(\$soc_v,"$mm\n"); + add_text_to_string(\$soc_v,"$ss\n"); + if($altera_jtag_ctrl>0 && $xilinx_jtag_ctrl>0 ){ + add_colored_info($txview,"Found JTAG comminication ports from differnt FPGA vendors:$jtag_insts. ",'red'); + }elsif ($xilinx_jtag_ctrl>0){ + $xilinx_jtag_ctrl_in ="{$xilinx_jtag_ctrl_in}" if($xilinx_jtag_ctrl != 1); + $xilinx_jtag_ctrl_out ="{$xilinx_jtag_ctrl_out}" if($xilinx_jtag_ctrl != 1); + $soc_v = $soc_v." + xilinx_jtag_wb #( + .JWB_NUM($xilinx_jtag_ctrl), + .JDw(${jtag_inst_name}_JDw), + .JAw(${jtag_inst_name}_JAw) + )jwb( + .reset($rpin), + .cpu_en(jtag_cpu_en), + .system_reset(jtag_system_reset), + .wb_to_jtag_all($xilinx_jtag_ctrl_out), + .jtag_to_wb_all($xilinx_jtag_ctrl_in) + ); "; - - }elsif($altera_jtag_ctrl>0) { -$soc_v = $soc_v." - jtag_system_en jtag_en ( - .cpu_en(jtag_cpu_en), - .system_reset(jtag_system_reset) - - ); -"; - - }else{ + }elsif($altera_jtag_ctrl>0) { $soc_v = $soc_v." - //No jtag connection has found in the design - assign jtag_cpu_en=1\'b0; - assign jtag_system_reset=1'b0; + jtag_system_en jtag_en ( + .cpu_en(jtag_cpu_en), + .system_reset(jtag_system_reset) + ); "; - } - - $soc_v=$soc_v."\n endmodule\n"; - return $soc_v; - + }else{ +$soc_v = $soc_v." + //No jtag connection has found in the design + assign jtag_cpu_en=1\'b0; + assign jtag_system_reset=1'b0; +"; + } + $soc_v=$soc_v."\n endmodule\n"; + return $soc_v; } - - - - sub gen_soc_instance_v_no_modfy{ - my ($soc,$soc_name,$param_pass_v)=@_; - my $soc_v; - my $processor_en=0; - - - my $mm="$soc_name #(\n $param_pass_v \n\t)the_${soc_name}(\n"; - - my $top=$soc->soc_get_top(); - my @intfcs=$top->top_get_intfc_list(); - - my $i=0; - - - - - my $ss=""; - my $ww=""; - - foreach my $intfc (@intfcs){ - - - - - - my @ports=$top->top_get_intfc_ports_list($intfc); - foreach my $p (@ports){ - my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); - $mm="$mm," if ($i); - if( $intfc =~ /socket:jtag_to_wb\[/){#dont include jtag connection - $mm="$mm\n\t\t.$p( )"; - }else{ - $mm="$mm\n\t\t.$p($p)"; - } - $i=1; - - - } - - - } - $mm="$mm\n\t);"; - add_text_to_string(\$soc_v,"$ww\n"); - add_text_to_string(\$soc_v,"$mm\n"); - add_text_to_string(\$soc_v,"$ss\n"); - add_text_to_string(\$soc_v,"\n endmodule\n"); - - - - return $soc_v; - + my ($soc,$soc_name,$param_pass_v)=@_; + my $soc_v; + my $processor_en=0; + my $mm="$soc_name #(\n $param_pass_v \n\t)the_${soc_name}(\n"; + my $top=$soc->soc_get_top(); + my @intfcs=$top->top_get_intfc_list(); + my $i=0; + my $ss=""; + my $ww=""; + foreach my $intfc (@intfcs){ + my @ports=$top->top_get_intfc_ports_list($intfc); + foreach my $p (@ports){ + my($inst,$range,$type,$intfc_name,$intfc_port)= $top->top_get_port($p); + $mm="$mm," if ($i); + if( $intfc =~ /socket:jtag_to_wb\[/){#dont include jtag connection + $mm="$mm\n\t\t.$p( )"; + }else{ + $mm="$mm\n\t\t.$p($p)"; + } + $i=1; + } + } + $mm="$mm\n\t);"; + add_text_to_string(\$soc_v,"$ww\n"); + add_text_to_string(\$soc_v,"$mm\n"); + add_text_to_string(\$soc_v,"$ss\n"); + add_text_to_string(\$soc_v,"\n endmodule\n"); + return $soc_v; } - - - - - - - sub gen_system_info { - my ($soc,$param)=@_; - my ($wb_slaves,$wb_masters,$other,$jtag); - #my (@newbase,@newend,@connects); - - - $jtag=''; - - my @all_instances=$soc->soc_get_all_instances(); - -my %jtagwb; my %ram; - - - foreach my $instance_id (@all_instances){ - my $category=$soc->soc_get_category($instance_id); - - my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); - foreach my $plug (@plugs){ - my @nums=$soc->soc_list_plug_nums($instance_id,$plug); - foreach my $num (@nums){ - my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); - - my $instance_name=$soc->soc_get_instance_name($instance_id); - my $connect_name=$soc->soc_get_instance_name($connect_id); - #get interfaces - if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ - - $base=sprintf("0x%08x", $base); - $end=sprintf("0x%08x", $end); - add_text_to_string(\$wb_slaves, "\t$instance_name, $name, $connect_name, $base, $end\n"); - if ($category eq 'RAM') { - $ram{$instance_id}{'base'}=$base; - $ram{$instance_id}{'end'}=$end; - $ram{$instance_id}{'connect'}=$connect_id; - } - - }#if - elsif((defined $connect_socket) && ($connect_socket eq 'wb_master')){ - add_text_to_string(\$wb_masters,"\t$instance_name, $name, $connect_name\n"); - } - elsif(defined $connect_socket) { - add_text_to_string(\$other,"\t$instance_name, $name, $connect_name\n"); - - } - # get jtag_wbs - if((defined $connect_socket) && ($connect_socket eq 'wb_master') && ($instance_id =~ /jtag_wb/)){ - my $index=$soc->soc_get_module_param_value($instance_id,'JTAG_INDEX'); - my $chain=$soc->soc_get_module_param_value($instance_id,'JTAG_CHAIN'); - my $vendor_connect =$soc->soc_get_module_param_value($instance_id,'JTAG_CONNECT'); - add_text_to_string(\$jtag, "\t$instance_name, $connect_name, $index\n"); - - $jtagwb{$connect_id}{'index'}=$index; - $jtagwb{$connect_id}{'chain'}=$chain; - $jtagwb{$connect_id}{'vendor_connect'}=$vendor_connect; - } - - - }#foreach my $num - }#foreach my $plug - }#foreach my $instance_id - - #Generate memory programming command + my ($soc,$param)=@_; + my ($wb_slaves,$wb_masters,$other,$jtag); + #my (@newbase,@newend,@connects); + $jtag=''; + my @all_instances=$soc->soc_get_all_instances(); + my %jtagwb; my %ram; + foreach my $instance_id (@all_instances){ + my $category=$soc->soc_get_category($instance_id); + my @plugs= $soc->soc_get_all_plugs_of_an_instance($instance_id); + foreach my $plug (@plugs){ + my @nums=$soc->soc_list_plug_nums($instance_id,$plug); + foreach my $num (@nums){ + my ($addr,$base,$end,$name,$connect_id,$connect_socket,$connect_socket_num)=$soc->soc_get_plug($instance_id,$plug,$num); + my $instance_name=$soc->soc_get_instance_name($instance_id); + my $connect_name=$soc->soc_get_instance_name($connect_id); + #get interfaces + if((defined $connect_socket) && ($connect_socket eq 'wb_slave')){ + $base=sprintf("0x%08x", $base); + $end=sprintf("0x%08x", $end); + add_text_to_string(\$wb_slaves, "\t$instance_name, $name, $connect_name, $base, $end\n"); + if ($category eq 'RAM') { + $ram{$instance_id}{'base'}=$base; + $ram{$instance_id}{'end'}=$end; + $ram{$instance_id}{'connect'}=$connect_id; + } + }#if + elsif((defined $connect_socket) && ($connect_socket eq 'wb_master')){ + add_text_to_string(\$wb_masters,"\t$instance_name, $name, $connect_name\n"); + } + elsif(defined $connect_socket) { + add_text_to_string(\$other,"\t$instance_name, $name, $connect_name\n"); + } + # get jtag_wbs + if((defined $connect_socket) && ($connect_socket eq 'wb_master') && ($instance_id =~ /jtag_wb/)){ + my $index=$soc->soc_get_module_param_value($instance_id,'JTAG_INDEX'); + my $chain=$soc->soc_get_module_param_value($instance_id,'JTAG_CHAIN'); + my $vendor_connect =$soc->soc_get_module_param_value($instance_id,'JTAG_CONNECT'); + add_text_to_string(\$jtag, "\t$instance_name, $connect_name, $index\n"); + $jtagwb{$connect_id}{'index'}=$index; + $jtagwb{$connect_id}{'chain'}=$chain; + $jtagwb{$connect_id}{'vendor_connect'}=$vendor_connect; + } + }#foreach my $num + }#foreach my $plug + }#foreach my $instance_id + #Generate memory programming command my $prog='#!/bin/bash - #JTAG_INTFC="$PRONOC_WORK/toolchain/bin/JTAG_INTFC" source ./jtag_intfc.sh - '; - - - foreach my $instance_id (@all_instances){ - my $category=$soc->soc_get_category($instance_id); - if ($category eq 'RAM') { - - my $jtag_connect=$soc->soc_get_module_param_value($instance_id,'JTAG_CONNECT'); - $jtag_connect=remove_all_white_spaces($jtag_connect); - my $aw=$soc->soc_get_module_param_value($instance_id,'Aw'); - my $dw=$soc->soc_get_module_param_value($instance_id,'Dw'); - my $JTAG_INDEX=$soc->soc_get_module_param_value($instance_id,'JTAG_INDEX'); - my $JTAG_CHAIN=$soc->soc_get_module_param_value($instance_id,'JTAG_CHAIN'); - - #check if jtag_index is a parameter - my $v=$soc->soc_get_module_param_value($instance_id,$JTAG_INDEX); - $JTAG_INDEX = $v if (defined $v); - $v= $soc->object_get_attribute('global_param',$JTAG_INDEX); - $JTAG_INDEX = $v if (defined $v); - - my $BINFILE=$soc->soc_get_module_param_value($instance_id,'JTAG_MEM_FILE'); - ($BINFILE)=$BINFILE=~ /"([^"]*)"/ if(defined $BINFILE); - $BINFILE=(defined $BINFILE) ? "./RAM/".$BINFILE.'.bin' : './RAM/ram0.bin'; - - my $OFSSET="0x00000000"; - my $end=((1 << $aw)*($dw/8))-1; - my $BOUNDRY=sprintf("0x%08x", $end); - if($jtag_connect =~ /ALTERA_JTAG_WB/ ) { - $prog= "$prog \$JTAG_INTFC -n $JTAG_INDEX -s \"$OFSSET\" -e \"$BOUNDRY\" -i \"$BINFILE\" -c"; - #print "prog= $prog\n"; - - } elsif ($jtag_connect =~ /XILINX_JTAG_WB/){ - $prog= "$prog \$JTAG_INTFC -t $JTAG_CHAIN -n $JTAG_INDEX -s \"$OFSSET\" -e \"$BOUNDRY\" -i \"$BINFILE\" -c"; - - } - - elsif ($jtag_connect eq 'ALTERA_IMCE'){ - #TODO add later - $prog= "$prog ".'>&2 echo'." \"ALTERA_IMCE runtime programming is not supported yet for programming $instance_id\"\n"; - - } else{ - #check if its connected to jtag_wb via the bus - my $connect_id = $ram{$instance_id}{'connect'}; - my $OFSSET = $ram{$instance_id}{'base'}; - my $BOUNDRY = $ram{$instance_id}{'end'}; - if(defined $connect_id){ - #print "id=$connect_id\n"; - my $JTAG_INDEX= $jtagwb{$connect_id}{'index'}; - my $JTAG_CHAIN= $jtagwb{$connect_id}{'chain'}; - my $JTAG_VENDOR= $jtagwb{$connect_id}{'vendor_connect'}; - - my $t=""; - $t="-t $JTAG_CHAIN"if($JTAG_VENDOR =~ /XILINX_JTAG_WB/); - - if(defined $JTAG_INDEX){ - $v= $soc->object_get_attribute('global_param',$JTAG_INDEX); - $JTAG_INDEX = $v if (defined $v); - $prog= "$prog \$JTAG_INTFC $t -n $JTAG_INDEX -s \"$OFSSET\" -e \"$BOUNDRY\" -i \"$BINFILE\" -c"; - #print "prog= $prog\n"; - - }else{ - $prog= "$prog".'>&2 echo'." \"JTAG runtime programming is not enabled in $instance_id\"\n"; - - } - - }else{ - $prog= "$prog".'>&2 echo'."\"JTAG runtime programming is not enabled in $instance_id\"\n"; - - } - } - - - } - - - } - - -my $lisence= get_license_header("readme"); -my $warning=autogen_warning(); - - -$wb_slaves = " \t\t NOTE: No wishbone slaves interface has been found in the design " if (!defined $wb_slaves); -$wb_masters= " \t\t NOTE: No wishbone master interface has been found in the design " if (!defined $wb_masters); - -my $readme=" + foreach my $instance_id (@all_instances){ + my $category=$soc->soc_get_category($instance_id); + if ($category eq 'RAM') { + my $jtag_connect=$soc->soc_get_module_param_value($instance_id,'JTAG_CONNECT'); + $jtag_connect=remove_all_white_spaces($jtag_connect); + my $aw=$soc->soc_get_module_param_value($instance_id,'Aw'); + my $dw=$soc->soc_get_module_param_value($instance_id,'Dw'); + my $JTAG_INDEX=$soc->soc_get_module_param_value($instance_id,'JTAG_INDEX'); + my $JTAG_CHAIN=$soc->soc_get_module_param_value($instance_id,'JTAG_CHAIN'); + #check if jtag_index is a parameter + my $v=$soc->soc_get_module_param_value($instance_id,$JTAG_INDEX); + $JTAG_INDEX = $v if (defined $v); + $v= $soc->object_get_attribute('global_param',$JTAG_INDEX); + $JTAG_INDEX = $v if (defined $v); + my $BINFILE=$soc->soc_get_module_param_value($instance_id,'JTAG_MEM_FILE'); + ($BINFILE)=$BINFILE=~ /"([^"]*)"/ if(defined $BINFILE); + $BINFILE=(defined $BINFILE) ? "./RAM/".$BINFILE.'.bin' : './RAM/ram0.bin'; + my $OFSSET="0x00000000"; + my $end=((1 << $aw)*($dw/8))-1; + my $BOUNDRY=sprintf("0x%08x", $end); + if($jtag_connect =~ /ALTERA_JTAG_WB/ ) { + $prog= "$prog \$JTAG_INTFC -n $JTAG_INDEX -s \"$OFSSET\" -e \"$BOUNDRY\" -i \"$BINFILE\" -c"; + #print "prog= $prog\n"; + } elsif ($jtag_connect =~ /XILINX_JTAG_WB/){ + $prog= "$prog \$JTAG_INTFC -t $JTAG_CHAIN -n $JTAG_INDEX -s \"$OFSSET\" -e \"$BOUNDRY\" -i \"$BINFILE\" -c"; + } + elsif ($jtag_connect eq 'ALTERA_IMCE'){ + #TODO add later + $prog= "$prog ".'>&2 echo'." \"ALTERA_IMCE runtime programming is not supported yet for programming $instance_id\"\n"; + } else{ + #check if its connected to jtag_wb via the bus + my $connect_id = $ram{$instance_id}{'connect'}; + my $OFSSET = $ram{$instance_id}{'base'}; + my $BOUNDRY = $ram{$instance_id}{'end'}; + if(defined $connect_id){ + #print "id=$connect_id\n"; + my $JTAG_INDEX= $jtagwb{$connect_id}{'index'}; + my $JTAG_CHAIN= $jtagwb{$connect_id}{'chain'}; + my $JTAG_VENDOR= $jtagwb{$connect_id}{'vendor_connect'}; + my $t=""; + $t="-t $JTAG_CHAIN"if($JTAG_VENDOR =~ /XILINX_JTAG_WB/); + if(defined $JTAG_INDEX){ + $v= $soc->object_get_attribute('global_param',$JTAG_INDEX); + $JTAG_INDEX = $v if (defined $v); + $prog= "$prog \$JTAG_INTFC $t -n $JTAG_INDEX -s \"$OFSSET\" -e \"$BOUNDRY\" -i \"$BINFILE\" -c"; + #print "prog= $prog\n"; + }else{ + $prog= "$prog".'>&2 echo'." \"JTAG runtime programming is not enabled in $instance_id\"\n"; + } + }else{ + $prog= "$prog".'>&2 echo'."\"JTAG runtime programming is not enabled in $instance_id\"\n"; + } + } + } + } + my $lisence= get_license_header("readme"); + my $warning=autogen_warning(); + $wb_slaves = " \t\t NOTE: No wishbone slaves interface has been found in the design " if (!defined $wb_slaves); + $wb_masters= " \t\t NOTE: No wishbone master interface has been found in the design " if (!defined $wb_masters); + my $readme=" $warning $lisence - *********************** -** Program the memories +** Program the memories *********************** - -If the memory core and jtag_wb are connected to the same wishbone bus, you can program the memory using - - bash program.sh - - - +If the memory core and jtag_wb are connected to the same wishbone bus, you can program the memory using + bash program.sh *************************** -** soc parameters +** soc parameters *************************** - $param - **************************** -** wishbone bus(es) info +** wishbone bus(es) info **************************** - #slave interfaces: - #instance name, interface name, connected to, base address, boundary address + #slave interfaces: + #instance name, interface name, connected to, base address, boundary address $wb_slaves - - #master interfaces: - #instance name, interface name, connected to + #master interfaces: + #instance name, interface name, connected to $wb_masters - **************************** -** Jtag to wishbone interface (jtag_wb) info: +** Jtag to wishbone interface (jtag_wb) info: **************************** - - #instance name, instance name, JTAG_INDEX + #instance name, instance name, JTAG_INDEX $jtag - - "; - - - - - return ($readme,$prog); - - - -} - - + return ($readme,$prog); +} ###################### # soc_generate_verilog ##################### - -sub soc_generate_verilator{ - my ($soc,$sw_path,$name,$params_ref)= @_; - my $soc_name=$soc->object_get_attribute('soc_name'); - my $top_ip=ip_gen->top_gen_new(); - if(!defined $soc_name){$soc_name='soc'}; - - my @instances=$soc->soc_get_all_instances(); - my $io_sim_v; - my $top_io_short_all; - my $core_id= $soc->object_get_attribute('global_param','CORE_ID'); - $core_id= 0 if(!defined $core_id); - my $param_as_in_v_all="\tparameter\tCORE_ID=$core_id, +sub soc_generate_verilator{ + my ($soc,$sw_path,$name,$params_ref)= @_; + my $soc_name=$soc->object_get_attribute('soc_name'); + my $top_ip=ip_gen->top_gen_new(); + if(!defined $soc_name){$soc_name='soc'}; + my @instances=$soc->soc_get_all_instances(); + my $io_sim_v; + my $top_io_short_all; + my $core_id= $soc->object_get_attribute('global_param','CORE_ID'); + $core_id= 0 if(!defined $core_id); + my $param_as_in_v_all="\tparameter\tCORE_ID=$core_id, \tparameter\tSW_LOC=\"$sw_path\"\n,"; - - my $param_pass_v_all="\t\t.CORE_ID(CORE_ID),\n\t\t.SW_LOC(SW_LOC)"; - my $body_v; - - my ($param_v_all, $local_param_v_all, $wire_def_v_all, $inst_v_all, $plugs_assign_v_all, $sockets_assign_v_all,$io_full_v_all,$top_io_full_all,$system_v_all); - my ($src_io_full_all,$src_io_short_all); - my $wires=soc->new_wires(); - my $intfc=interface->interface_new(); - - - foreach my $id (@instances){ - my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, - $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires,1); - my $inst = $soc->soc_get_instance_name($id); - add_text_to_string(\$body_v,"/*******************\n*\n*\t$inst\n*\n*\n*********************/\n"); - add_text_to_string(\$param_as_in_v_all,",\n$param_as_in_v") if(defined ($param_as_in_v)); - add_text_to_string(\$local_param_v_all,"$local_param_v\n") if(defined($local_param_v)); - add_text_to_string(\$param_pass_v_all,",\n$param_pass_v") if(defined($param_pass_v)); - add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); - add_text_to_string(\$inst_v_all,$inst_v) if(defined($inst_v)); - add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); - add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); - add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); - add_text_to_string(\$top_io_full_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); - add_text_to_string(\$src_io_full_all,"$src_io_full\n") if(length($src_io_full)>3); - - $top_io_short_all = (defined $top_io_short_all)? "$top_io_short_all,\n$top_io_short" : $top_io_short if(defined($top_io_short)); - $src_io_short_all = (defined $src_io_short_all)? "$src_io_short_all,\n$src_io_short" : $src_io_short if(defined($src_io_short)); - #print "$param_v $local_param_v $wire_def_v $inst_v $plugs_assign_v $sockets_assign_v $io_full_v"; - - } - - - - my ($addr_map,$addr_localparam,$module_addr_localparam)= generate_address_cmp($soc,$wires); - - #add functions - my $dir = Cwd::getcwd(); - open my $file1, "<", "$dir/lib/verilog/functions.v" or die; - my $functions_all=''; - while (my $f1 = readline ($file1)) { - $functions_all="$functions_all $f1 "; - } - close($file1); - my $unused_wiers_v=assign_unconnected_wires($wires,$intfc); - - - $soc->object_add_attribute('top_ip',undef,$top_ip); - #print @assigned_wires; - - #generate topmodule - my $params_v=" + my $param_pass_v_all="\t\t.CORE_ID(CORE_ID),\n\t\t.SW_LOC(SW_LOC)"; + my $body_v; + my ($param_v_all, $local_param_v_all, $wire_def_v_all, $inst_v_all, $plugs_assign_v_all, $sockets_assign_v_all,$io_full_v_all,$top_io_full_all,$system_v_all); + my ($src_io_full_all,$src_io_short_all); + my $wires=soc->new_wires(); + my $intfc=interface->interface_new(); + foreach my $id (@instances){ + my ($param_v, $local_param_v, $wire_def_v, $inst_v, $plugs_assign_v, $sockets_assign_v,$io_full_v,$io_top_full_v,$io_sim_v, + $top_io_short,$param_as_in_v,$param_pass_v,$system_v,$assigned_ports,$top_io_pass,$src_io_short, $src_io_full)=gen_module_inst($id,$soc,$top_ip,$intfc,$wires,1); + my $inst = $soc->soc_get_instance_name($id); + add_text_to_string(\$body_v,"/*******************\n*\n*\t$inst\n*\n*\n*********************/\n"); + add_text_to_string(\$param_as_in_v_all,",\n$param_as_in_v") if(defined ($param_as_in_v)); + add_text_to_string(\$local_param_v_all,"$local_param_v\n") if(defined($local_param_v)); + add_text_to_string(\$param_pass_v_all,",\n$param_pass_v") if(defined($param_pass_v)); + add_text_to_string(\$wire_def_v_all,"$wire_def_v\n") if(defined($wire_def_v)); + add_text_to_string(\$inst_v_all,$inst_v) if(defined($inst_v)); + add_text_to_string(\$plugs_assign_v_all,"$plugs_assign_v\n") if(defined($plugs_assign_v)); + add_text_to_string(\$sockets_assign_v_all,"$sockets_assign_v\n")if(defined($sockets_assign_v)); + add_text_to_string(\$io_full_v_all,"$io_full_v\n") if(length($io_full_v)>3); + add_text_to_string(\$top_io_full_all,"$io_top_full_v\n") if(length($io_top_full_v)>3); + add_text_to_string(\$src_io_full_all,"$src_io_full\n") if(length($src_io_full)>3); + $top_io_short_all = (defined $top_io_short_all)? "$top_io_short_all,\n$top_io_short" : $top_io_short if(defined($top_io_short)); + $src_io_short_all = (defined $src_io_short_all)? "$src_io_short_all,\n$src_io_short" : $src_io_short if(defined($src_io_short)); + #print "$param_v $local_param_v $wire_def_v $inst_v $plugs_assign_v $sockets_assign_v $io_full_v"; + } + my ($addr_map,$addr_localparam,$module_addr_localparam)= generate_address_cmp($soc,$wires); + #add functions + my $dir = Cwd::getcwd(); + open my $file1, "<", "$dir/lib/verilog/functions.v" or die; + my $functions_all=''; + while (my $f1 = readline ($file1)) { + $functions_all="$functions_all $f1 "; + } + close($file1); + my $unused_wiers_v=assign_unconnected_wires($wires,$intfc); + $soc->object_add_attribute('top_ip',undef,$top_ip); + #print @assigned_wires; + #generate topmodule + my $params_v=" \tparameter\tCORE_ID=$core_id; \tparameter\tSW_LOC=\"$sw_path\";\n"; - - - my %all_param=soc_get_all_parameters($soc); - my @order= soc_get_all_parameters_order($soc); - - - - #replace global parameters - my @list=sort keys%{$params_ref}; - foreach my $p (@list){ - my %hash=%{$params_ref}; - $all_param{$p}= $hash{$p}; - } - - foreach my $p (@order){ - add_text_to_string(\$params_v,"\tlocalparam $p = $all_param{$p};\n") if(defined $all_param{$p} ); - } - - - $top_io_short_all=(defined $top_io_short_all)? "$top_io_short_all,\n$src_io_short_all" : $src_io_short_all; - $top_io_full_all=$top_io_full_all."\n$src_io_full_all"; - # $top_io_pass_all=$top_io_pass_all.",\n$clk_assigned_port"; - - my $has_ni =check_for_ni($soc); - my $import = ($has_ni)? "\n\t`NOC_CONF\n" : ""; - - my $verilator_v = " + my %all_param=soc_get_all_parameters($soc); + my @order= soc_get_all_parameters_order($soc); + #replace global parameters + my @list=sort keys%{$params_ref}; + foreach my $p (@list){ + my %hash=%{$params_ref}; + $all_param{$p}= $hash{$p}; + } + foreach my $p (@order){ + add_text_to_string(\$params_v,"\tlocalparam $p = $all_param{$p};\n") if(defined $all_param{$p} ); + } + $top_io_short_all=(defined $top_io_short_all)? "$top_io_short_all,\n$src_io_short_all" : $src_io_short_all; + $top_io_full_all=$top_io_full_all."\n$src_io_full_all"; + # $top_io_pass_all=$top_io_pass_all.",\n$clk_assigned_port"; + my $has_ni =check_for_ni($soc); + my $import = ($has_ni)? "\n\t`NOC_CONF\n" : ""; + my $verilator_v = " /********************* - ${name} + ${name} *********************/ - module ${name} (\n $top_io_short_all\n);\n $import \n"; - my $ins= gen_soc_instance_v_no_modfy($soc,$soc_name,$param_pass_v_all); + my $ins= gen_soc_instance_v_no_modfy($soc,$soc_name,$param_pass_v_all); $verilator_v.=" -$functions_all +$functions_all /* verilator lint_off WIDTH */ $params_v /* verilator lint_on WIDTH */ $top_io_full_all $ins "; - my ($readme,$prog)=gen_system_info($soc,$param_as_in_v_all); - return ($verilator_v); - - -} - + my ($readme,$prog)=gen_system_info($soc,$param_as_in_v_all); + return ($verilator_v); +} sub get_golal_param_v{ - my $project_dir = get_project_dir(); #mpsoc dir addr - my $paths_file= "$project_dir/mpsoc/perl_gui/lib/glob_params"; - my $paramv=''; - if (-f $paths_file ){ - my $self= do $paths_file; - my @parameters = object_get_attribute_order($self,'Parameters'); - foreach my $p (@parameters) { - my $v =object_get_attribute($self,'Parameters',$p); - $paramv.="\t localparam $p = $v;\n" if(defined $v); - } - } - return $paramv; + my $project_dir = get_project_dir(); #mpsoc dir addr + my $paths_file= "$project_dir/mpsoc/perl_gui/lib/glob_params"; + my $paramv=''; + if (-f $paths_file ){ + my $self= do $paths_file; + my @parameters = object_get_attribute_order($self,'Parameters'); + foreach my $p (@parameters) { + my $v =object_get_attribute($self,'Parameters',$p); + $paramv.="\t localparam $p = $v;\n" if(defined $v); + } + } + return $paramv; } - - - - -1; - - +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/widget.pl b/mpsoc/perl_gui/lib/perl/widget.pl index 7201cdc..89c7992 100755 --- a/mpsoc/perl_gui/lib/perl/widget.pl +++ b/mpsoc/perl_gui/lib/perl/widget.pl @@ -12,17 +12,9 @@ BEGIN $module->import; } - - if(Consts::GTK_VERSION==2){ - require "widget2.pl"; + require "widget2.pl"; }else{ - require "widget3.pl"; + require "widget3.pl"; } - - - - - - 1; diff --git a/mpsoc/perl_gui/lib/perl/widget2.pl b/mpsoc/perl_gui/lib/perl/widget2.pl index ce90f2b..fb8c72f 100755 --- a/mpsoc/perl_gui/lib/perl/widget2.pl +++ b/mpsoc/perl_gui/lib/perl/widget2.pl @@ -2,418 +2,355 @@ #use Gtk2 '-init'; use strict; use warnings; - use Data::Dumper; use Gtk2::SourceView2; use Consts; - -require "common.pl"; - +require "common.pl"; use FindBin; use lib $FindBin::Bin; use IO::CaptureOutput qw(capture qxx qxy); - use ColorButton; use HexSpin2; - - use Gtk2::Pango; -#use Tk::Animation; +#use Tk::Animation; our %glob_setting; - ############## # combo box ############# sub gen_combo{ - my ($combo_list, $combo_active_pos)= @_; - my $combo = Gtk2::ComboBox->new_text; - - combo_set_names($combo,$combo_list); - $combo->set_active($combo_active_pos) if(defined $combo_active_pos); - - #my $font = Gtk2::Pango::FontDescription->from_string('Tahoma 5'); - #$combo->modify_font($font); - - - return $combo; + my ($combo_list, $combo_active_pos)= @_; + my $combo = Gtk2::ComboBox->new_text; + combo_set_names($combo,$combo_list); + $combo->set_active($combo_active_pos) if(defined $combo_active_pos); + #my $font = Gtk2::Pango::FontDescription->from_string('Tahoma 5'); + #$combo->modify_font($font); + return $combo; } - sub combo_set_names { - my ( $combo, $list_ref ) = @_; - my @list=@{$list_ref}; - #print "$list[0]\n"; - for my $item (@list){$combo->append_text($item);} + my ( $combo, $list_ref ) = @_; + my @list=@{$list_ref}; + #print "$list[0]\n"; + for my $item (@list){$combo->append_text($item);} } - sub gen_combo_help { - my ($help, @combo_list, $pos)= @_; - my $box = def_hbox(FALSE, 0); - my $combo= gen_combo(@combo_list, $pos); - my $button=def_image_button("icons/help.png"); - - $button->signal_connect("clicked" => sub {message_dialog($help);}); - - $box->pack_start( $combo, FALSE, FALSE, 3); - $box->pack_start( $button, FALSE, FALSE, 3); - $box->show_all; - - return ($box,$combo); -} - - + my ($help, @combo_list, $pos)= @_; + my $box = def_hbox(FALSE, 0); + my $combo= gen_combo(@combo_list, $pos); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $combo, FALSE, FALSE, 3); + $box->pack_start( $button, FALSE, FALSE, 3); + $box->show_all; + return ($box,$combo); +} + sub def_h_labeled_combo{ - my ($label_name,$combo_list,$combo_active_pos)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name); - my $combo= gen_combo($combo_list, $combo_active_pos); - $box->pack_start( $label, FALSE, FALSE, 3); - $box->pack_start( $combo, FALSE, TRUE, 3); - return ($box,$combo); -} + my ($label_name,$combo_list,$combo_active_pos)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name); + my $combo= gen_combo($combo_list, $combo_active_pos); + $box->pack_start( $label, FALSE, FALSE, 3); + $box->pack_start( $combo, FALSE, TRUE, 3); + return ($box,$combo); +} sub def_h_labeled_combo_scaled{ - my ($label_name,$combo_list,$combo_active_pos,$label_w,$comb_w)=@_; - my $table= def_table(1,3,TRUE); - my $label= gen_label_in_left($label_name); - my $combo= gen_combo($combo_list, $combo_active_pos); - $table->attach_defaults ($label, 0, $label_w, 0, 1); - $table->attach_defaults ($combo, 1, $label_w+$comb_w, 0, 1); - return ($table,$combo); -} - + my ($label_name,$combo_list,$combo_active_pos,$label_w,$comb_w)=@_; + my $table= def_table(1,3,TRUE); + my $label= gen_label_in_left($label_name); + my $combo= gen_combo($combo_list, $combo_active_pos); + $table->attach_defaults ($label, 0, $label_w, 0, 1); + $table->attach_defaults ($combo, 1, $label_w+$comb_w, 0, 1); + return ($table,$combo); +} sub gen_combo_model{ - my $ref=shift; - my %inputs=%{$ref}; - my $store = Gtk2::TreeStore->new('Glib::String'); - for my $i (sort { $a cmp $b} keys %inputs ) { - my $iter = $store->append(undef); - - $store->set($iter, 0, $i); - for my $capital (sort { $a cmp $b} keys %{$inputs{$i}}) { - my $iter2 = $store->append($iter); - $store->set($iter2, 0, $capital); - } - } - return $store; - + my $ref=shift; + my %inputs=%{$ref}; + my $store = Gtk2::TreeStore->new('Glib::String'); + for my $i (sort { $a cmp $b} keys %inputs ) { + my $iter = $store->append(undef); + $store->set($iter, 0, $i); + for my $capital (sort { $a cmp $b} keys %{$inputs{$i}}) { + my $iter2 = $store->append($iter); + $store->set($iter2, 0, $capital); + } + } + return $store; } sub gen_tree_combo{ - my $model=shift; - my $combo = Gtk2::ComboBox->new_with_model($model); - my $renderer = Gtk2::CellRendererText->new(); - $combo->pack_start($renderer, TRUE); - $combo->set_attributes($renderer, "text", 0); - $combo->set_cell_data_func($renderer, \&is_capital_sensitive); - return $combo; - + my $model=shift; + my $combo = Gtk2::ComboBox->new_with_model($model); + my $renderer = Gtk2::CellRendererText->new(); + $combo->pack_start($renderer, TRUE); + $combo->set_attributes($renderer, "text", 0); + $combo->set_cell_data_func($renderer, \&is_capital_sensitive); + return $combo; } - sub TreePath_new_from_indices { - my @indices =@_; - my $path = Gtk2::TreePath->new_from_indices(@indices); - return $path; - + my @indices =@_; + my $path = Gtk2::TreePath->new_from_indices(@indices); + return $path; } - ############## # spin button ############# sub gen_spin{ - my ($min,$max,$step,$digit)= @_; - - return Gtk2::SpinButton->new_with_range ($min, $max, $step); - if(!defined $digit){ - my $d1 = get_float_precision($min); - my $d2 = get_float_precision($max); - my $d3 = get_float_precision($step); - $digit = ($d1 >$d2)? $d1 : $d2; - $digit = $d3 if($d3>$digit); - } - print "($min,$max,$step,$digit)\n"; - return Gtk2::SpinButton->new_with_range ($min, $max, $step) if($digit ==0); - return gen_spin_float($min,$max,$step,$digit); + my ($min,$max,$step,$digit)= @_; + return Gtk2::SpinButton->new_with_range ($min, $max, $step); + if(!defined $digit){ + my $d1 = get_float_precision($min); + my $d2 = get_float_precision($max); + my $d3 = get_float_precision($step); + $digit = ($d1 >$d2)? $d1 : $d2; + $digit = $d3 if($d3>$digit); + } + print "($min,$max,$step,$digit)\n"; + return Gtk2::SpinButton->new_with_range ($min, $max, $step) if($digit ==0); + return gen_spin_float($min,$max,$step,$digit); } sub get_float_precision{ - my $num=shift; - my $digit = length(($num =~ /\.(.*)/)[0]); - $digit=0 if(!defined $digit); - return $digit; + my $num=shift; + my $digit = length(($num =~ /\.(.*)/)[0]); + $digit=0 if(!defined $digit); + return $digit; } sub gen_spin_float{ - my ($min,$max,$step,$digit)= @_; - #$page_inc = ($max - $min)/ - my $adj = Gtk2::Adjustment->new (0, $min, $max, $step,3.1, 0); - my $spinner = Gtk2::SpinButton->new ($adj, 1.0,$digit); - return $spinner; + my ($min,$max,$step,$digit)= @_; + #$page_inc = ($max - $min)/ + my $adj = Gtk2::Adjustment->new (0, $min, $max, $step,3.1, 0); + my $spinner = Gtk2::SpinButton->new ($adj, 1.0,$digit); + return $spinner; } - sub gen_spin_help { - my ($help, $min,$max,$step,$digit)= @_; - my $box = def_hbox(FALSE, 0); - my $spin= gen_spin($min,$max,$step,$digit); - my $button=def_image_button("icons/help.png"); - - $button->signal_connect("clicked" => sub {message_dialog($help);}); - - $box->pack_start( $spin, FALSE, FALSE, 3); - $box->pack_start( $button, FALSE, FALSE, 3); - $box->show_all; - - return ($box,$spin); + my ($help, $min,$max,$step,$digit)= @_; + my $box = def_hbox(FALSE, 0); + my $spin= gen_spin($min,$max,$step,$digit); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $spin, FALSE, FALSE, 3); + $box->pack_start( $button, FALSE, FALSE, 3); + $box->show_all; + return ($box,$spin); } - ############# # entry ############# sub gen_entry{ - my ($initial) = @_; - my $entry = Gtk2::Entry->new; - if(defined $initial){ $entry->set_text($initial)}; - return $entry; + my ($initial) = @_; + my $entry = Gtk2::Entry->new; + if(defined $initial){ $entry->set_text($initial)}; + return $entry; } - sub gen_entry_new_with_max_length{ - my ($n,$initial) = @_; - my $entry = Gtk2::Entry->new_with_max_length ($n); - if(defined $initial){ $entry->set_text($initial)}; - return $entry; + my ($n,$initial) = @_; + my $entry = Gtk2::Entry->new_with_max_length ($n); + if(defined $initial){ $entry->set_text($initial)}; + return $entry; } - - sub gen_entry_help{ - my ($help, $init)= @_; - my $box = def_hbox(FALSE, 0); - my $entry= gen_entry ($init); - my $button=def_image_button("icons/help.png"); - - $button->signal_connect("clicked" => sub {message_dialog($help);}); - - $box->pack_start( $entry, FALSE, FALSE, 3); - $box->pack_start( $button, FALSE, FALSE, 3); - $box->show_all; - - return ($box,$entry); + my ($help, $init)= @_; + my $box = def_hbox(FALSE, 0); + my $entry= gen_entry ($init); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $entry, FALSE, FALSE, 3); + $box->pack_start( $button, FALSE, FALSE, 3); + $box->show_all; + return ($box,$entry); } sub def_h_labeled_entry{ - my ($label_name,$initial)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name); - my $entry =gen_entry($initial); - $box->pack_start( $label, FALSE, FALSE, 3); - $box->pack_start( $entry, FALSE, FALSE, 3); - return ($box,$entry); - + my ($label_name,$initial)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name); + my $entry =gen_entry($initial); + $box->pack_start( $label, FALSE, FALSE, 3); + $box->pack_start( $entry, FALSE, FALSE, 3); + return ($box,$entry); } sub def_h_labeled_entry_help{ - my ($help,$label_name,$initial)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name); - my ($b,$entry) =gen_entry_help($help,$initial); - $box->pack_start( $label, FALSE, FALSE, 3); - $box->pack_start( $b, FALSE, FALSE, 3); - return ($box,$entry); - -} - + my ($help,$label_name,$initial)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name); + my ($b,$entry) =gen_entry_help($help,$initial); + $box->pack_start( $label, FALSE, FALSE, 3); + $box->pack_start( $b, FALSE, FALSE, 3); + return ($box,$entry); +} ############## # ComboBoxEntry ############## - sub gen_combo_entry{ - my ($list_ref,$pos)=@_; - my @list=@{$list_ref}; - - my $combo_box_entry = Gtk2::ComboBoxEntry->new_text; - foreach my $p (@list){ - $combo_box_entry->append_text($p); - } - $pos=0 if(! defined $pos ); - $combo_box_entry->set_active($pos); - return $combo_box_entry; + my ($list_ref,$pos)=@_; + my @list=@{$list_ref}; + my $combo_box_entry = Gtk2::ComboBoxEntry->new_text; + foreach my $p (@list){ + $combo_box_entry->append_text($p); + } + $pos=0 if(! defined $pos ); + $combo_box_entry->set_active($pos); + return $combo_box_entry; } - sub combo_entry_get_chiled{ - my $combentry =shift; - return $combentry->child; + my $combentry =shift; + return $combentry->child; } - - - sub update_combo_entry_content { - my ($self,$content,$pos)=@_; - my @combo_list=split(/\s*,\s*/,$content) if(defined $content); - foreach my $p (@combo_list){ - $self->append_text($p); - } - $pos=0 if(! defined $pos ); - $self->set_active($pos); + my ($self,$content,$pos)=@_; + my @combo_list=split(/\s*,\s*/,$content) if(defined $content); + foreach my $p (@combo_list){ + $self->append_text($p); + } + $pos=0 if(! defined $pos ); + $self->set_active($pos); } ########### # checkbutton ########### - sub def_h_labeled_checkbutton{ - my ($label_name)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name) if (defined $label_name); - my $check= Gtk2::CheckButton->new; - #if($status==1) $check-> - $box->pack_start( $label, FALSE, FALSE, 3) if (defined $label_name); - $box->pack_start( $check, FALSE, FALSE, 3); - return ($box,$check); - -} + my ($label_name)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name) if (defined $label_name); + my $check= Gtk2::CheckButton->new; + #if($status==1) $check-> + $box->pack_start( $label, FALSE, FALSE, 3) if (defined $label_name); + $box->pack_start( $check, FALSE, FALSE, 3); + return ($box,$check); +} sub gen_checkbutton{ - my $label=shift; - return Gtk2::CheckButton->new($label) if (defined $label); - return Gtk2::CheckButton->new; + my $label=shift; + return Gtk2::CheckButton->new($label) if (defined $label); + return Gtk2::CheckButton->new; } - ############# # label ############ - sub gen_label_in_left{ - my ($data)=@_; - my $label = Gtk2::Label->new($data); - $label->set_alignment( 0, 0.5 ); - #my $font = Gtk2::Pango::FontDescription->from_string('Tahoma 5'); - #$label->modify_font($font); - return $label; + my ($data)=@_; + my $label = Gtk2::Label->new($data); + $label->set_alignment( 0, 0.5 ); + #my $font = Gtk2::Pango::FontDescription->from_string('Tahoma 5'); + #$label->modify_font($font); + return $label; } - sub gen_label_in_center{ - my ($data)=@_; - my $label = Gtk2::Label->new($data); - return $label; + my ($data)=@_; + my $label = Gtk2::Label->new($data); + return $label; } sub def_label{ - my @data=@_; - my $label = Gtk2::Label->new(@data); - $label->set_alignment( 0, 0.5 ); - return $label; - + my @data=@_; + my $label = Gtk2::Label->new(@data); + $label->set_alignment( 0, 0.5 ); + return $label; } - sub box_label{ - my( $homogeneous, $spacing, $name)=@_; - my $box=def_hbox($homogeneous, $spacing); - my $label= def_label($name); - $box->pack_start( $label, FALSE, FALSE, 3); - return $box; + my( $homogeneous, $spacing, $name)=@_; + my $box=def_hbox($homogeneous, $spacing); + my $label= def_label($name); + $box->pack_start( $label, FALSE, FALSE, 3); + return $box; } - sub def_title_box{ - my( $homogeneous, $spacing, @labels)=@_; - my $box=def_hbox($homogeneous, $spacing); - foreach my $label (@labels){ - my $labelbox=box_label($homogeneous, $spacing, $label); - $box->pack_start( $labelbox, FALSE, FALSE, 3); - } - return $box; -} - - -sub gen_label_help { - my ($help, $label_name)= @_; - my $box = def_hbox(FALSE, 0); - my $label= gen_label_in_left($label_name); - my $button=def_image_button("icons/help.png"); - $button->signal_connect("clicked" => sub {message_dialog($help);}); - $box->pack_start( $label, FALSE, FALSE, 0); - $box->pack_start( $button, FALSE, FALSE, 0); - $box->set_spacing (0); - $box->show_all; - return $box; + my( $homogeneous, $spacing, @labels)=@_; + my $box=def_hbox($homogeneous, $spacing); + foreach my $label (@labels){ + my $labelbox=box_label($homogeneous, $spacing, $label); + $box->pack_start( $labelbox, FALSE, FALSE, 3); + } + return $box; } -sub gen_label_with_mnemonic { - my $name=shift; - Gtk2::Label->new_with_mnemonic($name); +sub gen_label_help { + my ($help, $label_name)= @_; + my $box = def_hbox(FALSE, 0); + my $label= gen_label_in_left($label_name); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $label, FALSE, FALSE, 0); + $box->pack_start( $button, FALSE, FALSE, 0); + $box->set_spacing (0); + $box->show_all; + return $box; +} +sub gen_label_with_mnemonic { + my $name=shift; + Gtk2::Label->new_with_mnemonic($name); } - + ############## # button ############# - sub button_box{ # create a new button - my $label=@_; - my $button = Gtk2::Button->new_from_stock($label); - my $box=def_hbox(TRUE,5); - $box->pack_start($button, FALSE, FALSE,0); - - return ($box,$button); - + my $label=@_; + my $button = Gtk2::Button->new_from_stock($label); + my $box=def_hbox(TRUE,5); + $box->pack_start($button, FALSE, FALSE,0); + return ($box,$button); } - sub get_icon_pixbuff{ my $icon_file=shift; - my $size; + my $size; if ($glob_setting{'ICON_SIZE'} eq 'default'){ - my $font_size=get_defualt_font_size(); - $size=($font_size *2.5); + my $font_size=get_defualt_font_size(); + $size=($font_size *2.5); }else{ - $size = int ($glob_setting{'ICON_SIZE'}); + $size = int ($glob_setting{'ICON_SIZE'}); } - my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale($icon_file,$size,$size,FALSE); - return $pixbuf; + my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale($icon_file,$size,$size,FALSE); + return $pixbuf; } - - sub def_icon{ - my $icon_file=shift; - return Gtk2::Image->new_from_pixbuf(get_icon_pixbuff($icon_file)); + my $icon_file=shift; + return Gtk2::Image->new_from_pixbuf(get_icon_pixbuff($icon_file)); } sub call_gtk_drag_finish{ - my ($context,$a,$b,$time)=@_; - $context->finish (0, 0, $time); + my ($context,$a,$b,$time)=@_; + $context->finish (0, 0, $time); } - - sub add_drag_dest_set{ - my ($widget,$a,$b,$c) = @_; - #Create a target table to receive drops - my @target_table = ( + my ($widget,$a,$b,$c) = @_; + #Create a target table to receive drops + my @target_table = ( {'target' => $a, 'flags' => $b, 'info' => $c }, - ); - $widget->drag_dest_set('all', ['copy'], @target_table); + ); + $widget->drag_dest_set('all', ['copy'], @target_table); } sub add_drag_source { - my ($widget,$a,$b,$c) = @_; - $widget->drag_source_set ( + my ($widget,$a,$b,$c) = @_; + $widget->drag_source_set ( ['button1_mask', 'button3_mask'], ['copy'], { @@ -425,1254 +362,1050 @@ sub add_drag_source { } sub drag_set_icon_pixbuf { - my ($icon_view,$icon_pixbuf)=@_; - $icon_view->drag_source_set_icon_pixbuf ($icon_pixbuf); + my ($icon_view,$icon_pixbuf)=@_; + $icon_view->drag_source_set_icon_pixbuf ($icon_pixbuf); } sub gen_iconview { - my ($tree_model,$marc_col,$pix_con)=@_; - my $icon_view = Gtk2::IconView->new_with_model($tree_model); + my ($tree_model,$marc_col,$pix_con)=@_; + my $icon_view = Gtk2::IconView->new_with_model($tree_model); $icon_view->set_markup_column($marc_col); $icon_view->set_pixbuf_column($pix_con); - return $icon_view; + return $icon_view; } - sub add_frame_to_image{ - my $image=shift; - my $align = Gtk2::Alignment->new (0.5, 0.5, 0, 0); - my $frame = Gtk2::Frame->new; - $frame->set_shadow_type ('in'); - # Animation - $frame->add ($image); - $align->add ($frame); - return $align; + my $image=shift; + my $align = Gtk2::Alignment->new (0.5, 0.5, 0, 0); + my $frame = Gtk2::Frame->new; + $frame->set_shadow_type ('in'); + # Animation + $frame->add ($image); + $align->add ($frame); + return $align; } sub gen_frame { - return Gtk2::Frame->new; + return Gtk2::Frame->new; } - - sub new_image_from_file{ - return Gtk2::Image->new_from_file (@_); + return Gtk2::Image->new_from_file (@_); } - sub gen_pixbuf{ - my $file=shift; - return Gtk2::Gdk::Pixbuf->new_from_file($file); + my $file=shift; + return Gtk2::Gdk::Pixbuf->new_from_file($file); } sub open_image{ - my ($image_file,$x,$y,$unit)=@_; - if(defined $unit){ - my($width,$hight)=max_win_size(); - if($unit eq 'percent'){ - $x= ($x * $width)/100; - $y= ($y * $hight)/100; - } # else its pixels - - } - $image_file ="icons/blank.png" unless(-f $image_file); - my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale($image_file,$x,$y,TRUE); - my $image = Gtk2::Image->new_from_pixbuf($pixbuf); - return $image; + my ($image_file,$x,$y,$unit)=@_; + if(defined $unit){ + my($width,$hight)=max_win_size(); + if($unit eq 'percent'){ + $x= ($x * $width)/100; + $y= ($y * $hight)/100; + } # else its pixels + } + $image_file ="icons/blank.png" unless(-f $image_file); + my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale($image_file,$x,$y,TRUE); + my $image = Gtk2::Image->new_from_pixbuf($pixbuf); + return $image; } sub open_inline_image{ - my ($image_string,$x,$y,$unit)=@_; - if(defined $unit){ - my($width,$hight)=max_win_size(); - if($unit eq 'percent'){ - $x= ($x * $width)/100; - $y= ($y * $hight)/100; - } # else its pixels - - } - my $pixbuf = do { + my ($image_string,$x,$y,$unit)=@_; + if(defined $unit){ + my($width,$hight)=max_win_size(); + if($unit eq 'percent'){ + $x= ($x * $width)/100; + $y= ($y * $hight)/100; + } # else its pixels + } + my $pixbuf = do { my $loader = Gtk2::Gdk::PixbufLoader->new(); $loader->set_size( $x,$y ) if (defined $y); - $loader->write( $image_string ); + $loader->write( $image_string ); $loader->close(); $loader->get_pixbuf(); }; - - - my $image = Gtk2::Image->new_from_pixbuf($pixbuf); - - return $image; + my $image = Gtk2::Image->new_from_pixbuf($pixbuf); + return $image; } sub find_icon{ - my $file =shift; - return $file if(-f $file); #called from perl_gui - return "../../$file"; #called from lib/perl + my $file =shift; + return $file if(-f $file); #called from perl_gui + return "../../$file"; #called from lib/perl } sub def_image_button{ - my ($image_file, $label_text, $homogeneous, $mnemonic)=@_; - # create box for image and label - $homogeneous = FALSE if(!defined $homogeneous); - my $box = def_hbox($homogeneous,0); - my $image; - $image_file = find_icon( $image_file); - $image = def_icon($image_file) if(-f $image_file); - - # now on to the image stuff - #my $image = Gtk2::Image->new_from_file($image_file); - $box->pack_start($image, FALSE, FALSE, 0) if(defined $image); - $box->set_border_width(0); - $box->set_spacing (0); - # Create a label for the button - if(defined $label_text ) { - my $label; - $label = Gtk2::Label->new(" $label_text") unless (defined $mnemonic); - $label = Gtk2::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); - $box->pack_start($label, FALSE, FALSE, 0); - } - - my $button = Gtk2::Button->new(); - $button->add($box); - $button->set_border_width(0); - $button->show_all; - return $button; + my ($image_file, $label_text, $homogeneous, $mnemonic)=@_; + # create box for image and label + $homogeneous = FALSE if(!defined $homogeneous); + my $box = def_hbox($homogeneous,0); + my $image; + $image_file = find_icon( $image_file); + $image = def_icon($image_file) if(-f $image_file); + # now on to the image stuff + #my $image = Gtk2::Image->new_from_file($image_file); + $box->pack_start($image, FALSE, FALSE, 0) if(defined $image); + $box->set_border_width(0); + $box->set_spacing (0); + # Create a label for the button + if(defined $label_text ) { + my $label; + $label = Gtk2::Label->new(" $label_text") unless (defined $mnemonic); + $label = Gtk2::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); + $box->pack_start($label, FALSE, FALSE, 0); + } + my $button = Gtk2::Button->new(); + $button->add($box); + $button->set_border_width(0); + $button->show_all; + return $button; } sub def_button{ - my ($label_text)=@_; - my $label = Gtk2::Label->new("$label_text") if (defined $label_text); - my $button= Gtk2::Button->new(); - $button->add($label) if (defined $label_text); - return $button; -} - + my ($label_text)=@_; + my $label = Gtk2::Label->new("$label_text") if (defined $label_text); + my $button= Gtk2::Button->new(); + $button->add($label) if (defined $label_text); + return $button; +} sub def_image_label{ - my ($image_file, $label_text,$mnemonic)=@_; - # create box for image and label - my $box = def_hbox(FALSE,1); - # now on to the image stuff - my $image = def_icon($image_file); - $box->pack_start($image, TRUE, FALSE, 0); - # Create a label for the button - if(defined $label_text ) { - my $label; - $label = Gtk2::Label->new(" $label_text") unless (defined $mnemonic); - $label = Gtk2::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); - $box->pack_start($label, TRUE, FALSE, 0); - } - - return $box; - + my ($image_file, $label_text,$mnemonic)=@_; + # create box for image and label + my $box = def_hbox(FALSE,1); + # now on to the image stuff + my $image = def_icon($image_file); + $box->pack_start($image, TRUE, FALSE, 0); + # Create a label for the button + if(defined $label_text ) { + my $label; + $label = Gtk2::Label->new(" $label_text") unless (defined $mnemonic); + $label = Gtk2::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); + $box->pack_start($label, TRUE, FALSE, 0); + } + return $box; } - -sub gen_button_message { - my ($help, $image_file,$label_name)= @_; - my $box = def_hbox(FALSE, 0); - my $label= gen_label_in_center($label_name) if(defined $label_name); - my $button=def_image_button($image_file); - - if(defined $help ){$button->signal_connect("clicked" => sub {message_dialog($help);});} - - $box->pack_start( $label, FALSE, FALSE, 0) if(defined $label_name); - $box->pack_start( $button, FALSE, FALSE, 0); - $box->set_border_width(0); - $box->set_spacing (0); - $box->show_all; - - return $box; - - +sub gen_button_message { + my ($help, $image_file,$label_name)= @_; + my $box = def_hbox(FALSE, 0); + my $label= gen_label_in_center($label_name) if(defined $label_name); + my $button=def_image_button($image_file); + if(defined $help ){$button->signal_connect("clicked" => sub {message_dialog($help);});} + $box->pack_start( $label, FALSE, FALSE, 0) if(defined $label_name); + $box->pack_start( $button, FALSE, FALSE, 0); + $box->set_border_width(0); + $box->set_spacing (0); + $box->show_all; + return $box; } - sub def_colored_button{ - my ($label_text,$color_num)=@_; - # create box for image and label - my $box = def_hbox(FALSE,0); - my $font_size=get_defualt_font_size(); - - my ($red,$green,$blue) = get_color($color_num); - my $button = ColorButton->new (red => $red, green => $green, blue => $blue, label=>"$label_text"); - - $button->set_border_width(0); - $button->show_all; - return $button; + my ($label_text,$color_num)=@_; + # create box for image and label + my $box = def_hbox(FALSE,0); + my $font_size=get_defualt_font_size(); + my ($red,$green,$blue) = get_color($color_num); + my $button = ColorButton->new (red => $red, green => $green, blue => $blue, label=>"$label_text"); + $button->set_border_width(0); + $button->show_all; + return $button; } - - - - sub entry_set_text_color { - my ($entry,$color_num)=@_; - my ($red,$green,$blue) = get_color($color_num); - my $color = Gtk2::Gdk::Color->new ($red,$green,$blue); - $entry->modify_text('normal' , $color); + my ($entry,$color_num)=@_; + my ($red,$green,$blue) = get_color($color_num); + my $color = Gtk2::Gdk::Color->new ($red,$green,$blue); + $entry->modify_text('normal' , $color); } - - - - - - - sub show_gif{ - my $gif = shift; - $gif=find_icon( $gif); - my $vbox = Gtk2::HBox->new (TRUE, 8); + my $gif = shift; + $gif=find_icon( $gif); + my $vbox = Gtk2::HBox->new (TRUE, 8); my $filename; - eval { - $filename = main::demo_find_file ($gif); - }; + eval { + $filename = main::demo_find_file ($gif); + }; my $image = Gtk2::Image->new_from_file ($gif); $vbox->set_border_width (4); my $align = Gtk2::Alignment->new (0.5, 0.5, 0, 0); - my $frame = Gtk2::Frame->new; - $frame->set_shadow_type ('in'); + my $frame = Gtk2::Frame->new; + $frame->set_shadow_type ('in'); # Animation $frame->add ($image); $align->add ($frame); - $vbox->pack_start ($align, FALSE, FALSE, 0); - return $vbox; + $vbox->pack_start ($align, FALSE, FALSE, 0); + return $vbox; } sub gen_radiobutton { - my ($from,$label,$icon,$tip) =@_; - my $rbtn = (defined $from )? Gtk2::RadioToolButton->new_from_widget($from) : Gtk2::RadioToolButton->new (undef); - $rbtn->set_label ($label) if(defined $label); - $rbtn->set_icon_widget (def_icon($icon)) if(defined $icon); - set_tip($rbtn, $tip) if(defined $tip); - return $rbtn; + my ($from,$label,$icon,$tip) =@_; + my $rbtn = (defined $from )? Gtk2::RadioToolButton->new_from_widget($from) : Gtk2::RadioToolButton->new (undef); + $rbtn->set_label ($label) if(defined $label); + $rbtn->set_icon_widget (def_icon($icon)) if(defined $icon); + set_tip($rbtn, $tip) if(defined $tip); + return $rbtn; } sub gen_colored_label{ - my ($label_text, $color_num)=@_; - - my $color_hex = get_color_hex_string($color_num); - my $label = Gtk2::Label->new($label_text); - $label->set_markup("new($label_text); + $label->set_markup("$label_text"); - - return $label; + return $label; } - ############ -# message_dialog +# message_dialog ############ - sub message_dialog { - my ($message,$type)=@_; - $type = 'info' if (!defined $type); - my $window; - my $dialog = Gtk2::MessageDialog->new ($window, - [qw/modal destroy-with-parent/], - $type, - 'ok', - $message); - $dialog->run; - $dialog->destroy; - + my ($message,$type)=@_; + $type = 'info' if (!defined $type); + my $window; + my $dialog = Gtk2::MessageDialog->new ($window, + [qw/modal destroy-with-parent/], + $type, + 'ok', + $message); + $dialog->run; + $dialog->destroy; } - - sub set_tip{ - my ($widget,$tip)=@_; - my $tooltips = Gtk2::Tooltips->new; - $tooltips->set_tip($widget,$tip); - - + my ($widget,$tip)=@_; + my $tooltips = Gtk2::Tooltips->new; + $tooltips->set_tip($widget,$tip); } - sub yes_no_dialog { - my ($message)=@_; - my $dialog = Gtk2::MessageDialog->new (my $window, - 'destroy-with-parent', - 'question', # message type - 'yes-no', # which set of buttons? - "$message"); - my $response = $dialog->run; - $dialog->destroy; - return $response; + my ($message)=@_; + my $dialog = Gtk2::MessageDialog->new (my $window, + 'destroy-with-parent', + 'question', # message type + 'yes-no', # which set of buttons? + "$message"); + my $response = $dialog->run; + $dialog->destroy; + return $response; } sub create_dialog { - my ($message_head,$message_body,$icon,@buttons)=@_; - # create a new dialog with some buttons - one stock, one not. - my %hash1; - my %hash2; - my $i=0; - foreach my $b (@buttons){ - $hash1{$b}=$i; - $hash2{$i}=$b; - $i++; - } - - my $dialog = Gtk2::Dialog->new ( - " ", - Gtk2::Window->new('toplevel'), - [qw/modal destroy-with-parent/], + my ($message_head,$message_body,$icon,@buttons)=@_; + # create a new dialog with some buttons - one stock, one not. + my %hash1; + my %hash2; + my $i=0; + foreach my $b (@buttons){ + $hash1{$b}=$i; + $hash2{$i}=$b; + $i++; + } + my $dialog = Gtk2::Dialog->new ( + " ", + Gtk2::Window->new('toplevel'), + [qw/modal destroy-with-parent/], %hash1 ); - my $content = $dialog->get_content_area (); - - my $table = def_table(1,3,TRUE); - $table->attach (def_icon($icon) , 0, 1, 0, 2,'expand','expand',2,2) if(defined $icon); - if(defined $message_head){ - my $hd=gen_label_in_left($message_head); - $hd->set_markup("$message_head"); - $table->attach ($hd , 1, 10, 0, 1,'fill','shrink',2,2); - } - if(defined $message_head){ - $table->attach (gen_label_in_left($message_body) , 2, 10, 1, 2,'fill','shrink',2,2); - } - - $content->add ($table); - $content->show_all; - - $dialog->set_transient_for (Gtk2::Window->new('toplevel'));#just to get rid of transient warning - my $response = $dialog->run; - - $dialog->destroy; - return $hash2{$response}; -} - + my $content = $dialog->get_content_area (); + my $table = def_table(1,3,TRUE); + $table->attach (def_icon($icon) , 0, 1, 0, 2,'expand','expand',2,2) if(defined $icon); + if(defined $message_head){ + my $hd=gen_label_in_left($message_head); + $hd->set_markup("$message_head"); + $table->attach ($hd , 1, 10, 0, 1,'fill','shrink',2,2); + } + if(defined $message_head){ + $table->attach (gen_label_in_left($message_body) , 2, 10, 1, 2,'fill','shrink',2,2); + } + $content->add ($table); + $content->show_all; + $dialog->set_transient_for (Gtk2::Window->new('toplevel'));#just to get rid of transient warning + my $response = $dialog->run; + $dialog->destroy; + return $hash2{$response}; +} ############ # window ########### - sub def_win { - my @titel=shift; - my $window = Gtk2::Window->new('toplevel'); - $window->set_title(@titel); - $window->set_position("center"); - $window->set_default_size(100, 100); - $window->set_border_width(20); - $window->signal_connect (delete_event => sub { Gtk2->main_quit }); - return $window; - -} - + my @titel=shift; + my $window = Gtk2::Window->new('toplevel'); + $window->set_title(@titel); + $window->set_position("center"); + $window->set_default_size(100, 100); + $window->set_border_width(20); + $window->signal_connect (delete_event => sub { Gtk2->main_quit }); + return $window; +} sub def_win_size { - my $x=shift; - my $y=shift; - my @titel=shift; - my $window = Gtk2::Window->new('toplevel'); - $window->set_title(@titel); - $window->set_position("center"); - $window->set_default_size($x, $y); - $window->set_border_width(20); - $window->signal_connect (delete_event => sub { Gtk2->main_quit }); - return $window; - -} - + my $x=shift; + my $y=shift; + my @titel=shift; + my $window = Gtk2::Window->new('toplevel'); + $window->set_title(@titel); + $window->set_position("center"); + $window->set_default_size($x, $y); + $window->set_border_width(20); + $window->signal_connect (delete_event => sub { Gtk2->main_quit }); + return $window; +} sub def_popwin_size { - my ($x,$y,$titel,$unit)=@_; - if(defined $unit){ - my($width,$hight)=max_win_size(); - if($unit eq 'percent'){ - $x= ($x * $width)/100; - $y= ($y * $hight)/100; - } # else its pixels - - } - #my $window = Gtk2::Window->new('popup'); - my $window = Gtk2::Window->new('toplevel'); - $window->set_title($titel); - $window->set_position("center"); - $window->set_default_size($x, $y); - $window->set_border_width(20); - #$window->signal_connect (delete_event => sub { $window->destroy }); - return $window; - -} - - - - + my ($x,$y,$titel,$unit)=@_; + if(defined $unit){ + my($width,$hight)=max_win_size(); + if($unit eq 'percent'){ + $x= ($x * $width)/100; + $y= ($y * $hight)/100; + } # else its pixels + } + #my $window = Gtk2::Window->new('popup'); + my $window = Gtk2::Window->new('toplevel'); + $window->set_title($titel); + $window->set_position("center"); + $window->set_default_size($x, $y); + $window->set_border_width(20); + #$window->signal_connect (delete_event => sub { $window->destroy }); + return $window; +} sub def_scrolled_window_box{ - - my $window = def_popwin_size(@_); - my $box=def_vbox(TRUE,5); - my $scrolled_window = new Gtk2::ScrolledWindow (undef, undef); - $scrolled_window->set_policy( "automatic", "automatic" ); - $scrolled_window->add_with_viewport($box); - $window->add($scrolled_window); - $window->show_all; - $box->show_all; - return ($box,$window); - + my $window = def_popwin_size(@_); + my $box=def_vbox(TRUE,5); + my $scrolled_window = new Gtk2::ScrolledWindow (undef, undef); + $scrolled_window->set_policy( "automatic", "automatic" ); + $scrolled_window->add_with_viewport($box); + $window->add($scrolled_window); + $window->show_all; + $box->show_all; + return ($box,$window); } - sub get_default_screen { - return Gtk2::Gdk::Screen->get_default(); + return Gtk2::Gdk::Screen->get_default(); } - - sub get_defualt_font_size{ - return int($glob_setting{'FONT_SIZE'}) if ($glob_setting{'FONT_SIZE'} ne 'default'); - - my($width,$hight)=max_win_size(); - #print "($width,$hight)\n"; - my $font_size=($width>=1600)? 10: - ($width>=1400)? 9: - ($width>=1200)? 9: - ($width>=1000)? 8:7; - #print "$font_size\n"; - return $font_size; + return int($glob_setting{'FONT_SIZE'}) if ($glob_setting{'FONT_SIZE'} ne 'default'); + my($width,$hight)=max_win_size(); + #print "($width,$hight)\n"; + my $font_size= + ($width>=1600)? 10: + ($width>=1400)? 9: + ($width>=1200)? 9: + ($width>=1000)? 8:7; + #print "$font_size\n"; + return $font_size; } - sub set_defualt_font_size{ - my $font_size=get_defualt_font_size(); - #$font_size= int (1.5*$font_size); - Gtk2::Rc->parse_string(<<__); - style "normal" { - font_name ="Verdana $font_size" - } - widget "*" style "normal" + my $font_size=get_defualt_font_size(); + #$font_size= int (1.5*$font_size); + Gtk2::Rc->parse_string(<<__); + style "normal" { + font_name ="Verdana $font_size" + } + widget "*" style "normal" __ - } - - sub add_widget_to_scrolled_win{ - my ($widget,$scrolled_win) =@_; - if(! defined $scrolled_win){ - $scrolled_win = new Gtk2::ScrolledWindow (undef, undef); - $scrolled_win->set_policy( "automatic", "automatic" ); - } - $scrolled_win->add_with_viewport($widget) if(defined $widget); - #$scrolled_win->set_shadow_type('in'); - #$scrolled_win->show_all; - return $scrolled_win; + my ($widget,$scrolled_win) =@_; + if(! defined $scrolled_win){ + $scrolled_win = new Gtk2::ScrolledWindow (undef, undef); + $scrolled_win->set_policy( "automatic", "automatic" ); + } + $scrolled_win->add_with_viewport($widget) if(defined $widget); + #$scrolled_win->set_shadow_type('in'); + #$scrolled_win->show_all; + return $scrolled_win; } sub gen_scr_win_with_adjst { - my ($self,$name)=@_; - my $scrolled_win = new Gtk2::ScrolledWindow (undef, undef); - $scrolled_win->set_policy( "automatic", "automatic" ); - $scrolled_win->signal_connect("destroy"=> sub{ - save_scrolled_win_adj($self,$scrolled_win, $name); - - }); - my $adjast=0; - $scrolled_win->signal_connect("size-allocate"=> sub{ - if($adjast==0){ - load_scrolled_win_adj($self,$scrolled_win, $name); - $adjast=1; - } - - }); - return $scrolled_win; + my ($self,$name)=@_; + my $scrolled_win = new Gtk2::ScrolledWindow (undef, undef); + $scrolled_win->set_policy( "automatic", "automatic" ); + $scrolled_win->signal_connect("destroy"=> sub{ + save_scrolled_win_adj($self,$scrolled_win, $name); + }); + my $adjast=0; + $scrolled_win->signal_connect("size-allocate"=> sub{ + if($adjast==0){ + load_scrolled_win_adj($self,$scrolled_win, $name); + $adjast=1; + } + }); + return $scrolled_win; } - sub save_scrolled_win_adj { - my ($self,$scrolled_win,$name)=@_; - my $ha= $scrolled_win->get_hadjustment(); + my ($self,$scrolled_win,$name)=@_; + my $ha= $scrolled_win->get_hadjustment(); my $va =$scrolled_win->get_vadjustment(); return if(!defined $ha); return if(!defined $va); - save_adj ($self,$ha,$name,"ha"); - save_adj ($self,$va,$name,"va"); + save_adj ($self,$ha,$name,"ha"); + save_adj ($self,$va,$name,"va"); } - sub load_scrolled_win_adj { - my ($self,$scrolled_win,$name)=@_; - my $ha= $scrolled_win->get_hadjustment(); + my ($self,$scrolled_win,$name)=@_; + my $ha= $scrolled_win->get_hadjustment(); my $va =$scrolled_win->get_vadjustment(); - my $h=load_adj ($self,$ha,$name,"ha"); - my $v=load_adj ($self,$va,$name,"va"); - #$ha->set_value($h) if(defined $h); - #$va->set_value($v) if(defined $v); -} - - - - -sub save_adj { - my ($self,$adjustment,$at1,$at2)=@_; - my $value = $adjustment->value; - $self->object_add_attribute($at1,$at2,$value); + my $h=load_adj ($self,$ha,$name,"ha"); + my $v=load_adj ($self,$va,$name,"va"); + #$ha->set_value($h) if(defined $h); + #$va->set_value($v) if(defined $v); } +sub save_adj { + my ($self,$adjustment,$at1,$at2)=@_; + my $value = $adjustment->value; + $self->object_add_attribute($at1,$at2,$value); +} sub load_adj { - my ($self,$adjustment,$at1,$at2)=@_; - return if(!defined $at1); + my ($self,$adjustment,$at1,$at2)=@_; + return if(!defined $at1); my $value= $self->object_get_attribute($at1,$at2); return if(!defined $value); my $lower = $adjustment->lower; my $upper = $adjustment->upper - $adjustment->page_size; - $value= ($value < $lower || $value > $upper ) ? 0 : $value; - - $adjustment->set_value($value); + $value= ($value < $lower || $value > $upper ) ? 0 : $value; + $adjustment->set_value($value); } sub set_pronoc_icon{ - my $window=shift; - my $navIco = gen_pixbuf("./icons/ProNoC.png"); - $window->set_default_icon($navIco); + my $window=shift; + my $navIco = gen_pixbuf("./icons/ProNoC.png"); + $window->set_default_icon($navIco); } ############## -# box +# box ############# - sub def_hbox { - my( $homogeneous, $spacing)=@_; - my $box = Gtk2::HBox->new($homogeneous, $spacing); - $box->set_border_width(2); - return $box; + my( $homogeneous, $spacing)=@_; + my $box = Gtk2::HBox->new($homogeneous, $spacing); + $box->set_border_width(2); + return $box; } sub def_vbox { - my $box = Gtk2::VBox->new(FALSE, 0); - $box->set_border_width(2); - return $box; + my $box = Gtk2::VBox->new(FALSE, 0); + $box->set_border_width(2); + return $box; } sub def_pack_hbox{ - my( $homogeneous, $spacing , @box_list)=@_; - my $box=def_hbox($homogeneous, $spacing); - foreach my $subbox (@box_list){ - $box->pack_start( $subbox, FALSE, FALSE, 3); - } - return $box; - - + my( $homogeneous, $spacing , @box_list)=@_; + my $box=def_hbox($homogeneous, $spacing); + foreach my $subbox (@box_list){ + $box->pack_start( $subbox, FALSE, FALSE, 3); + } + return $box; } sub def_pack_vbox{ - my( $homogeneous, $spacing , @box_list)=@_; - my $box=def_vbox($homogeneous, $spacing); - foreach my $subbox (@box_list){ - $box->pack_start( $subbox, FALSE, FALSE, 3); - } - return $box; - + my( $homogeneous, $spacing , @box_list)=@_; + my $box=def_vbox($homogeneous, $spacing); + foreach my $subbox (@box_list){ + $box->pack_start( $subbox, FALSE, FALSE, 3); + } + return $box; } - ########## # Paned ######### - - sub gen_vpaned { - my ($w1,$loc,$w2) = @_; - my $vpaned = Gtk2::VPaned -> new; - my($width,$hight)=max_win_size(); - - $vpaned -> pack1($w1, TRUE, TRUE); - $vpaned -> set_position ($hight*$loc); - $vpaned -> pack2($w2, TRUE, TRUE); - - return $vpaned; + my ($w1,$loc,$w2) = @_; + my $vpaned = Gtk2::VPaned -> new; + my($width,$hight)=max_win_size(); + $vpaned -> pack1($w1, TRUE, TRUE); + $vpaned -> set_position ($hight*$loc); + $vpaned -> pack2($w2, TRUE, TRUE); + return $vpaned; } - sub gen_hpaned { - my ($w1,$loc,$w2) = @_; - my $hpaned = Gtk2::HPaned -> new; - my($width,$hight)=max_win_size(); - - - $hpaned -> pack1($w1, TRUE, TRUE); - $hpaned -> set_position ($width*$loc); - $hpaned -> pack2($w2, TRUE, TRUE); - - return $hpaned; + my ($w1,$loc,$w2) = @_; + my $hpaned = Gtk2::HPaned -> new; + my($width,$hight)=max_win_size(); + $hpaned -> pack1($w1, TRUE, TRUE); + $hpaned -> set_position ($width*$loc); + $hpaned -> pack2($w2, TRUE, TRUE); + return $hpaned; } sub gen_hpaned_adj { - my ($self,$w1,$loc,$w2,$name) = @_; - my $hpaned = Gtk2::HPaned -> new; - $hpaned -> pack1($w1, TRUE, TRUE); - $hpaned -> pack2($w2, TRUE, TRUE); - - $hpaned->signal_connect("destroy"=> sub{ - my $adj = $hpaned->get_position (); - $self->object_add_attribute("adj",$name,$adj); - }); - - my $val =$self->object_get_attribute("adj",$name); - if(defined $val){ - $hpaned -> set_position ($val); - } else{ - my($width,$hight)=max_win_size(); - $hpaned -> set_position ($width*$loc); - } - - return $hpaned; + my ($self,$w1,$loc,$w2,$name) = @_; + my $hpaned = Gtk2::HPaned -> new; + $hpaned -> pack1($w1, TRUE, TRUE); + $hpaned -> pack2($w2, TRUE, TRUE); + $hpaned->signal_connect("destroy"=> sub{ + my $adj = $hpaned->get_position (); + $self->object_add_attribute("adj",$name,$adj); + }); + my $val =$self->object_get_attribute("adj",$name); + if(defined $val){ + $hpaned -> set_position ($val); + } else{ + my($width,$hight)=max_win_size(); + $hpaned -> set_position ($width*$loc); + } + return $hpaned; } - ############# -# text_view +# text_view ############ - sub create_txview { - my $scrolled_window = Gtk2::ScrolledWindow->new; - $scrolled_window->set_policy ('automatic', 'automatic'); - $scrolled_window->set_shadow_type ('in'); - my $tview = Gtk2::TextView->new(); - $scrolled_window->add ($tview); - $tview->show_all; - # Make it a bit nicer for text. - $tview->set_wrap_mode ('word'); - $tview->set_pixels_above_lines (2); - $tview->set_pixels_below_lines (2); - # $scrolled_window->set_placement('bottom_left' ); - add_colors_to_textview($tview); - - return ($scrolled_window,$tview); + my $scrolled_window = Gtk2::ScrolledWindow->new; + $scrolled_window->set_policy ('automatic', 'automatic'); + $scrolled_window->set_shadow_type ('in'); + my $tview = Gtk2::TextView->new(); + $scrolled_window->add ($tview); + $tview->show_all; + # Make it a bit nicer for text. + $tview->set_wrap_mode ('word'); + $tview->set_pixels_above_lines (2); + $tview->set_pixels_below_lines (2); + # $scrolled_window->set_placement('bottom_left' ); + add_colors_to_textview($tview); + return ($scrolled_window,$tview); } - sub txview_scrol_to_end { - my $tview =shift; - my $buffer = $tview->get_buffer; - my $end_mark = $buffer->create_mark( 'end', $buffer->get_end_iter, 0 ); - $tview->scroll_to_mark( $end_mark, 0.0,0, 0.0, 1.0 ); + my $tview =shift; + my $buffer = $tview->get_buffer; + my $end_mark = $buffer->create_mark( 'end', $buffer->get_end_iter, 0 ); + $tview->scroll_to_mark( $end_mark, 0.0,0, 0.0, 1.0 ); } - - ################# -# table +# table ################ - sub def_table{ - my ($row,$col,$homogeneous)=@_; - my $table = Gtk2::Table->new ($row, $col, $homogeneous); - $table->set_row_spacings (0); - $table->set_col_spacings (0); - return $table; - + my ($row,$col,$homogeneous)=@_; + my $table = Gtk2::Table->new ($row, $col, $homogeneous); + $table->set_row_spacings (0); + $table->set_col_spacings (0); + return $table; } sub attach_widget_to_table { - my ($table,$row,$label,$inf_bt,$widget,$column)=@_; - $column = 0 if(!defined $column); - #$column *=4; - #my $tmp=gen_label_in_left(" "); - if(defined $label) {$table->attach ($label , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} - if(defined $inf_bt) {$table->attach ($inf_bt , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} - if(defined $widget) {$table->attach ($widget , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} - #$table->attach ($tmp , $column+3, $column+4, $row,$row+1,'fill','shrink',2,2); + my ($table,$row,$label,$inf_bt,$widget,$column)=@_; + $column = 0 if(!defined $column); + #$column *=4; + #my $tmp=gen_label_in_left(" "); + if(defined $label) {$table->attach ($label , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} + if(defined $inf_bt) {$table->attach ($inf_bt , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} + if(defined $widget) {$table->attach ($widget , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} + #$table->attach ($tmp , $column+3, $column+4, $row,$row+1,'fill','shrink',2,2); } -sub gen_Hsep { - return Gtk2::HSeparator->new; +sub gen_Hsep { + return Gtk2::HSeparator->new; } -sub gen_Vsep { - return Gtk2::VSeparator->new; +sub gen_Vsep { + return Gtk2::VSeparator->new; } - sub add_Hsep_to_table { - my($table,$col0,$col1,$row)=@_; - my $separator = gen_Hsep(); - $table->attach ($separator ,$col0,$col1 , $row, $row+1,'fill','fill',2,2); + my($table,$col0,$col1,$row)=@_; + my $separator = gen_Hsep(); + $table->attach ($separator ,$col0,$col1 , $row, $row+1,'fill','fill',2,2); } sub add_Vsep_to_table { - my($table,$col,$row1,$row2)=@_; - my $separator = gen_Vsep(); - $table->attach ($separator ,$col,$col+1 , $row1, $row2,'fill','fill',2,2); + my($table,$col,$row1,$row2)=@_; + my $separator = gen_Vsep(); + $table->attach ($separator ,$col,$col+1 , $row1, $row2,'fill','fill',2,2); } - ################## -# show_info +# show_info ################## sub show_info{ - my ($textview,$info)=@_; - #return;# if(!defined $textview_ref); - #print "$textview_ref\n"; - my $buffer = $textview->get_buffer(); - $buffer->set_text($info); - txview_scrol_to_end($textview); + my ($textview,$info)=@_; + #return;# if(!defined $textview_ref); + #print "$textview_ref\n"; + my $buffer = $textview->get_buffer(); + $buffer->set_text($info); + txview_scrol_to_end($textview); } sub add_info{ - my ($textview,$info)=@_; - my $buffer = $textview->get_buffer(); - my $textiter = $buffer->get_end_iter(); - #Insert some text into the buffer - $buffer->insert($textiter,$info); - txview_scrol_to_end($textview); - + my ($textview,$info)=@_; + my $buffer = $textview->get_buffer(); + my $textiter = $buffer->get_end_iter(); + #Insert some text into the buffer + $buffer->insert($textiter,$info); + txview_scrol_to_end($textview); } - sub show_colored_info{ - my ($textview,$info,$color)=@_; - my $buffer = $textview->get_buffer(); - #$buffer->set_text($info); - my $textiter = $buffer->get_start_iter(); - $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); - txview_scrol_to_end($textview); + my ($textview,$info,$color)=@_; + my $buffer = $textview->get_buffer(); + #$buffer->set_text($info); + my $textiter = $buffer->get_start_iter(); + $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); + txview_scrol_to_end($textview); } sub add_colored_info{ - my ($textview,$info,$color)=@_; - my $buffer = $textview->get_buffer(); - my $textiter = $buffer->get_end_iter(); - $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); - txview_scrol_to_end($textview); - + my ($textview,$info,$color)=@_; + my $buffer = $textview->get_buffer(); + my $textiter = $buffer->get_end_iter(); + $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); + txview_scrol_to_end($textview); } sub add_colors_to_textview{ - my $tview= shift; - add_colored_tag($tview,'red'); - add_colored_tag($tview,'blue'); - add_colored_tag($tview,'brown'); - add_colored_tag($tview,'green'); + my $tview= shift; + add_colored_tag($tview,'red'); + add_colored_tag($tview,'blue'); + add_colored_tag($tview,'brown'); + add_colored_tag($tview,'green'); } - sub add_colored_tag{ - my ($textview_ref,$color)=@_; - my $buffer = $textview_ref->get_buffer(); - $buffer->create_tag ("${color}_tag", foreground => $color); + my ($textview_ref,$color)=@_; + my $buffer = $textview_ref->get_buffer(); + $buffer->create_tag ("${color}_tag", foreground => $color); } sub add_color_to_gd{ - foreach (my $i=0;$i<32;$i++ ) { - my ($red,$green,$blue)=get_color($i); - add_colour("my_color$i"=>[$red>>8,$green>>8,$blue>>8]); - - } + foreach (my $i=0;$i<32;$i++ ) { + my ($red,$green,$blue)=get_color($i); + add_colour("my_color$i"=>[$red>>8,$green>>8,$blue>>8]); + } } - - ############ -# get file folder list +# get file folder list ########### - sub get_directory_name_widget { - my ($object,$title,$entry,$attribute1,$attribute2,$status,$timeout)= @_; - my $browse= def_image_button("icons/browse.png"); - - $browse->signal_connect("clicked"=> sub{ - my $entry_ref=$_[1]; - my $file; - $title ='select directory' if(!defined $title); - my $dialog = Gtk2::FileChooserDialog->new( - $title, undef, - # 'open', - 'select-folder', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - $$entry_ref->set_text($file); - $object->object_add_attribute($attribute1,$attribute2,$file); - set_gui_status($object,$status,$timeout) if(defined $status); - #check_input_file($file,$socgen,$soc_state,$info); - #print "file = $file\n"; - } - $dialog->destroy; - - - - } , \$entry); - - return $browse; - + my ($object,$title,$entry,$attribute1,$attribute2,$status,$timeout)= @_; + my $browse= def_image_button("icons/browse.png"); + $browse->signal_connect("clicked"=> sub{ + my $entry_ref=$_[1]; + my $file; + $title ='select directory' if(!defined $title); + my $dialog = Gtk2::FileChooserDialog->new( + $title, undef, + # 'open', + 'select-folder', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + $$entry_ref->set_text($file); + $object->object_add_attribute($attribute1,$attribute2,$file); + set_gui_status($object,$status,$timeout) if(defined $status); + #check_input_file($file,$socgen,$soc_state,$info); + #print "file = $file\n"; + } + $dialog->destroy; + } , \$entry); + return $browse; } - sub get_dir_name { - my ($object,$title,$attribute1,$attribute2,$open_in,$status,$timeout)= @_; - my $dir; - $title ='select directory' if(!defined $title); - my $dialog = Gtk2::FileChooserDialog->new( - $title, undef, - # 'open', - 'select-folder', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - if(defined $open_in){ - $dialog->set_current_folder ($open_in); - } - - if ( "ok" eq $dialog->run ) { - $dir = $dialog->get_filename; - $object->object_add_attribute($attribute1,$attribute2,$dir); - set_gui_status($object,$status,$timeout) if(defined $status); - $dialog->destroy; - } + my ($object,$title,$attribute1,$attribute2,$open_in,$status,$timeout)= @_; + my $dir; + $title ='select directory' if(!defined $title); + my $dialog = Gtk2::FileChooserDialog->new( + $title, undef, + # 'open', + 'select-folder', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + if(defined $open_in){ + $dialog->set_current_folder ($open_in); + } + if ( "ok" eq $dialog->run ) { + $dir = $dialog->get_filename; + $object->object_add_attribute($attribute1,$attribute2,$dir); + set_gui_status($object,$status,$timeout) if(defined $status); + $dialog->destroy; + } } - - sub get_file_name { - my ($object,$title,$entry,$attribute1,$attribute2,$extension,$label,$open_in)= @_; - my $browse= def_image_button("icons/browse.png"); - - $browse->signal_connect("clicked"=> sub{ - my $entry_ref=$_[1]; - my $file; - $title ='select a file' if(!defined $title); - my $dialog = Gtk2::FileChooserDialog->new( - 'Select a File', undef, - 'open', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - if(defined $extension){ - my $filter = Gtk2::FileFilter->new(); - $filter->set_name($extension); - $filter->add_pattern("*.$extension"); - $dialog->add_filter ($filter); - } - if(defined $open_in){ - $dialog->set_current_folder ($open_in); - # print "$open_in\n"; - - } - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - #remove $project_dir form beginig of each file - $file =remove_project_dir_from_addr($file); - $$entry_ref->set_text($file); - $object->object_add_attribute($attribute1,$attribute2,$file) if(defined $object); - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if(defined $label){ - $label->set_markup("$name$suffix"); - $label->show; - } - - #check_input_file($file,$socgen,$soc_state,$info); - #print "file = $file\n"; - } - $dialog->destroy; - - - - } , \$entry); - - return $browse; - + my ($object,$title,$entry,$attribute1,$attribute2,$extension,$label,$open_in)= @_; + my $browse= def_image_button("icons/browse.png"); + $browse->signal_connect("clicked"=> sub{ + my $entry_ref=$_[1]; + my $file; + $title ='select a file' if(!defined $title); + my $dialog = Gtk2::FileChooserDialog->new( + 'Select a File', undef, + 'open', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + if(defined $extension){ + my $filter = Gtk2::FileFilter->new(); + $filter->set_name($extension); + $filter->add_pattern("*.$extension"); + $dialog->add_filter ($filter); + } + if(defined $open_in){ + $dialog->set_current_folder ($open_in); + # print "$open_in\n"; + } + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + #remove $project_dir form beginig of each file + $file =remove_project_dir_from_addr($file); + $$entry_ref->set_text($file); + $object->object_add_attribute($attribute1,$attribute2,$file) if(defined $object); + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if(defined $label){ + $label->set_markup("$name$suffix"); + $label->show; + } + #check_input_file($file,$socgen,$soc_state,$info); + #print "file = $file\n"; + } + $dialog->destroy; + } , \$entry); + return $browse; } sub gen_file_dialog { - my ($title, @extension)=@_; - $title = 'Select a File' if (!defined $title); - - my $dialog = Gtk2::FileChooserDialog->new( - $title, undef, - 'open', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - foreach my $ext (@extension){ - my $filter = Gtk2::FileFilter->new(); - $filter->set_name("$ext"); - $filter->add_pattern("*.$ext"); - $dialog->add_filter ($filter); - } - - return $dialog; + my ($title, @extension)=@_; + $title = 'Select a File' if (!defined $title); + my $dialog = Gtk2::FileChooserDialog->new( + $title, undef, + 'open', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + foreach my $ext (@extension){ + my $filter = Gtk2::FileFilter->new(); + $filter->set_name("$ext"); + $filter->add_pattern("*.$ext"); + $dialog->add_filter ($filter); + } + return $dialog; } - sub save_file_dialog { - my ($title, @extension)=@_; - $title = 'Select a File' if (!defined $title); - - my $dialog = Gtk2::FileChooserDialog->new( - $title, - undef, - 'save', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - $dialog->set_modal(TRUE); - $dialog->set_transient_for (Gtk2::Window->new('toplevel'));#just to get rid of transient warning - - foreach my $ext (@extension){ - my $filter = Gtk2::FileFilter->new(); - $filter->set_name("$ext"); - $filter->add_pattern("*.$ext"); - $dialog->add_filter ($filter); - } - - return $dialog; - + my ($title, @extension)=@_; + $title = 'Select a File' if (!defined $title); + my $dialog = Gtk2::FileChooserDialog->new( + $title, + undef, + 'save', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + $dialog->set_modal(TRUE); + $dialog->set_transient_for (Gtk2::Window->new('toplevel'));#just to get rid of transient warning + foreach my $ext (@extension){ + my $filter = Gtk2::FileFilter->new(); + $filter->set_name("$ext"); + $filter->add_pattern("*.$ext"); + $dialog->add_filter ($filter); + } + return $dialog; } - - - sub gen_folder_dialog { - my ($title)=@_; - $title = 'Select Folder' if (!defined $title); - - - - my $dialog = Gtk2::FileChooserDialog->new( - $title, - undef, - 'select-folder', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - $dialog->set_modal(TRUE); - - return $dialog; - + my ($title)=@_; + $title = 'Select Folder' if (!defined $title); + my $dialog = Gtk2::FileChooserDialog->new( + $title, + undef, + 'select-folder', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + $dialog->set_modal(TRUE); + return $dialog; } - sub get_filenames_from_dialog{ - my $dialog=shift; - my @files = $dialog->get_filenames; - return @files; + my $dialog=shift; + my @files = $dialog->get_filenames; + return @files; } - sub new_dialog_with_buttons { - my $self =shift; - return Gtk2::Dialog->new_with_buttons( - "Goto to line", - $self->window, - [ 'modal' ], - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - + my $self =shift; + return Gtk2::Dialog->new_with_buttons( + "Goto to line", + $self->window, + [ 'modal' ], + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); } - ################# -# widget update object +# widget update object ################# - sub gen_entry_object { - my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; - my $old=$object->object_get_attribute($attribute1,$attribute2); - my $widget; - if(defined $old ){ - $widget=gen_entry($old); - } - else - { - $widget=gen_entry($default); - $object->object_add_attribute($attribute1,$attribute2,$default); - } - $widget-> signal_connect("changed" => sub{ - my $new_param_value=$widget->get_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; + my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; + my $old=$object->object_get_attribute($attribute1,$attribute2); + my $widget; + if(defined $old ){ + $widget=gen_entry($old); + } + else + { + $widget=gen_entry($default); + $object->object_add_attribute($attribute1,$attribute2,$default); + } + $widget-> signal_connect("changed" => sub{ + my $new_param_value=$widget->get_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - sub gen_combobox_object { - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - my @combo_list=split(/\s*,\s*/,$content); - my $value=$object->object_get_attribute($attribute1,$attribute2); - my $pos; - $pos=get_pos($value, @combo_list) if (defined $value); - if(!defined $pos && defined $default){ - $object->object_add_attribute($attribute1,$attribute2,$default); - $pos=get_item_pos($default, @combo_list); - } - #print " my $pos=get_item_pos($value, @combo_list);\n"; - my $widget=gen_combo(\@combo_list, $pos); - $widget-> signal_connect("changed" => sub{ - my $new_param_value=$widget->get_active_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; - - + my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; + my @combo_list=split(/\s*,\s*/,$content); + my $value=$object->object_get_attribute($attribute1,$attribute2); + my $pos; + $pos=get_pos($value, @combo_list) if (defined $value); + if(!defined $pos && defined $default){ + $object->object_add_attribute($attribute1,$attribute2,$default); + $pos=get_item_pos($default, @combo_list); + } + #print " my $pos=get_item_pos($value, @combo_list);\n"; + my $widget=gen_combo(\@combo_list, $pos); + $widget-> signal_connect("changed" => sub{ + my $new_param_value=$widget->get_active_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - sub gen_comboentry_object { - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - my @combo_list; - @combo_list=split(/\s*,\s*/,$content) if(defined $content ); - my $value=$object->object_get_attribute($attribute1,$attribute2); - my $pos; - $pos=get_pos($value, @combo_list) if (defined $value); - if(!defined $pos && defined $default){ - $object->object_add_attribute($attribute1,$attribute2,$default); - $pos=get_item_pos($default, @combo_list); - } - #print " my $pos=get_item_pos($value, @combo_list);\n"; - - my $widget=gen_combo_entry(\@combo_list, $pos); - ($widget->child)->signal_connect('changed' => sub { - my ($entry) = @_; - my $new_param_value=$entry->get_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; - + my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; + my @combo_list; + @combo_list=split(/\s*,\s*/,$content) if(defined $content ); + my $value=$object->object_get_attribute($attribute1,$attribute2); + my $pos; + $pos=get_pos($value, @combo_list) if (defined $value); + if(!defined $pos && defined $default){ + $object->object_add_attribute($attribute1,$attribute2,$default); + $pos=get_item_pos($default, @combo_list); + } + #print " my $pos=get_item_pos($value, @combo_list);\n"; + my $widget=gen_combo_entry(\@combo_list, $pos); + ($widget->child)->signal_connect('changed' => sub { + my ($entry) = @_; + my $new_param_value=$entry->get_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - - sub gen_spin_object { - my ($object,$attribute1,$attribute2,$content, $default,$status,$timeout)=@_; - my $value=$object->object_get_attribute($attribute1,$attribute2); - my ($min,$max,$step,$digit)=split(/\s*,\s*/,$content); - if(!defined $value){ - $value=$default; - $object->object_add_attribute($attribute1,$attribute2,$value); - } - - $value=~ s/[^0-9.\-]//g; - $min=~ s/[^0-9.\-]//g; - $max=~ s/[^0-9.\-]//g; - $step=~ s/[^0-9.\-]//g; - $digit=~ s/[^0-9.\-]//g if (defined $digit); - - my $widget=gen_spin($min,$max,$step,$digit); - $widget->set_value($value); - $widget-> signal_connect("value_changed" => sub{ - my $new_param_value=$widget->get_value(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; + my ($object,$attribute1,$attribute2,$content, $default,$status,$timeout)=@_; + my $value=$object->object_get_attribute($attribute1,$attribute2); + my ($min,$max,$step,$digit)=split(/\s*,\s*/,$content); + if(!defined $value){ + $value=$default; + $object->object_add_attribute($attribute1,$attribute2,$value); + } + $value=~ s/[^0-9.\-]//g; + $min=~ s/[^0-9.\-]//g; + $max=~ s/[^0-9.\-]//g; + $step=~ s/[^0-9.\-]//g; + $digit=~ s/[^0-9.\-]//g if (defined $digit); + my $widget=gen_spin($min,$max,$step,$digit); + $widget->set_value($value); + $widget-> signal_connect("value_changed" => sub{ + my $new_param_value=$widget->get_value(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - sub gen_check_box_object_array { - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - my $value=$object->object_get_attribute($attribute1,$attribute2); - $value = $default if (!defined $value); - my $widget = def_hbox(FALSE,0); - my @check; - for (my $i=0;$i<$content;$i++){ - $check[$i]= Gtk2::CheckButton->new; - } - for (my $i=0;$i<$content;$i++){ - $widget->pack_end( $check[$i], FALSE, FALSE, 0); - - my @chars = split("",$value); - #check if saved value match the size of check box - if($chars[0] ne $content ) { - $object->object_add_attribute($attribute1,$attribute2,$default); - $value=$default; - @chars = split("",$value); - } - #set initial value - - #print "\@chars=@chars\n"; - for (my $i=0;$i<$content;$i++){ - my $loc= (scalar @chars) -($i+1); - if( $chars[$loc] eq '1') {$check[$i]->set_active(TRUE);} - else {$check[$i]->set_active(FALSE);} - } - - - #get new value - $check[$i]-> signal_connect("toggled" => sub{ - my $new_val="$content\'b"; - - for (my $i=$content-1; $i >= 0; $i--){ - if($check[$i]->get_active()) {$new_val="${new_val}1" ;} - else {$new_val="${new_val}0" ;} - } - $object->object_add_attribute($attribute1,$attribute2,$new_val); - #print "\$new_val=$new_val\n"; - set_gui_status($object,$status,$timeout) if (defined $status); - }); - } - return $widget; - + my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; + my $value=$object->object_get_attribute($attribute1,$attribute2); + $value = $default if (!defined $value); + my $widget = def_hbox(FALSE,0); + my @check; + for (my $i=0;$i<$content;$i++){ + $check[$i]= Gtk2::CheckButton->new; + } + for (my $i=0;$i<$content;$i++){ + $widget->pack_end( $check[$i], FALSE, FALSE, 0); + my @chars = split("",$value); + #check if saved value match the size of check box + if($chars[0] ne $content ) { + $object->object_add_attribute($attribute1,$attribute2,$default); + $value=$default; + @chars = split("",$value); + } + #set initial value + #print "\@chars=@chars\n"; + for (my $i=0;$i<$content;$i++){ + my $loc= (scalar @chars) -($i+1); + if( $chars[$loc] eq '1') {$check[$i]->set_active(TRUE);} + else {$check[$i]->set_active(FALSE);} + } + #get new value + $check[$i]-> signal_connect("toggled" => sub{ + my $new_val="$content\'b"; + for (my $i=$content-1; $i >= 0; $i--){ + if($check[$i]->get_active()) {$new_val="${new_val}1" ;} + else {$new_val="${new_val}0" ;} + } + $object->object_add_attribute($attribute1,$attribute2,$new_val); + #print "\$new_val=$new_val\n"; + set_gui_status($object,$status,$timeout) if (defined $status); + }); + } + return $widget; } - - - - sub gen_check_box_object { - my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; - my $value=$object->object_get_attribute($attribute1,$attribute2); - if (!defined $value){ - #set initial value - $object->object_add_attribute($attribute1,$attribute2,$default); - $value = $default - } - my $widget = Gtk2::CheckButton->new; - if($value == 1) {$widget->set_active(TRUE);} - else {$widget->set_active(FALSE);} - - #get new value - $widget-> signal_connect("toggled" => sub{ - my $new_val; - if($widget->get_active()) {$new_val=1;} - else {$new_val=0;} - $object->object_add_attribute($attribute1,$attribute2,$new_val); - #print "\$new_val=$new_val\n"; - set_gui_status($object,$status,$timeout) if (defined $status); - }); - - return $widget; - + my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; + my $value=$object->object_get_attribute($attribute1,$attribute2); + if (!defined $value){ + #set initial value + $object->object_add_attribute($attribute1,$attribute2,$default); + $value = $default + } + my $widget = Gtk2::CheckButton->new; + if($value == 1) {$widget->set_active(TRUE);} + else {$widget->set_active(FALSE);} + #get new value + $widget-> signal_connect("toggled" => sub{ + my $new_val; + if($widget->get_active()) {$new_val=1;} + else {$new_val=0;} + $object->object_add_attribute($attribute1,$attribute2,$new_val); + #print "\$new_val=$new_val\n"; + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - - - - - sub get_dir_in_object { - my ($object,$attribute1,$attribute2,$content,$status,$timeout,$default)=@_; - my $widget = def_hbox(FALSE,0); - my $value=$object->object_get_attribute($attribute1,$attribute2); - $object->object_add_attribute($attribute1,$attribute2, $default) if (!defined $value ); - $value = $default if (!defined $value ); - if (defined $default){ - $object->object_add_attribute($attribute1,$attribute2, $default) if !(-d $value ); - $value = $default if !(-d $value ); - }; - - my $warning; - - my $entry=gen_entry($value); - $entry-> signal_connect("changed" => sub{ - my $new_param_value=$entry->get_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - unless (-d $new_param_value ){ - if (!defined $warning){ - $warning = def_icon("icons/warning.png"); - $widget->pack_start( $warning, FALSE, FALSE, 0); - set_tip($warning,"$new_param_value is not a valid directory"); - $widget->show_all; - } - - }else{ - $warning->destroy if (defined $warning); - undef $warning; - - } - - }); - my $browse= get_directory_name_widget($object,undef,$entry,$attribute1,$attribute2,$status,$timeout); - - $widget->pack_start( $entry, FALSE, FALSE, 0); - $widget->pack_start( $browse, FALSE, FALSE, 0); - - if(defined $value){ - unless (-d $value ){ - $warning= def_icon("icons/warning.png"); - $widget->pack_start( $warning, FALSE, FALSE, 0); - set_tip($warning,"$value is not a valid directory path"); - } - } - return $widget; + my ($object,$attribute1,$attribute2,$content,$status,$timeout,$default)=@_; + my $widget = def_hbox(FALSE,0); + my $value=$object->object_get_attribute($attribute1,$attribute2); + $object->object_add_attribute($attribute1,$attribute2, $default) if (!defined $value ); + $value = $default if (!defined $value ); + if (defined $default){ + $object->object_add_attribute($attribute1,$attribute2, $default) if !(-d $value ); + $value = $default if !(-d $value ); + }; + my $warning; + my $entry=gen_entry($value); + $entry-> signal_connect("changed" => sub{ + my $new_param_value=$entry->get_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + unless (-d $new_param_value ){ + if (!defined $warning){ + $warning = def_icon("icons/warning.png"); + $widget->pack_start( $warning, FALSE, FALSE, 0); + set_tip($warning,"$new_param_value is not a valid directory"); + $widget->show_all; + } + }else{ + $warning->destroy if (defined $warning); + undef $warning; + } + }); + my $browse= get_directory_name_widget($object,undef,$entry,$attribute1,$attribute2,$status,$timeout); + $widget->pack_start( $entry, FALSE, FALSE, 0); + $widget->pack_start( $browse, FALSE, FALSE, 0); + if(defined $value){ + unless (-d $value ){ + $warning= def_icon("icons/warning.png"); + $widget->pack_start( $warning, FALSE, FALSE, 0); + set_tip($warning,"$value is not a valid directory path"); + } + } + return $widget; } - - - sub get_file_name_object { - my ($object,$attribute1,$attribute2,$extension,$open_in)=@_; - my $widget = def_hbox(FALSE,0); - my $value=$object->object_get_attribute($attribute1,$attribute2); - my $label; - if(defined $value){ - my ($name,$path,$suffix) = fileparse("$value",qr"\..[^.]*$"); - $label=gen_label_in_center($name.$suffix); - - } else { - $label=gen_label_in_center("Selecet a file"); - $label->set_markup("No file has been selected yet"); - } - my $entry=gen_entry(); - my $browse= get_file_name($object,undef,$entry,$attribute1,$attribute2,$extension,$label,$open_in); - $widget->pack_start( $label, FALSE, FALSE, 0); - $widget->pack_start( $browse, FALSE, FALSE, 0); - return $widget; + my ($object,$attribute1,$attribute2,$extension,$open_in)=@_; + my $widget = def_hbox(FALSE,0); + my $value=$object->object_get_attribute($attribute1,$attribute2); + my $label; + if(defined $value){ + my ($name,$path,$suffix) = fileparse("$value",qr"\..[^.]*$"); + $label=gen_label_in_center($name.$suffix); + } else { + $label=gen_label_in_center("Selecet a file"); + $label->set_markup("No file has been selected yet"); + } + my $entry=gen_entry(); + my $browse= get_file_name($object,undef,$entry,$attribute1,$attribute2,$extension,$label,$open_in); + $widget->pack_start( $label, FALSE, FALSE, 0); + $widget->pack_start( $browse, FALSE, FALSE, 0); + return $widget; } - - - - sub gen_notebook { - my $notebook = Gtk2::Notebook->new; - $notebook->can_focus(FALSE); - - return $notebook; + my $notebook = Gtk2::Notebook->new; + $notebook->can_focus(FALSE); + return $notebook; } + ################ # ADD info and label to widget ################ - - sub gen_label_info{ - my ($label_name,$widget,$info)=@_; - my $box = def_hbox(FALSE,0); - #label - if(defined $label_name){ - my $label= gen_label_in_left($label_name); - $box->pack_start( $label, FALSE, FALSE, 3); - } - $box->pack_start( $widget, FALSE, FALSE, 3); - #info - if(defined $info){ - my $button=def_image_button("icons/help.png"); - $button->signal_connect("clicked" => sub {message_dialog($info);}); - $box->pack_start( $button, FALSE, FALSE, 3); - } - $box->show_all; - return $box; -} - + my ($label_name,$widget,$info)=@_; + my $box = def_hbox(FALSE,0); + #label + if(defined $label_name){ + my $label= gen_label_in_left($label_name); + $box->pack_start( $label, FALSE, FALSE, 3); + } + $box->pack_start( $widget, FALSE, FALSE, 3); + #info + if(defined $info){ + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($info);}); + $box->pack_start( $button, FALSE, FALSE, 3); + } + $box->show_all; + return $box; +} ############ # ########### - sub gen_MenuBar{ - my ($window,@menu_items)=@_; - my $accel_group = Gtk2::AccelGroup->new; + my ($window,@menu_items)=@_; + my $accel_group = Gtk2::AccelGroup->new; my $item_factory = Gtk2::ItemFactory->new ("Gtk2::MenuBar", "

",$accel_group); - $window->add_accel_group ($accel_group); + $window->add_accel_group ($accel_group); # Set up item factory to go away with the window $window->{'
'} = $item_factory; # create menu items @@ -1681,43 +1414,39 @@ sub gen_MenuBar{ } sub creating_detachable_toolbar{ - my @attachments=@_; - - #The handle box helps in creating a detachable toolbar - my $hb = Gtk2::HandleBox->new; - #create a toolbar, and do some initial settings - my $toolbar = Gtk2::Toolbar->new; - $toolbar->set_icon_size ('small-toolbar'); - $toolbar->set_show_arrow (FALSE); - foreach my $p (@attachments){ - $toolbar->insert($p,-1); - - } - $hb->add($toolbar); - return $hb; + my @attachments=@_; + #The handle box helps in creating a detachable toolbar + my $hb = Gtk2::HandleBox->new; + #create a toolbar, and do some initial settings + my $toolbar = Gtk2::Toolbar->new; + $toolbar->set_icon_size ('small-toolbar'); + $toolbar->set_show_arrow (FALSE); + foreach my $p (@attachments){ + $toolbar->insert($p,-1); + } + $hb->add($toolbar); + return $hb; } sub gui_quite{ - Gtk2->main_quit; + Gtk2->main_quit; } sub gtk_gui_run{ - my ($main)=@_; - Gtk2->init; - &$main; - Gtk2->main(); - return 1; + my ($main)=@_; + Gtk2->init; + &$main; + Gtk2->main(); + return 1; } - sub refresh_gui{ - while (Gtk2->events_pending) { - Gtk2->main_iteration; + while (Gtk2->events_pending) { + Gtk2->main_iteration; } Gtk2::Gdk->flush; } - sub about { my $version=shift; my $about = Gtk2::AboutDialog->new; @@ -1728,358 +1457,269 @@ sub about { $about->set_program_name('ProNoC'); my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale("icons/ProNoC.png",50,50,FALSE); $about->set_logo($pixbuf); - $about->set_license( - "This program is free software; you can redistribute it\n" + "This program is free software; you can redistribute it\n" . "and/or modify it under the terms of the GNU General \n" - . "Public License as published by the Free Software \n" - . "Foundation; either version 1, or (at your option)\n" - . "any later version.\n\n" - + . "Public License as published by the Free Software \n" + . "Foundation; either version 1, or (at your option)\n" + . "any later version.\n\n" ); - # Add the Hide action to the 'Close' button in the AboutDialog(): + # Add the Hide action to the 'Close' button in the AboutDialog(): $about->signal_connect('response' => sub { $about->hide; }); - - $about->run; $about->destroy; return; } - - ############ # list_store ########### - sub gen_list_store { - my ($dref,$clmn_type_ref, $clmn_lables_ref)=@_; - - -# my @data = ( -# {0 => "Average distance", 1 =>"$avg"}, -# {0 => "Max distance", 1 =>"$max" }, -# {0 => "Min distance",1 => "$min"}, + my ($dref,$clmn_type_ref, $clmn_lables_ref)=@_; +# my @data = ( +# {0 => "Average distance", 1 =>"$avg"}, +# {0 => "Max distance", 1 =>"$max" }, +# {0 => "Min distance",1 => "$min"}, # {0 => "Normlized data per hop", 1 =>"$norm" } # ); - # my @clmn_type = (#'Glib::Boolean', # => G_TYPE_BOOLEAN # #'Glib::Uint', # => G_TYPE_UINT # 'Glib::String', # => G_TYPE_STRING # 'Glib::String'); # you get the idea - - - my @data = @{$dref}; - my @clmn_type = @{$clmn_type_ref}; - my @clmn_lables= @{$clmn_lables_ref}; - - + my @data = @{$dref}; + my @clmn_type = @{$clmn_type_ref}; + my @clmn_lables= @{$clmn_lables_ref}; # create list store my $store = Gtk2::ListStore->new ( @clmn_type); - - - # add data to the list store - foreach my $d (@data) { - my $iter = $store->append; - my @clmns = sort keys %{$d}; - my @a=($iter); - foreach my $c (@clmns){ - push (@a,($c,$d->{$c})); - - } - $store->set (@a); - - } - - + # add data to the list store + foreach my $d (@data) { + my $iter = $store->append; + my @clmns = sort keys %{$d}; + my @a=($iter); + foreach my $c (@clmns){ + push (@a,($c,$d->{$c})); + } + $store->set (@a); + } my $treeview = Gtk2::TreeView->new ($store); $treeview->set_rules_hint (TRUE); - $treeview->set_search_column (1); + $treeview->set_search_column (1); my $renderer = Gtk2::CellRendererToggle->new; $renderer->signal_connect (toggled => \&fixed_toggled, $store); - - - # column for severities - my $c=0; - foreach my $l (@clmn_lables){ - $renderer = Gtk2::CellRendererText->new; - my $column = Gtk2::TreeViewColumn->new_with_attributes ("$l", - $renderer, - text => $c ); - $column->set_sort_column_id ($c ); - $treeview->append_column ($column); - $c++; - } - - - return $treeview; + # column for severities + my $c=0; + foreach my $l (@clmn_lables){ + $renderer = Gtk2::CellRendererText->new; + my $column = Gtk2::TreeViewColumn->new_with_attributes ( + "$l", + $renderer, + text => $c ); + $column->set_sort_column_id ($c ); + $treeview->append_column ($column); + $c++; + } + return $treeview; } - - - - ############## -# create tree +# create tree ############## - - sub create_tree_model_network_maker{ - my $model = Gtk2::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); - my $tree_view = Gtk2::TreeView->new; - $tree_view->set_model ($model); - my $selection = $tree_view->get_selection; - $selection->set_mode ("single"); - my $cell = Gtk2::CellRendererText->new; - $cell->set ('style' => 'italic'); - my $column = Gtk2::TreeViewColumn->new_with_attributes ("select", $cell, 'text' => 0, 'style_set' => 3); - return ($model,$tree_view,$column); + my $model = Gtk2::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); + my $tree_view = Gtk2::TreeView->new; + $tree_view->set_model ($model); + my $selection = $tree_view->get_selection; + $selection->set_mode ("single"); + my $cell = Gtk2::CellRendererText->new; + $cell->set ('style' => 'italic'); + my $column = Gtk2::TreeViewColumn->new_with_attributes ("select", $cell, 'text' => 0, 'style_set' => 3); + return ($model,$tree_view,$column); } - sub treemodel_next_iter{ - my ($child , $tree_model)=@_; - return $tree_model->iter_next ($child); + my ($child , $tree_model)=@_; + return $tree_model->iter_next ($child); } - - - - - - - - - - - - - # clean names for column numbers. use constant DISPLAY_COLUMN => 0; use constant CATRGORY_COLUMN => 1; use constant MODULE_COLUMN => 2; use constant ITALIC_COLUMN => 3; use constant NUM_COLUMNS => 4; - sub create_tree { - my ($self,$label,$info,$tree_ref,$row_selected_func,$row_activated_func)=@_; - my %tree_in = %{$tree_ref}; - my $model = Gtk2::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); - my $tree_view = Gtk2::TreeView->new; - $tree_view->set_model ($model); - my $selection = $tree_view->get_selection; - $selection->set_mode ('browse'); - - - - foreach my $p (sort keys %tree_in) - { - - my @modules= @{$tree_in{$p}}; - #my @dev_entry= @{$tree_entry{$p}}; - my $iter = $model->append (undef); - $model->set ($iter, - DISPLAY_COLUMN, $p, - CATRGORY_COLUMN, $p || '', - MODULE_COLUMN, 0 || '', - ITALIC_COLUMN, FALSE); - - next unless @modules; - - foreach my $v ( @modules){ - my $child_iter = $model->append ($iter); - my $entry= ''; - - $model->set ($child_iter, - DISPLAY_COLUMN, $v, - CATRGORY_COLUMN, $p|| '', - MODULE_COLUMN, $v || '', - ITALIC_COLUMN, FALSE); - } - - - - } - - my $cell = Gtk2::CellRendererText->new; - $cell->set ('style' => 'italic'); - my $column = Gtk2::TreeViewColumn->new_with_attributes - ("$label", - $cell, - 'text' => DISPLAY_COLUMN, - 'style_set' => ITALIC_COLUMN); - - $tree_view->append_column ($column); - my @ll=($model,$info); - #row selected - $selection->signal_connect (changed =>sub { - my ($selection, $ref) = @_; - my ($model,$info)=@{$ref}; - my $iter = $selection->get_selected; - return unless defined $iter; - - my ($category) = $model->get ($iter, CATRGORY_COLUMN); - my ($module) = $model->get ($iter,MODULE_COLUMN ); - $row_selected_func->($self,$category,$module,$info) if(defined $row_selected_func); - - - -}, \@ll); - -# row_activated - $tree_view->signal_connect (row_activated => sub{ - - my ($tree_view, $path, $column) = @_; - my $model = $tree_view->get_model; - my $iter = $model->get_iter ($path); - my ($category) = $model->get ($iter, CATRGORY_COLUMN); - my ($module) = $model->get ($iter,MODULE_COLUMN ); - - - if($module){ - #print "$module is selected via row activaton!\n"; - $row_activated_func->($self,$category,$module,$info) if(defined $row_activated_func); - #add_module_to_soc($soc,$ip,$category,$module,$info); - - } - -}, \@ll); - - #$tree_view->expand_all; - - my $scrolled_window = Gtk2::ScrolledWindow->new; - $scrolled_window->set_policy ('automatic', 'automatic'); - $scrolled_window->set_shadow_type ('in'); - $scrolled_window->add($tree_view); - - my $hbox = Gtk2::HBox->new (FALSE, 0); - $hbox->pack_start ( $scrolled_window, TRUE, TRUE, 0); - - return $hbox; + my ($self,$label,$info,$tree_ref,$row_selected_func,$row_activated_func)=@_; + my %tree_in = %{$tree_ref}; + my $model = Gtk2::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); + my $tree_view = Gtk2::TreeView->new; + $tree_view->set_model ($model); + my $selection = $tree_view->get_selection; + $selection->set_mode ('browse'); + foreach my $p (sort keys %tree_in) + { + my @modules= @{$tree_in{$p}}; + #my @dev_entry= @{$tree_entry{$p}}; + my $iter = $model->append (undef); + $model->set ( + $iter, + DISPLAY_COLUMN, $p, + CATRGORY_COLUMN, $p || '', + MODULE_COLUMN, 0 || '', + ITALIC_COLUMN, FALSE); + next unless @modules; + foreach my $v ( @modules){ + my $child_iter = $model->append ($iter); + my $entry= ''; + $model->set ($child_iter, + DISPLAY_COLUMN, $v, + CATRGORY_COLUMN, $p|| '', + MODULE_COLUMN, $v || '', + ITALIC_COLUMN, FALSE); + } + } + my $cell = Gtk2::CellRendererText->new; + $cell->set ('style' => 'italic'); + my $column = Gtk2::TreeViewColumn->new_with_attributes ( + "$label", + $cell, + 'text' => DISPLAY_COLUMN, + 'style_set' => ITALIC_COLUMN); + $tree_view->append_column ($column); + my @ll=($model,$info); + #row selected + $selection->signal_connect (changed =>sub { + my ($selection, $ref) = @_; + my ($model,$info)=@{$ref}; + my $iter = $selection->get_selected; + return unless defined $iter; + my ($category) = $model->get ($iter, CATRGORY_COLUMN); + my ($module) = $model->get ($iter,MODULE_COLUMN ); + $row_selected_func->($self,$category,$module,$info) if(defined $row_selected_func); + }, \@ll); + # row_activated + $tree_view->signal_connect (row_activated => sub{ + my ($tree_view, $path, $column) = @_; + my $model = $tree_view->get_model; + my $iter = $model->get_iter ($path); + my ($category) = $model->get ($iter, CATRGORY_COLUMN); + my ($module) = $model->get ($iter,MODULE_COLUMN ); + if($module){ + #print "$module is selected via row activaton!\n"; + $row_activated_func->($self,$category,$module,$info) if(defined $row_activated_func); + #add_module_to_soc($soc,$ip,$category,$module,$info); + } + }, \@ll); + #$tree_view->expand_all; + my $scrolled_window = Gtk2::ScrolledWindow->new; + $scrolled_window->set_policy ('automatic', 'automatic'); + $scrolled_window->set_shadow_type ('in'); + $scrolled_window->add($tree_view); + my $hbox = Gtk2::HBox->new (FALSE, 0); + $hbox->pack_start ( $scrolled_window, TRUE, TRUE, 0); + return $hbox; } - sub row_activated_cb{ - my ($tree_view, $path, $column) = @_; - my $model = $tree_view->get_model; - my $iter = $model->get_iter ($path); - my ($category) = $model->get ($iter, DISPLAY_COLUMN); - my ($module) = $model->get ($iter, CATRGORY_COLUMN); - + my ($tree_view, $path, $column) = @_; + my $model = $tree_view->get_model; + my $iter = $model->get_iter ($path); + my ($category) = $model->get ($iter, DISPLAY_COLUMN); + my ($module) = $model->get ($iter, CATRGORY_COLUMN); } - - sub file_edit_tree { - my $tree_store = Gtk2::TreeStore->new('Glib::String', 'Glib::String'); - my $tree_view = Gtk2::TreeView->new($tree_store); - my $column = Gtk2::TreeViewColumn->new_with_attributes('Double-click to open', Gtk2::CellRendererText->new(), text => "0"); - $tree_view->append_column($column); - $tree_view->set_headers_visible(TRUE); - return ($tree_store,$tree_view); + my $tree_store = Gtk2::TreeStore->new('Glib::String', 'Glib::String'); + my $tree_view = Gtk2::TreeView->new($tree_store); + my $column = Gtk2::TreeViewColumn->new_with_attributes('Double-click to open', Gtk2::CellRendererText->new(), text => "0"); + $tree_view->append_column($column); + $tree_view->set_headers_visible(TRUE); + return ($tree_store,$tree_view); } ########## # run external commands ########## - - - sub run_cmd_in_back_ground { - my $command = shift; - #print "\t$command\n"; - - ### Start running the Background Job: + my $command = shift; + #print "\t$command\n"; + ### Start running the Background Job: my $proc = Proc::Background->new($command); my $PID = $proc->pid; my $start_time = $proc->start_time; my $alive = $proc->alive; - - ### While $alive is NOT '0', then keep checking till it is... - # *When $alive is '0', it has finished executing. - while($alive ne 0) - { - $alive = $proc->alive; - - # This while loop will cause Gtk2 to continue processing events, if - # there are events pending... *which there are... - while (Gtk2->events_pending) { - Gtk2->main_iteration; - } + ### While $alive is NOT '0', then keep checking till it is... + # *When $alive is '0', it has finished executing. + while($alive ne 0) + { + $alive = $proc->alive; + # This while loop will cause Gtk2 to continue processing events, if + # there are events pending... *which there are... + while (Gtk2->events_pending) { + Gtk2->main_iteration; + } Gtk2::Gdk->flush; - usleep(1000); - } - - my $end_time = $proc->end_time; - # print "*Command Completed at $end_time, with PID = $PID\n\n"; - - # Since the while loop has exited, the BG job has finished running: - # so close the pop-up window... - # $popup_window->hide; - - # Get the RETCODE from the Background Job using the 'wait' method - my $retcode = $proc->wait; - $retcode /= 256; - - #print "\t*RETCODE == $retcode\n\n"; - Gtk2::Gdk->flush; - ### Check if the RETCODE returned with an Error: - if ($retcode ne 0) { + } + my $end_time = $proc->end_time; + # print "*Command Completed at $end_time, with PID = $PID\n\n"; + # Since the while loop has exited, the BG job has finished running: + # so close the pop-up window... + # $popup_window->hide; + # Get the RETCODE from the Background Job using the 'wait' method + my $retcode = $proc->wait; + $retcode /= 256; + #print "\t*RETCODE == $retcode\n\n"; + Gtk2::Gdk->flush; + ### Check if the RETCODE returned with an Error: + if ($retcode ne 0) { print "Error: The Background Job ($command) returned with an Error...!\n"; return 1; - } else { + } else { #print "Success: The Background Job Completed Successfully...!\n"; return 0; - } - + } } sub run_cmd_in_back_ground_get_stdout { - my $cmd=shift; - my $exit; - my ($stdout, $stderr); - STDOUT->flush(); - STDERR->flush(); - capture { $exit=run_cmd_in_back_ground($cmd) } \$stdout, \$stderr; - return ($stdout,$exit,$stderr); - -} - -sub run_cmd_message_dialog_errors{ - my ($cmd)=@_; - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - message_dialog("$stderr\n",'error'); - return 1; - }if($exit){ - message_dialog("Error $cmd failed: $stdout\n",'error'); - return 1; - } - return 0; - + my $cmd=shift; + my $exit; + my ($stdout, $stderr); + STDOUT->flush(); + STDERR->flush(); + capture { $exit=run_cmd_in_back_ground($cmd) } \$stdout, \$stderr; + return ($stdout,$exit,$stderr); } +sub run_cmd_message_dialog_errors{ + my ($cmd)=@_; + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + message_dialog("$stderr\n",'error'); + return 1; + }if($exit){ + message_dialog("Error $cmd failed: $stdout\n",'error'); + return 1; + } + return 0; +} sub run_cmd_textview_errors{ - my ($cmd,$tview)=@_; - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - add_colored_info($tview,"Error: $stderr\n",'red'); - add_colored_info($tview,"$cmd did not run successfully!\n",'red'); - return undef; - } - if($exit){ - add_colored_info($tview,"Error:$stdout\n",'red'); - add_colored_info($tview,"$cmd did not run successfully!\n",'red'); - return undef; - } - $stdout = "" if (!defined $stdout); - return $stdout -} - + my ($cmd,$tview)=@_; + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + add_colored_info($tview,"Error: $stderr\n",'red'); + add_colored_info($tview,"$cmd did not run successfully!\n",'red'); + return undef; + } + if($exit){ + add_colored_info($tview,"Error:$stdout\n",'red'); + add_colored_info($tview,"$cmd did not run successfully!\n",'red'); + return undef; + } + $stdout = "" if (!defined $stdout); + return $stdout +} sub create_iconview_model { #---------------------------------------------------- @@ -2089,90 +1729,63 @@ sub create_iconview_model { #text of the icon, and the last for the icon self---- #Gtk2::ListStore is ideal for this ------------------ #---------------------------------------------------- - my ($self,$name,$ref)=@_; - my @sources= (defined $ref)? @{$ref}:(); + my ($self,$name,$ref)=@_; + my @sources= (defined $ref)? @{$ref}:(); my $list_store = Gtk2::ListStore->new(qw/Glib::String Gtk2::Gdk::Pixbuf Glib::String/); - #****************************************************** #we populate the Gtk2::ListStore with Gtk2::Stock icons #****************************************************** - - - foreach my $val(@sources){ #get the iconset from the icon_factory #my $iconset = $icon_factory->lookup_default($val); #try and extract the icon from it add_icon_to_tree($self,$name,$list_store,$val); } - return $list_store; } #################### -# SourceView +# SourceView #################### - -sub gen_SourceView_with_buffer{ - return Gtk2::SourceView2::View->new_with_buffer(@_); +sub gen_SourceView_with_buffer{ + return Gtk2::SourceView2::View->new_with_buffer(@_); } - - - - sub create_SourceView_buffer { - my $self = shift; - my $tags = Gtk2::TextTagTable->new(); - - add_tag_to_SourceView($tags, search => { - background => 'yellow', - }); - add_tag_to_SourceView($tags, goto_line => { - 'paragraph-background' => 'orange', - }); - - my $buffer = Gtk2::SourceView2::Buffer->new($tags); - $buffer->signal_connect('notify::cursor-position' => sub { - $self->clear_highlighted(); - }); - - return $buffer; + my $self = shift; + my $tags = Gtk2::TextTagTable->new(); + add_tag_to_SourceView($tags, search => { + background => 'yellow', + }); + add_tag_to_SourceView($tags, goto_line => { + 'paragraph-background' => 'orange', + }); + my $buffer = Gtk2::SourceView2::Buffer->new($tags); + $buffer->signal_connect('notify::cursor-position' => sub { + $self->clear_highlighted(); + }); + return $buffer; } - sub add_tag_to_SourceView { - my ($tags, $name, $properties) = @_; - - my $tag = Gtk2::TextTag->new($name); - $tag->set(%{ $properties }); - $tags->add($tag); + my ($tags, $name, $properties) = @_; + my $tag = Gtk2::TextTag->new($name); + $tag->set(%{ $properties }); + $tags->add($tag); } - sub detect_language { - my $self = shift; - my ($filename) = @_; - - # Guess the programming language of the file - my $manager = Gtk2::SourceView2::LanguageManager->get_default; - my $language = $manager->guess_language($filename); - $self->buffer->set_language($language); + my $self = shift; + my ($filename) = @_; + # Guess the programming language of the file + my $manager = Gtk2::SourceView2::LanguageManager->get_default; + my $language = $manager->guess_language($filename); + $self->buffer->set_language($language); } - - -sub get_pressed_key{ - my $event=shift; - - my $key = Gtk2::Gdk->keyval_name( $event->keyval ); - return $key; +sub get_pressed_key{ + my $event=shift; + my $key = Gtk2::Gdk->keyval_name( $event->keyval ); + return $key; } - - - - - - - -1 +1; \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/widget3.pl b/mpsoc/perl_gui/lib/perl/widget3.pl index 5792501..fcfbb68 100755 --- a/mpsoc/perl_gui/lib/perl/widget3.pl +++ b/mpsoc/perl_gui/lib/perl/widget3.pl @@ -2,1872 +2,1550 @@ use Gtk3; use strict; use warnings; - use FindBin; use lib $FindBin::Bin; - use Data::Dumper; use Gtk3::SourceView; use Consts; - -require "common.pl"; - - +require "common.pl"; use IO::CaptureOutput qw(capture qxx qxy); - #use ColorButton; use HexSpin3; - #use Tk::Animation; - our %glob_setting; ############## # combo box ############# sub gen_combo{ - my ($combo_list, $combo_active_pos)= @_; - my $combo = Gtk3::ComboBoxText->new(); - - combo_set_names($combo,$combo_list); - $combo->set_active($combo_active_pos) if(defined $combo_active_pos); - - #my $font = Gtk3::Pango::FontDescription->from_string('Tahoma 5'); - #$combo->modify_font($font); - - - return $combo; + my ($combo_list, $combo_active_pos)= @_; + my $combo = Gtk3::ComboBoxText->new(); + combo_set_names($combo,$combo_list); + $combo->set_active($combo_active_pos) if(defined $combo_active_pos); + #my $font = Gtk3::Pango::FontDescription->from_string('Tahoma 5'); + #$combo->modify_font($font); + return $combo; } - sub combo_set_names { - my ( $combo, $list_ref ) = @_; - my @list=@{$list_ref}; - #print "$list[0]\n"; - for my $item (@list){$combo->append_text($item);} + my ( $combo, $list_ref ) = @_; + my @list=@{$list_ref}; + #print "$list[0]\n"; + for my $item (@list){$combo->append_text($item);} } - sub gen_combo_help { - my ($help, @combo_list, $pos)= @_; - my $box = def_hbox(FALSE, 0); - my $combo= gen_combo(@combo_list, $pos); - my $button=def_image_button("icons/help.png"); - - $button->signal_connect("clicked" => sub {message_dialog($help);}); - - $box->pack_start( $combo, FALSE, FALSE, 3); - $box->pack_start( $button, FALSE, FALSE, 3); - $box->show_all; - - return ($box,$combo); -} - - + my ($help, @combo_list, $pos)= @_; + my $box = def_hbox(FALSE, 0); + my $combo= gen_combo(@combo_list, $pos); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $combo, FALSE, FALSE, 3); + $box->pack_start( $button, FALSE, FALSE, 3); + $box->show_all; + return ($box,$combo); +} + sub def_h_labeled_combo{ - my ($label_name,$combo_list,$combo_active_pos)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name); - my $combo= gen_combo($combo_list, $combo_active_pos); - $box->pack_start( $label, FALSE, FALSE, 3); - $box->pack_start( $combo, FALSE, TRUE, 3); - return ($box,$combo); -} + my ($label_name,$combo_list,$combo_active_pos)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name); + my $combo= gen_combo($combo_list, $combo_active_pos); + $box->pack_start( $label, FALSE, FALSE, 3); + $box->pack_start( $combo, FALSE, TRUE, 3); + return ($box,$combo); +} sub def_h_labeled_combo_scaled{ - my ($label_name,$combo_list,$combo_active_pos,$label_w,$comb_w)=@_; - my $table= def_table(1,3,TRUE); - my $label= gen_label_in_left($label_name); - my $combo= gen_combo($combo_list, $combo_active_pos); - $table->attach_defaults ($label, 0, $label_w, 0, 1); - $table->attach_defaults ($combo, 1, $label_w+$comb_w, 0, 1); - return ($table,$combo); -} - + my ($label_name,$combo_list,$combo_active_pos,$label_w,$comb_w)=@_; + my $table= def_table(1,3,TRUE); + my $label= gen_label_in_left($label_name); + my $combo= gen_combo($combo_list, $combo_active_pos); + $table->attach_defaults ($label, 0, $label_w, 0, 1); + $table->attach_defaults ($combo, 1, $label_w+$comb_w, 0, 1); + return ($table,$combo); +} sub gen_combo_model{ - my $ref=shift; - my %inputs=%{$ref}; - my $store = Gtk3::TreeStore->new('Glib::String'); - for my $i (sort { $a cmp $b} keys %inputs ) { - my $iter = $store->append(undef); - - $store->set($iter, 0, $i); - for my $capital (sort { $a cmp $b} keys %{$inputs{$i}}) { - my $iter2 = $store->append($iter); - $store->set($iter2, 0, $capital); - } - } - return $store; - + my $ref=shift; + my %inputs=%{$ref}; + my $store = Gtk3::TreeStore->new('Glib::String'); + for my $i (sort { $a cmp $b} keys %inputs ) { + my $iter = $store->append(undef); + $store->set($iter, 0, $i); + for my $capital (sort { $a cmp $b} keys %{$inputs{$i}}) { + my $iter2 = $store->append($iter); + $store->set($iter2, 0, $capital); + } + } + return $store; } sub gen_tree_combo{ - my $model=shift; - my $combo = Gtk3::ComboBox->new_with_model($model); - my $renderer = Gtk3::CellRendererText->new(); - $combo->pack_start($renderer, TRUE); - $combo->set_attributes($renderer, "text", 0); - $combo->set_cell_data_func($renderer, \&is_capital_sensitive); - return $combo; - + my $model=shift; + my $combo = Gtk3::ComboBox->new_with_model($model); + my $renderer = Gtk3::CellRendererText->new(); + $combo->pack_start($renderer, TRUE); + $combo->set_attributes($renderer, "text", 0); + $combo->set_cell_data_func($renderer, \&is_capital_sensitive); + return $combo; } - sub TreePath_new_from_indices { - my @indices =@_; - my $path = Gtk3::TreePath->new_from_indices(@indices); - return $path; - + my @indices =@_; + my $path = Gtk3::TreePath->new_from_indices(@indices); + return $path; } - ############## # spin button ############# sub gen_spin{ - my ($min,$max,$step,$digit)= @_; - - return Gtk3::SpinButton->new_with_range ($min, $max, $step); - if(!defined $digit){ - my $d1 = get_float_precision($min); - my $d2 = get_float_precision($max); - my $d3 = get_float_precision($step); - $digit = ($d1 >$d2)? $d1 : $d2; - $digit = $d3 if($d3>$digit); - } - print "($min,$max,$step,$digit)\n"; - return Gtk3::SpinButton->new_with_range ($min, $max, $step) if($digit ==0); - return gen_spin_float($min,$max,$step,$digit); + my ($min,$max,$step,$digit)= @_; + return Gtk3::SpinButton->new_with_range ($min, $max, $step); + if(!defined $digit){ + my $d1 = get_float_precision($min); + my $d2 = get_float_precision($max); + my $d3 = get_float_precision($step); + $digit = ($d1 >$d2)? $d1 : $d2; + $digit = $d3 if($d3>$digit); + } + print "($min,$max,$step,$digit)\n"; + return Gtk3::SpinButton->new_with_range ($min, $max, $step) if($digit ==0); + return gen_spin_float($min,$max,$step,$digit); } sub get_float_precision{ - my $num=shift; - my $digit = length(($num =~ /\.(.*)/)[0]); - $digit=0 if(!defined $digit); - return $digit; + my $num=shift; + my $digit = length(($num =~ /\.(.*)/)[0]); + $digit=0 if(!defined $digit); + return $digit; } sub gen_spin_float{ - my ($min,$max,$step,$digit)= @_; - #$page_inc = ($max - $min)/ - my $adj = Gtk3::Adjustment->new (0, $min, $max, $step,3.1, 0); - my $spinner = Gtk3::SpinButton->new ($adj, 1.0,$digit); - return $spinner; + my ($min,$max,$step,$digit)= @_; + #$page_inc = ($max - $min)/ + my $adj = Gtk3::Adjustment->new (0, $min, $max, $step,3.1, 0); + my $spinner = Gtk3::SpinButton->new ($adj, 1.0,$digit); + return $spinner; } - sub gen_spin_help { - my ($help, $min,$max,$step,$digit)= @_; - my $box = def_hbox(FALSE, 0); - my $spin= gen_spin($min,$max,$step,$digit); - my $button=def_image_button("icons/help.png"); - - $button->signal_connect("clicked" => sub {message_dialog($help);}); - - $box->pack_start( $spin, FALSE, FALSE, 3); - $box->pack_start( $button, FALSE, FALSE, 3); - $box->show_all; - - return ($box,$spin); + my ($help, $min,$max,$step,$digit)= @_; + my $box = def_hbox(FALSE, 0); + my $spin= gen_spin($min,$max,$step,$digit); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $spin, FALSE, FALSE, 3); + $box->pack_start( $button, FALSE, FALSE, 3); + $box->show_all; + return ($box,$spin); } - ############# # entry ############# sub gen_entry{ - my ($initial) = @_; - my $entry = Gtk3::Entry->new; - if(defined $initial){ $entry->set_text($initial)}; - return $entry; + my ($initial) = @_; + my $entry = Gtk3::Entry->new; + if(defined $initial){ $entry->set_text($initial)}; + return $entry; } - sub gen_entry_new_with_max_length{ - my ($n,$initial) = @_; - my $entry = Gtk3::Entry->new (); - $entry->set_max_length($n); - if(defined $initial){ $entry->set_text($initial)}; - return $entry; + my ($n,$initial) = @_; + my $entry = Gtk3::Entry->new (); + $entry->set_max_length($n); + if(defined $initial){ $entry->set_text($initial)}; + return $entry; } - - sub gen_entry_help{ - my ($help, $init)= @_; - my $box = def_hbox(FALSE, 0); - my $entry= gen_entry ($init); - my $button=def_image_button("icons/help.png"); - - $button->signal_connect("clicked" => sub {message_dialog($help);}); - - $box->pack_start( $entry, FALSE, FALSE, 3); - $box->pack_start( $button, FALSE, FALSE, 3); - $box->show_all; - - return ($box,$entry); + my ($help, $init)= @_; + my $box = def_hbox(FALSE, 0); + my $entry= gen_entry ($init); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $entry, FALSE, FALSE, 3); + $box->pack_start( $button, FALSE, FALSE, 3); + $box->show_all; + return ($box,$entry); } sub def_h_labeled_entry{ - my ($label_name,$initial)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name); - my $entry =gen_entry($initial); - $box->pack_start( $label, FALSE, FALSE, 3); - $box->pack_start( $entry, FALSE, FALSE, 3); - return ($box,$entry); - + my ($label_name,$initial)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name); + my $entry =gen_entry($initial); + $box->pack_start( $label, FALSE, FALSE, 3); + $box->pack_start( $entry, FALSE, FALSE, 3); + return ($box,$entry); } sub def_h_labeled_entry_help{ - my ($help,$label_name,$initial)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name); - my ($b,$entry) =gen_entry_help($help,$initial); - $box->pack_start( $label, FALSE, FALSE, 3); - $box->pack_start( $b, FALSE, FALSE, 3); - return ($box,$entry); - -} - + my ($help,$label_name,$initial)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name); + my ($b,$entry) =gen_entry_help($help,$initial); + $box->pack_start( $label, FALSE, FALSE, 3); + $box->pack_start( $b, FALSE, FALSE, 3); + return ($box,$entry); +} ############## # ComboBoxEntry ############## - sub gen_combo_entry{ - my ($list_ref,$pos)=@_; - my @list=@{$list_ref}; - - #my $combo_box_entry = Gtk3::ComboBoxEntry->new_text; - + my ($list_ref,$pos)=@_; + my @list=@{$list_ref}; + #my $combo_box_entry = Gtk3::ComboBoxEntry->new_text; my $lstore = Gtk3::ListStore->new('Glib::String'); - foreach my $p (@list){ my $iter = $lstore->append(); $lstore->set( $iter, 0, $p ); } - - - - $pos=0 if(! defined $pos || scalar @list < $pos ); - my $combo_box_entry = Gtk3::ComboBox->new_with_model_and_entry($lstore); - $combo_box_entry->set_entry_text_column(0); - $combo_box_entry->set_active($pos); - - return $combo_box_entry; - + $pos=0 if(! defined $pos || scalar @list < $pos ); + my $combo_box_entry = Gtk3::ComboBox->new_with_model_and_entry($lstore); + $combo_box_entry->set_entry_text_column(0); + $combo_box_entry->set_active($pos); + return $combo_box_entry; } sub combo_entry_get_chiled{ - my $combentry =shift; - return Gtk3::Bin::get_child($combentry); + my $combentry =shift; + return Gtk3::Bin::get_child($combentry); } - - - sub update_combo_entry_content { - my ($self,$content,$pos)=@_; - my @combo_list=split(/\s*,\s*/,$content) if(defined $content); - foreach my $p (@combo_list){ - $self->append_text($p); - } - $pos=0 if(! defined $pos ); - $self->set_active($pos); + my ($self,$content,$pos)=@_; + my @combo_list=split(/\s*,\s*/,$content) if(defined $content); + foreach my $p (@combo_list){ + $self->append_text($p); + } + $pos=0 if(! defined $pos ); + $self->set_active($pos); } ########### # checkbutton ########### - sub def_h_labeled_checkbutton{ - my ($label_name)=@_; - my $box = def_hbox(TRUE,0); - my $label= gen_label_in_left($label_name) if (defined $label_name); - my $check= Gtk3::CheckButton->new; - #if($status==1) $check-> - $box->pack_start( $label, FALSE, FALSE, 3) if (defined $label_name); - $box->pack_start( $check, FALSE, FALSE, 3); - return ($box,$check); - -} + my ($label_name)=@_; + my $box = def_hbox(TRUE,0); + my $label= gen_label_in_left($label_name) if (defined $label_name); + my $check= Gtk3::CheckButton->new; + #if($status==1) $check-> + $box->pack_start( $label, FALSE, FALSE, 3) if (defined $label_name); + $box->pack_start( $check, FALSE, FALSE, 3); + return ($box,$check); +} sub gen_checkbutton{ - my $label=shift; - return Gtk3::CheckButton->new_with_label($label) if (defined $label); - return Gtk3::CheckButton->new; + my $label=shift; + return Gtk3::CheckButton->new_with_label($label) if (defined $label); + return Gtk3::CheckButton->new; } - ############# # label ############ - sub gen_label_in_left{ - my ($data)=@_; - my $label = Gtk3::Label->new($data); - $label->set_alignment( 0, 0.5 ); - #my $font = Gtk3::Pango::FontDescription->from_string('Tahoma 5'); - #$label->modify_font($font); - return $label; + my ($data)=@_; + my $label = Gtk3::Label->new($data); + $label->set_alignment( 0, 0.5 ); + #my $font = Gtk3::Pango::FontDescription->from_string('Tahoma 5'); + #$label->modify_font($font); + return $label; } - sub gen_label_in_center{ - my ($data)=@_; - my $label = Gtk3::Label->new($data); - return $label; + my ($data)=@_; + my $label = Gtk3::Label->new($data); + return $label; } sub def_label{ - my @data=@_; - my $label = Gtk3::Label->new(@data); - $label->set_alignment( 0, 0.5 ); - return $label; - + my @data=@_; + my $label = Gtk3::Label->new(@data); + $label->set_alignment( 0, 0.5 ); + return $label; } - sub box_label{ - my( $homogeneous, $spacing, $name)=@_; - my $box=def_hbox($homogeneous, $spacing); - my $label= def_label($name); - $box->pack_start( $label, FALSE, FALSE, 3); - return $box; + my( $homogeneous, $spacing, $name)=@_; + my $box=def_hbox($homogeneous, $spacing); + my $label= def_label($name); + $box->pack_start( $label, FALSE, FALSE, 3); + return $box; } - sub def_title_box{ - my( $homogeneous, $spacing, @labels)=@_; - my $box=def_hbox($homogeneous, $spacing); - foreach my $label (@labels){ - my $labelbox=box_label($homogeneous, $spacing, $label); - $box->pack_start( $labelbox, FALSE, FALSE, 3); - } - return $box; -} - - -sub gen_label_help { - my ($help, $label_name)= @_; - my $box = def_hbox(FALSE, 0); - my $label= gen_label_in_left($label_name); - my $button=def_image_button("icons/help.png"); - $button->signal_connect("clicked" => sub {message_dialog($help);}); - $box->pack_start( $label, FALSE, FALSE, 0); - $box->pack_start( $button, FALSE, FALSE, 0); - $box->set_spacing (0); - $box->show_all; - return $box; + my( $homogeneous, $spacing, @labels)=@_; + my $box=def_hbox($homogeneous, $spacing); + foreach my $label (@labels){ + my $labelbox=box_label($homogeneous, $spacing, $label); + $box->pack_start( $labelbox, FALSE, FALSE, 3); + } + return $box; } -sub gen_label_with_mnemonic { - my $name=shift; - Gtk3::Label->new_with_mnemonic($name); +sub gen_label_help { + my ($help, $label_name)= @_; + my $box = def_hbox(FALSE, 0); + my $label= gen_label_in_left($label_name); + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($help);}); + $box->pack_start( $label, FALSE, FALSE, 0); + $box->pack_start( $button, FALSE, FALSE, 0); + $box->set_spacing (0); + $box->show_all; + return $box; +} +sub gen_label_with_mnemonic { + my $name=shift; + Gtk3::Label->new_with_mnemonic($name); } - + ############## # button ############# - sub button_box{ # create a new button - my $label=@_; - my $button = Gtk3::Button->new_from_stock($label); - my $box=def_hbox(TRUE,5); - $box->pack_start($button, FALSE, FALSE,0); - - return ($box,$button); - + my $label=@_; + my $button = Gtk3::Button->new_from_stock($label); + my $box=def_hbox(TRUE,5); + $box->pack_start($button, FALSE, FALSE,0); + return ($box,$button); } - sub get_icon_pixbuff{ my $icon_file=shift; my $size; if ($glob_setting{'ICON_SIZE'} eq 'default'){ - my $font_size=get_defualt_font_size(); - $size=($font_size *2.5); + my $font_size=get_defualt_font_size(); + $size=($font_size *2.5); }else{ - $size = int ($glob_setting{'ICON_SIZE'}); + $size = int ($glob_setting{'ICON_SIZE'}); } - my $pixbuf = Gtk3::Gdk::Pixbuf->new_from_file_at_scale($icon_file,$size,$size,FALSE); - return $pixbuf; + my $pixbuf = Gtk3::Gdk::Pixbuf->new_from_file_at_scale($icon_file,$size,$size,FALSE); + return $pixbuf; } - sub def_icon{ - my $icon_file=shift; - return Gtk3::Image->new_from_pixbuf(get_icon_pixbuff($icon_file)); + my $icon_file=shift; + return Gtk3::Image->new_from_pixbuf(get_icon_pixbuff($icon_file)); } sub call_gtk_drag_finish{ - Gtk3::drag_finish(@_); + Gtk3::drag_finish(@_); } - - sub add_drag_dest_set{ - my ($widget,$a,$b,$c) = @_; - $widget->drag_dest_set(['all'],[def_gtk_target_entry($a,$b,$c)], ['copy']); + my ($widget,$a,$b,$c) = @_; + $widget->drag_dest_set(['all'],[def_gtk_target_entry($a,$b,$c)], ['copy']); } sub def_gtk_target_entry{ - return Gtk3::TargetEntry->new(@_); + return Gtk3::TargetEntry->new(@_); } - sub add_drag_source { - my ($widget,$a,$b,$c) = @_; - $widget->drag_source_set ( - ['button1_mask', 'button3_mask'], - [def_gtk_target_entry($a,$b,$c)], - ['copy'] - ); + my ($widget,$a,$b,$c) = @_; + $widget->drag_source_set ( + ['button1_mask', 'button3_mask'], + [def_gtk_target_entry($a,$b,$c)], + ['copy'] + ); } sub drag_set_icon_pixbuf { - my ($icon_view,$icon_pixbuf)=@_; - #$icon_view->drag_source_set_icon_pixbuf ($icon_pixbuf); + my ($icon_view,$icon_pixbuf)=@_; + #$icon_view->drag_source_set_icon_pixbuf ($icon_pixbuf); } sub gen_iconview { - my ($tree_model,$marc_col,$pix_con)=@_; - my $icon_view = Gtk3::IconView->new_with_model($tree_model); + my ($tree_model,$marc_col,$pix_con)=@_; + my $icon_view = Gtk3::IconView->new_with_model($tree_model); $icon_view->set_markup_column($marc_col); $icon_view->set_pixbuf_column($pix_con); - return $icon_view; + return $icon_view; } - sub add_frame_to_image{ - my $image=shift; - my $align = Gtk3::Alignment->new (0.5, 0.5, 0, 0); - my $frame = Gtk3::Frame->new; - $frame->set_shadow_type ('in'); - # Animation - $frame->add ($image); - $align->add ($frame); - return $align; + my $image=shift; + my $align = Gtk3::Alignment->new (0.5, 0.5, 0, 0); + my $frame = Gtk3::Frame->new; + $frame->set_shadow_type ('in'); + # Animation + $frame->add ($image); + $align->add ($frame); + return $align; } sub gen_frame { - return Gtk3::Frame->new; + return Gtk3::Frame->new; } - - sub new_image_from_file{ - return Gtk3::Image->new_from_file (@_); + return Gtk3::Image->new_from_file (@_); } - sub gen_pixbuf{ - my $file=shift; - return Gtk3::Gdk::Pixbuf->new_from_file($file); + my $file=shift; + return Gtk3::Gdk::Pixbuf->new_from_file($file); } sub open_image{ - my ($image_file,$x,$y,$unit)=@_; - if(defined $unit){ - my($width,$hight)=max_win_size(); - if($unit eq 'percent'){ - $x= ($x * $width)/100; - $y= ($y * $hight)/100; - } # else its pixels - - } - $image_file ="icons/blank.png" unless(-f $image_file); - my $pixbuf = Gtk3::Gdk::Pixbuf->new_from_file_at_scale($image_file,$x,$y,TRUE); - my $image = Gtk3::Image->new_from_pixbuf($pixbuf); - return $image; + my ($image_file,$x,$y,$unit)=@_; + if(defined $unit){ + my($width,$hight)=max_win_size(); + if($unit eq 'percent'){ + $x= ($x * $width)/100; + $y= ($y * $hight)/100; + } # else its pixels + } + $image_file ="icons/blank.png" unless(-f $image_file); + my $pixbuf = Gtk3::Gdk::Pixbuf->new_from_file_at_scale($image_file,$x,$y,TRUE); + my $image = Gtk3::Image->new_from_pixbuf($pixbuf); + return $image; } sub open_inline_image{ - my ($image_string,$x,$y,$unit)=@_; - if(defined $unit){ - my($width,$hight)=max_win_size(); - if($unit eq 'percent'){ - $x= ($x * $width)/100; - $y= ($y * $hight)/100; - } # else its pixels - - } - my $pixbuf = do { + my ($image_string,$x,$y,$unit)=@_; + if(defined $unit){ + my($width,$hight)=max_win_size(); + if($unit eq 'percent'){ + $x= ($x * $width)/100; + $y= ($y * $hight)/100; + } # else its pixels + } + my $pixbuf = do { my $loader = Gtk3::Gdk::PixbufLoader->new(); $loader->set_size( $x,$y ) if (defined $y); - $loader->write( [unpack 'C*', $image_string] ); + $loader->write( [unpack 'C*', $image_string] ); $loader->close(); $loader->get_pixbuf(); }; - - - my $image = Gtk3::Image->new_from_pixbuf($pixbuf); - - return $image; + my $image = Gtk3::Image->new_from_pixbuf($pixbuf); + return $image; } sub find_icon{ - my $file =shift; - return $file if(-f $file); #called from perl_gui - return "../../$file"; #called from lib/perl + my $file =shift; + return $file if(-f $file); #called from perl_gui + return "../../$file"; #called from lib/perl } sub def_image_button{ - my ($image_file, $label_text, $homogeneous, $mnemonic)=@_; - # create box for image and label - $homogeneous = FALSE if(!defined $homogeneous); - my $box = def_hbox($homogeneous,0); - my $image; - $image_file = find_icon( $image_file); - $image = def_icon($image_file) if(-f $image_file); - - # now on to the image stuff - #my $image = Gtk3::Image->new_from_file($image_file); - $box->pack_start($image, FALSE, FALSE, 0) if(defined $image); - $box->set_border_width(0); - $box->set_spacing (0); - # Create a label for the button - if(defined $label_text ) { - my $label; - $label = Gtk3::Label->new(" $label_text") unless (defined $mnemonic); - $label = Gtk3::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); - $box->pack_start($label, FALSE, FALSE, 0); - } - - my $button = Gtk3::Button->new(); - $button->add($box); - $button->set_border_width(0); - $button->show_all; - return $button; + my ($image_file, $label_text, $homogeneous, $mnemonic)=@_; + # create box for image and label + $homogeneous = FALSE if(!defined $homogeneous); + my $box = def_hbox($homogeneous,0); + my $image; + $image_file = find_icon( $image_file); + $image = def_icon($image_file) if(-f $image_file); + # now on to the image stuff + #my $image = Gtk3::Image->new_from_file($image_file); + $box->pack_start($image, FALSE, FALSE, 0) if(defined $image); + $box->set_border_width(0); + $box->set_spacing (0); + # Create a label for the button + if(defined $label_text ) { + my $label; + $label = Gtk3::Label->new(" $label_text") unless (defined $mnemonic); + $label = Gtk3::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); + $box->pack_start($label, FALSE, FALSE, 0); + } + my $button = Gtk3::Button->new(); + $button->add($box); + $button->set_border_width(0); + $button->show_all; + return $button; } sub def_button{ - my ($label_text)=@_; - my $label = Gtk3::Label->new("$label_text") if(defined $label_text); - my $button= Gtk3::Button->new(); - $button->add($label) if(defined $label_text); - return $button; -} - + my ($label_text)=@_; + my $label = Gtk3::Label->new("$label_text") if(defined $label_text); + my $button= Gtk3::Button->new(); + $button->add($label) if(defined $label_text); + return $button; +} sub def_image_label{ - my ($image_file, $label_text,$mnemonic)=@_; - # create box for image and label - my $box = def_hbox(FALSE,1); - # now on to the image stuff - my $image = def_icon($image_file); - $box->pack_start($image, TRUE, FALSE, 0); - # Create a label for the button - if(defined $label_text ) { - my $label; - $label = Gtk3::Label->new(" $label_text") unless (defined $mnemonic); - $label = Gtk3::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); - $box->pack_start($label, TRUE, FALSE, 0); - } - - return $box; - + my ($image_file, $label_text,$mnemonic)=@_; + # create box for image and label + my $box = def_hbox(FALSE,1); + # now on to the image stuff + my $image = def_icon($image_file); + $box->pack_start($image, TRUE, FALSE, 0); + # Create a label for the button + if(defined $label_text ) { + my $label; + $label = Gtk3::Label->new(" $label_text") unless (defined $mnemonic); + $label = Gtk3::Label->new_with_mnemonic (" $label_text") if (defined $mnemonic); + $box->pack_start($label, TRUE, FALSE, 0); + } + return $box; } - -sub gen_button_message { - my ($help, $image_file,$label_name)= @_; - my $box = def_hbox(FALSE, 0); - my $label= gen_label_in_center($label_name) if(defined $label_name); - my $button=def_image_button($image_file); - - if(defined $help ){$button->signal_connect("clicked" => sub {message_dialog($help);});} - - $box->pack_start( $label, FALSE, FALSE, 0) if(defined $label_name); - $box->pack_start( $button, FALSE, FALSE, 0); - $box->set_border_width(0); - $box->set_spacing (0); - $box->show_all; - - return $box; - - +sub gen_button_message { + my ($help, $image_file,$label_name)= @_; + my $box = def_hbox(FALSE, 0); + my $label= gen_label_in_center($label_name) if(defined $label_name); + my $button=def_image_button($image_file); + if(defined $help ){$button->signal_connect("clicked" => sub {message_dialog($help);});} + $box->pack_start( $label, FALSE, FALSE, 0) if(defined $label_name); + $box->pack_start( $button, FALSE, FALSE, 0); + $box->set_border_width(0); + $box->set_spacing (0); + $box->show_all; + return $box; } - sub def_colored_button{ - my ($label_text,$color_num)=@_; - # create box for image and label - my $box = def_hbox(FALSE,0); - my $font_size=get_defualt_font_size(); - - - my $button= Gtk3::Button->new(); - my $label = gen_label_in_center($label_text) if(defined $label_text); - - - # do custom css ##################################################### - my $css_provider = Gtk3::CssProvider->new; - - my ($red,$green,$blue) = get_color($color_num); - my $r =int ($red*100/65535); - my $g =int ($green*100/65535); - my $b =int ($blue*100/65535); - - - #select lable color based on backgorund - my $lc = (($r*0.299 + $g*0.587 + $b*0.114) > 50)? 0 : 1; # use #000000 else use #ffffff - - $label->set_markup("$label_text") if(defined $label_text && $lc==1); - - - - $css_provider->load_from_data ([map ord, split //, " - + my ($label_text,$color_num)=@_; + # create box for image and label + my $box = def_hbox(FALSE,0); + my $font_size=get_defualt_font_size(); + my $button= Gtk3::Button->new(); + my $label = gen_label_in_center($label_text) if(defined $label_text); + # do custom css ##################################################### + my $css_provider = Gtk3::CssProvider->new; + my ($red,$green,$blue) = get_color($color_num); + my $r =int ($red*100/65535); + my $g =int ($green*100/65535); + my $b =int ($blue*100/65535); + #select lable color based on backgorund + my $lc = (($r*0.299 + $g*0.587 + $b*0.114) > 50)? 0 : 1; # use #000000 else use #ffffff + $label->set_markup("$label_text") if(defined $label_text && $lc==1); + $css_provider->load_from_data ([map ord, split //, " button { - background-image: none; - background-color: rgba($r%,$g%,$b%,100); + background-image: none; + background-color: rgba($r%,$g%,$b%,100); }" ]); - - - my $style_context = $button->get_style_context; - $style_context->add_provider ( $css_provider, Gtk3::STYLE_PROVIDER_PRIORITY_USER); - - $button->add($label) if(defined $label_text); - - $button->show_all; - return $button; + my $style_context = $button->get_style_context; + $style_context->add_provider ( $css_provider, Gtk3::STYLE_PROVIDER_PRIORITY_USER); + $button->add($label) if(defined $label_text); + $button->show_all; + return $button; } - - - - sub entry_set_text_color { - my ($entry,$color_num)=@_; - my $color_hex = get_color_hex_string($color_num); - - my $css_provider = Gtk3::CssProvider->new; - $css_provider->load_from_data ([map ord, split //, " + my ($entry,$color_num)=@_; + my $color_hex = get_color_hex_string($color_num); + my $css_provider = Gtk3::CssProvider->new; + $css_provider->load_from_data ([map ord, split //, " entry { - color: #$color_hex; + color: #$color_hex; }" - ]); - - my $style_context = $entry->get_style_context; - $style_context->add_provider ( $css_provider, Gtk3::STYLE_PROVIDER_PRIORITY_USER); - + ]); + my $style_context = $entry->get_style_context; + $style_context->add_provider ( $css_provider, Gtk3::STYLE_PROVIDER_PRIORITY_USER); } - - - - - - - sub show_gif{ - my $gif = shift; - $gif=find_icon( $gif); - my $vbox = Gtk3::HBox->new (TRUE, 8); + my $gif = shift; + $gif=find_icon( $gif); + my $vbox = Gtk3::HBox->new (TRUE, 8); my $filename; - eval { - $filename = main::demo_find_file ($gif); - }; + eval { + $filename = main::demo_find_file ($gif); + }; my $image = Gtk3::Image->new_from_file ($gif); $vbox->set_border_width (4); my $align = Gtk3::Alignment->new (0.5, 0.5, 0, 0); - my $frame = Gtk3::Frame->new; - $frame->set_shadow_type ('in'); + my $frame = Gtk3::Frame->new; + $frame->set_shadow_type ('in'); # Animation $frame->add ($image); $align->add ($frame); - $vbox->pack_start ($align, FALSE, FALSE, 0); - return $vbox; + $vbox->pack_start ($align, FALSE, FALSE, 0); + return $vbox; } sub gen_radiobutton { - my ($from,$label,$icon,$tip) =@_; - my $rbtn = (defined $from )? Gtk3::RadioToolButton->new_from_widget($from) : Gtk3::RadioToolButton->new (undef); - $rbtn->set_label ($label) if(defined $label); - $rbtn->set_icon_widget (def_icon($icon)) if(defined $icon); - set_tip($rbtn, $tip) if(defined $tip); - return $rbtn; + my ($from,$label,$icon,$tip) =@_; + my $rbtn = (defined $from )? Gtk3::RadioToolButton->new_from_widget($from) : Gtk3::RadioToolButton->new (undef); + $rbtn->set_label ($label) if(defined $label); + $rbtn->set_icon_widget (def_icon($icon)) if(defined $icon); + set_tip($rbtn, $tip) if(defined $tip); + return $rbtn; } sub gen_colored_label{ - my ($label_text, $color_num)=@_; - - my $color_hex = get_color_hex_string($color_num); + my ($label_text, $color_num)=@_; + my $color_hex = get_color_hex_string($color_num); my $label = Gtk3::Label->new($label_text); - $label->set_markup("$label_text"); - - return $label; + $label->set_markup("$label_text"); + return $label; } - ############ -# message_dialog +# message_dialog ############ - sub message_dialog { - my ($message,$type)=@_; - $type = 'info' if (!defined $type); - my $window; - my $dialog = Gtk3::MessageDialog->new ($window, - [qw( modal destroy-with-parent )], - $type, - 'ok', - $message); - - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - $dialog->run; - $dialog->destroy; - + my ($message,$type)=@_; + $type = 'info' if (!defined $type); + my $window; + my $dialog = Gtk3::MessageDialog->new ($window, + [qw( modal destroy-with-parent )], + $type, + 'ok', + $message); + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + $dialog->run; + $dialog->destroy; } - - sub set_tip{ - my ($widget,$tip)=@_; - #my $tooltips = Gtk3::Tooltips->new; - #$tooltips->set_tip($widget,$tip); - $widget->set_tooltip_text($tip); - - + my ($widget,$tip)=@_; + #my $tooltips = Gtk3::Tooltips->new; + #$tooltips->set_tip($widget,$tip); + $widget->set_tooltip_text($tip); } - sub yes_no_dialog { - my ($message)=@_; - my $dialog = Gtk3::MessageDialog->new (my $window, - 'destroy-with-parent', - 'question', # message type - 'yes-no', # which set of buttons? - "$message"); - - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - my $response = $dialog->run; - - $dialog->destroy; - return $response; + my ($message)=@_; + my $dialog = Gtk3::MessageDialog->new (my $window, + 'destroy-with-parent', + 'question', # message type + 'yes-no', # which set of buttons? + "$message"); + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + my $response = $dialog->run; + $dialog->destroy; + return $response; } sub create_dialog { - my ($message_head,$message_body,$icon,@buttons)=@_; - # create a new dialog with some buttons - my %hash1; - my %hash2; - my $i=0; - foreach my $b (@buttons){ - $hash1{$b}=$i; - $hash2{$i}=$b; - $i++; - } - - my $dialog = Gtk3::Dialog->new ( - " ", - Gtk3::Window->new('toplevel'), - [qw/modal destroy-with-parent/], + my ($message_head,$message_body,$icon,@buttons)=@_; + # create a new dialog with some buttons + my %hash1; + my %hash2; + my $i=0; + foreach my $b (@buttons){ + $hash1{$b}=$i; + $hash2{$i}=$b; + $i++; + } + my $dialog = Gtk3::Dialog->new ( + " ", + Gtk3::Window->new('toplevel'), + [qw/modal destroy-with-parent/], %hash1 ); - my $content = $dialog->get_content_area (); - - my $table = def_table(1,3,TRUE); - $table->attach (def_icon($icon) , 0, 1, 0, 2,'expand','expand',2,2) if(defined $icon); - if(defined $message_head){ - my $hd=gen_label_in_left($message_head); - $hd->set_markup("$message_head"); - $table->attach ($hd , 1, 10, 0, 1,'fill','shrink',2,2); - } - if(defined $message_head){ - $table->attach (gen_label_in_left($message_body) , 2, 10, 1, 2,'fill','shrink',2,2); - } - - $content->add ($table); - $content->show_all; - - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - my $response = $dialog->run; - - $dialog->destroy; - return $hash2{$response}; + my $content = $dialog->get_content_area (); + my $table = def_table(1,3,TRUE); + $table->attach (def_icon($icon) , 0, 1, 0, 2,'expand','expand',2,2) if(defined $icon); + if(defined $message_head){ + my $hd=gen_label_in_left($message_head); + $hd->set_markup("$message_head"); + $table->attach ($hd , 1, 10, 0, 1,'fill','shrink',2,2); + } + if(defined $message_head){ + $table->attach (gen_label_in_left($message_body) , 2, 10, 1, 2,'fill','shrink',2,2); + } + $content->add ($table); + $content->show_all; + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + my $response = $dialog->run; + $dialog->destroy; + return $hash2{$response}; } ############ # window ########### - sub def_win { - my @titel=shift; - my $window = Gtk3::Window->new('toplevel'); - $window->set_title(@titel); - $window->set_position("center"); - $window->set_default_size(100, 100); - $window->set_border_width(20); - $window->signal_connect (delete_event => sub { Gtk3->main_quit }); - return $window; - -} - + my @titel=shift; + my $window = Gtk3::Window->new('toplevel'); + $window->set_title(@titel); + $window->set_position("center"); + $window->set_default_size(100, 100); + $window->set_border_width(20); + $window->signal_connect (delete_event => sub { Gtk3->main_quit }); + return $window; +} sub def_win_size { - my $x=shift; - my $y=shift; - my @titel=shift; - my $window = Gtk3::Window->new('toplevel'); - $window->set_title(@titel); - $window->set_position("center"); - $window->set_default_size($x, $y); - $window->set_border_width(20); - $window->signal_connect (delete_event => sub { Gtk3->main_quit }); - return $window; - -} - + my $x=shift; + my $y=shift; + my @titel=shift; + my $window = Gtk3::Window->new('toplevel'); + $window->set_title(@titel); + $window->set_position("center"); + $window->set_default_size($x, $y); + $window->set_border_width(20); + $window->signal_connect (delete_event => sub { Gtk3->main_quit }); + return $window; +} sub def_popwin_size { - my ($x,$y,$titel,$unit)=@_; - if(defined $unit){ - my($width,$hight)=max_win_size(); - if($unit eq 'percent'){ - $x= ($x * $width)/100; - $y= ($y * $hight)/100; - } # else its pixels - - } - #my $window = Gtk3::Window->new('popup'); - my $window = Gtk3::Window->new('toplevel'); - $window->set_title($titel); - $window->set_position("center"); - $window->set_default_size($x, $y); - $window->set_border_width(20); - #$window->signal_connect (delete_event => sub { $window->destroy }); - return $window; - -} - - - - + my ($x,$y,$titel,$unit)=@_; + if(defined $unit){ + my($width,$hight)=max_win_size(); + if($unit eq 'percent'){ + $x= ($x * $width)/100; + $y= ($y * $hight)/100; + } # else its pixels + } + #my $window = Gtk3::Window->new('popup'); + my $window = Gtk3::Window->new('toplevel'); + $window->set_title($titel); + $window->set_position("center"); + $window->set_default_size($x, $y); + $window->set_border_width(20); + #$window->signal_connect (delete_event => sub { $window->destroy }); + return $window; +} sub def_scrolled_window_box{ - - my $window = def_popwin_size(@_); - my $box=def_vbox(TRUE,5); - my $scrolled_window = new Gtk3::ScrolledWindow (undef, undef); - $scrolled_window->set_policy( "automatic", "automatic" ); - $scrolled_window->add($box); - $window->add($scrolled_window); - $window->show_all; - $box->show_all; - return ($box,$window); - + my $window = def_popwin_size(@_); + my $box=def_vbox(TRUE,5); + my $scrolled_window = new Gtk3::ScrolledWindow (undef, undef); + $scrolled_window->set_policy( "automatic", "automatic" ); + $scrolled_window->add($box); + $window->add($scrolled_window); + $window->show_all; + $box->show_all; + return ($box,$window); } - sub get_default_screen { - return Gtk3::Gdk::Screen::get_default; + return Gtk3::Gdk::Screen::get_default; } sub get_defualt_font_size{ - return int($glob_setting{'FONT_SIZE'}) if ($glob_setting{'FONT_SIZE'} ne 'default'); - - my($width,$hight)=max_win_size(); - #print "($width,$hight)\n"; - my $font_size=($width>=1600)? 10: - ($width>=1400)? 9: - ($width>=1200)? 9: - ($width>=1000)? 7:6; - #print "$font_size\n"; - return $font_size; + return int($glob_setting{'FONT_SIZE'}) if ($glob_setting{'FONT_SIZE'} ne 'default'); + my($width,$hight)=max_win_size(); + #print "($width,$hight)\n"; + my $font_size= + ($width>=1600)? 10: + ($width>=1400)? 9: + ($width>=1200)? 9: + ($width>=1000)? 7:6; + #print "$font_size\n"; + return $font_size; } - sub set_defualt_font_size{ - my $font_size=get_defualt_font_size(); - $font_size= int (1.35*$font_size); + my $font_size=get_defualt_font_size(); + $font_size= int (1.35*$font_size); # do custom css ##################################################### - my $css_provider = Gtk3::CssProvider->new; - $css_provider->load_from_data ([map ord, split //, " - *{ - + my $css_provider = Gtk3::CssProvider->new; + $css_provider->load_from_data ([map ord, split //, " + *{ font-family:Verdana; font-size:${font_size}px; - }" - + }" ]); - #font_name = Verdana $font_size" - - - #print $css_provider->to_string,"\n"; - - my $d = Gtk3::Gdk::Display::get_default (); - my $s = $d->get_default_screen; - - Gtk3::StyleContext::add_provider_for_screen ( $s, $css_provider, Gtk3::STYLE_PROVIDER_PRIORITY_USER); - - - - #Gtk3::Rc->parse_string(<<__); - # style "normal" { - # font_name ="Verdana $font_size" - # } - # widget "*" style "normal" + #print $css_provider->to_string,"\n"; + my $d = Gtk3::Gdk::Display::get_default (); + my $s = $d->get_default_screen; + Gtk3::StyleContext::add_provider_for_screen ( $s, $css_provider, Gtk3::STYLE_PROVIDER_PRIORITY_USER); + #Gtk3::Rc->parse_string(<<__); + # style "normal" { + # font_name ="Verdana $font_size" + # } + # widget "*" style "normal" #__ - } sub add_widget_to_scrolled_win{ - my ($widget,$scrolled_win) =@_; - if(! defined $scrolled_win){ - $scrolled_win = new Gtk3::ScrolledWindow (undef, undef); - $scrolled_win->set_policy( "automatic", "automatic" ); - $scrolled_win->set_shadow_type('in'); - }else { - my @list = $scrolled_win->get_children (); - foreach my $c( @list){ $scrolled_win->remove($c);} - } - #$scrolled_win->add_with_viewport($widget) if(defined $widget); - $scrolled_win->add($widget) if(defined $widget); - $scrolled_win->show_all; - return $scrolled_win ; + my ($widget,$scrolled_win) =@_; + if(! defined $scrolled_win){ + $scrolled_win = new Gtk3::ScrolledWindow (undef, undef); + $scrolled_win->set_policy( "automatic", "automatic" ); + $scrolled_win->set_shadow_type('in'); + }else { + my @list = $scrolled_win->get_children (); + foreach my $c( @list){ $scrolled_win->remove($c);} + } + #$scrolled_win->add_with_viewport($widget) if(defined $widget); + $scrolled_win->add($widget) if(defined $widget); + $scrolled_win->show_all; + return $scrolled_win ; } sub gen_scr_win_with_adjst { - my ($self,$name)=@_; - my $scrolled_win = new Gtk3::ScrolledWindow (undef, undef); - $scrolled_win->set_policy( "automatic", "automatic" ); - $scrolled_win->signal_connect("destroy"=> sub{ - save_scrolled_win_adj($self,$scrolled_win, $name); - - }); - my $adjast=0; - $scrolled_win->signal_connect("size-allocate"=> sub{ - if($adjast==0){ - load_scrolled_win_adj($self,$scrolled_win, $name); - $adjast=1; - } - - }); - return $scrolled_win; + my ($self,$name)=@_; + my $scrolled_win = new Gtk3::ScrolledWindow (undef, undef); + $scrolled_win->set_policy( "automatic", "automatic" ); + $scrolled_win->signal_connect("destroy"=> sub{ + save_scrolled_win_adj($self,$scrolled_win, $name); + }); + my $adjast=0; + $scrolled_win->signal_connect("size-allocate"=> sub{ + if($adjast==0){ + load_scrolled_win_adj($self,$scrolled_win, $name); + $adjast=1; + } + }); + return $scrolled_win; } - sub save_scrolled_win_adj { - my ($self,$scrolled_win,$name)=@_; - return if (!defined $scrolled_win); - my $ha= $scrolled_win->get_hadjustment(); + my ($self,$scrolled_win,$name)=@_; + return if (!defined $scrolled_win); + my $ha= $scrolled_win->get_hadjustment(); my $va =$scrolled_win->get_vadjustment(); return if(!defined $ha); return if(!defined $va); - save_adj ($self,$ha,$name,"ha"); - save_adj ($self,$va,$name,"va"); + save_adj ($self,$ha,$name,"ha"); + save_adj ($self,$va,$name,"va"); } - sub load_scrolled_win_adj { - my ($self,$scrolled_win,$name)=@_; - my $ha= $scrolled_win->get_hadjustment(); + my ($self,$scrolled_win,$name)=@_; + my $ha= $scrolled_win->get_hadjustment(); my $va =$scrolled_win->get_vadjustment(); - my $h=load_adj ($self,$ha,$name,"ha"); - my $v=load_adj ($self,$va,$name,"va"); - #$ha->set_value($h) if(defined $h); - #$va->set_value($v) if(defined $v); -} - - - - -sub save_adj { - my ($self,$adjustment,$at1,$at2)=@_; - my $value = $adjustment->get_value; - $self->object_add_attribute($at1,$at2,$value) if (defined $self); + my $h=load_adj ($self,$ha,$name,"ha"); + my $v=load_adj ($self,$va,$name,"va"); + #$ha->set_value($h) if(defined $h); + #$va->set_value($v) if(defined $v); } +sub save_adj { + my ($self,$adjustment,$at1,$at2)=@_; + my $value = $adjustment->get_value; + $self->object_add_attribute($at1,$at2,$value) if (defined $self); +} sub load_adj { - my ($self,$adjustment,$at1,$at2)=@_; - return if(!defined $at1); + my ($self,$adjustment,$at1,$at2)=@_; + return if(!defined $at1); my $value= $self->object_get_attribute($at1,$at2); return if(!defined $value); my $lower = $adjustment->get_lower; my $upper = $adjustment->get_upper - $adjustment->get_page_size; - $value= ($value < $lower || $value > $upper ) ? 0 : $value; - - $adjustment->set_value($value); + $value= ($value < $lower || $value > $upper ) ? 0 : $value; + $adjustment->set_value($value); } sub set_pronoc_icon{ - my $window=shift; - my $navIco = gen_pixbuf("./icons/ProNoC.png"); - $window->set_icon($navIco); + my $window=shift; + my $navIco = gen_pixbuf("./icons/ProNoC.png"); + $window->set_icon($navIco); } ############## -# box +# box ############# - sub def_hbox { - my( $homogeneous, $spacing)=@_; - my $box = Gtk3::HBox->new($homogeneous, $spacing); - $box->set_border_width(2); - return $box; + my( $homogeneous, $spacing)=@_; + my $box = Gtk3::HBox->new($homogeneous, $spacing); + $box->set_border_width(2); + return $box; } sub def_vbox { - my $box = Gtk3::VBox->new(FALSE, 0); - $box->set_border_width(2); - return $box; + my $box = Gtk3::VBox->new(FALSE, 0); + $box->set_border_width(2); + return $box; } sub def_pack_hbox{ - my( $homogeneous, $spacing , @box_list)=@_; - my $box=def_hbox($homogeneous, $spacing); - foreach my $subbox (@box_list){ - $box->pack_start( $subbox, FALSE, FALSE, 3); - } - return $box; - - + my( $homogeneous, $spacing , @box_list)=@_; + my $box=def_hbox($homogeneous, $spacing); + foreach my $subbox (@box_list){ + $box->pack_start( $subbox, FALSE, FALSE, 3); + } + return $box; } sub def_pack_vbox{ - my( $homogeneous, $spacing , @box_list)=@_; - my $box=def_vbox($homogeneous, $spacing); - foreach my $subbox (@box_list){ - $box->pack_start( $subbox, FALSE, FALSE, 3); - } - return $box; - + my( $homogeneous, $spacing , @box_list)=@_; + my $box=def_vbox($homogeneous, $spacing); + foreach my $subbox (@box_list){ + $box->pack_start( $subbox, FALSE, FALSE, 3); + } + return $box; } - ########## # Paned ######### - - sub gen_vpaned { - my ($w1,$loc,$w2) = @_; - my $vpaned = Gtk3::VPaned -> new; - my($width,$hight)=max_win_size(); - - - $vpaned -> pack1($w1, TRUE, TRUE); - $vpaned -> set_position ($hight*$loc); - $vpaned -> pack2($w2, TRUE, TRUE); - - return $vpaned; + my ($w1,$loc,$w2) = @_; + my $vpaned = Gtk3::VPaned -> new; + my($width,$hight)=max_win_size(); + $vpaned -> pack1($w1, TRUE, TRUE); + $vpaned -> set_position ($hight*$loc); + $vpaned -> pack2($w2, TRUE, TRUE); + return $vpaned; } - sub gen_hpaned { - my ($w1,$loc,$w2) = @_; - my $hpaned = Gtk3::HPaned -> new; - my($width,$hight)=max_win_size(); - - $hpaned -> pack1($w1, TRUE, TRUE); - $hpaned -> set_position ($width*$loc); - $hpaned -> pack2($w2, TRUE, TRUE); - - return $hpaned; + my ($w1,$loc,$w2) = @_; + my $hpaned = Gtk3::HPaned -> new; + my($width,$hight)=max_win_size(); + $hpaned -> pack1($w1, TRUE, TRUE); + $hpaned -> set_position ($width*$loc); + $hpaned -> pack2($w2, TRUE, TRUE); + return $hpaned; } - sub gen_hpaned_adj { - my ($self,$w1,$loc,$w2,$name) = @_; - my $hpaned = Gtk3::HPaned -> new; - $hpaned -> pack1($w1, TRUE, TRUE); - $hpaned -> pack2($w2, TRUE, TRUE); - - $hpaned->signal_connect("destroy"=> sub{ - my $adj = $hpaned->get_position (); - $self->object_add_attribute("adj",$name,$adj); - }); - - my $val =$self->object_get_attribute("adj",$name); - if(defined $val){ - $hpaned -> set_position ($val); - } else{ - my($width,$hight)=max_win_size(); - $hpaned -> set_position ($width*$loc); - } - - return $hpaned; + my ($self,$w1,$loc,$w2,$name) = @_; + my $hpaned = Gtk3::HPaned -> new; + $hpaned -> pack1($w1, TRUE, TRUE); + $hpaned -> pack2($w2, TRUE, TRUE); + $hpaned->signal_connect("destroy"=> sub{ + my $adj = $hpaned->get_position (); + $self->object_add_attribute("adj",$name,$adj); + }); + my $val =$self->object_get_attribute("adj",$name); + if(defined $val){ + $hpaned -> set_position ($val); + } else{ + my($width,$hight)=max_win_size(); + $hpaned -> set_position ($width*$loc); + } + return $hpaned; } - ############# -# text_view +# text_view ############ - sub create_txview { - my $scrolled_window = Gtk3::ScrolledWindow->new; - $scrolled_window->set_policy ('automatic', 'automatic'); - $scrolled_window->set_shadow_type ('in'); - my $tview = Gtk3::TextView->new(); - $scrolled_window->add ($tview); - - # Make it a bit nicer for text. - $tview->set_wrap_mode ('word'); - $tview->set_pixels_above_lines (2); - $tview->set_pixels_below_lines (2); - # $scrolled_window->set_placement('bottom_left' ); - add_colors_to_textview($tview); - - - $scrolled_window->show_all; - - return ($scrolled_window,$tview); + my $scrolled_window = Gtk3::ScrolledWindow->new; + $scrolled_window->set_policy ('automatic', 'automatic'); + $scrolled_window->set_shadow_type ('in'); + my $tview = Gtk3::TextView->new(); + $scrolled_window->add ($tview); + # Make it a bit nicer for text. + $tview->set_wrap_mode ('word'); + $tview->set_pixels_above_lines (2); + $tview->set_pixels_below_lines (2); + # $scrolled_window->set_placement('bottom_left' ); + add_colors_to_textview($tview); + $scrolled_window->show_all; + return ($scrolled_window,$tview); } - sub txview_scrol_to_end { - my $tview =shift; - my $buffer = $tview->get_buffer; - my $end_mark = $buffer->create_mark( 'end', $buffer->get_end_iter, 0 ); - $tview->scroll_to_mark( $end_mark, 0.0,0, 0.0, 1.0 ); + my $tview =shift; + my $buffer = $tview->get_buffer; + my $end_mark = $buffer->create_mark( 'end', $buffer->get_end_iter, 0 ); + $tview->scroll_to_mark( $end_mark, 0.0,0, 0.0, 1.0 ); } - ################# -# table +# table ################ - sub def_table{ - my ($row,$col,$homogeneous)=@_; - my $table = Gtk3::Table->new ($row, $col, $homogeneous); - $table->set_row_spacings (0); - $table->set_col_spacings (0); - return $table; - + my ($row,$col,$homogeneous)=@_; + my $table = Gtk3::Table->new ($row, $col, $homogeneous); + $table->set_row_spacings (0); + $table->set_col_spacings (0); + return $table; } sub attach_widget_to_table { - my ($table,$row,$label,$inf_bt,$widget,$column)=@_; - $column = 0 if(!defined $column); - #$column *=4; - #my $tmp=gen_label_in_left(" "); - if(defined $label) {$table->attach ($label , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} - if(defined $inf_bt) {$table->attach ($inf_bt , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} - if(defined $widget) {$table->attach ($widget , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} - #$table->attach ($tmp , $column+3, $column+4, $row,$row+1,'fill','shrink',2,2); + my ($table,$row,$label,$inf_bt,$widget,$column)=@_; + $column = 0 if(!defined $column); + #$column *=4; + #my $tmp=gen_label_in_left(" "); + if(defined $label) {$table->attach ($label , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} + if(defined $inf_bt) {$table->attach ($inf_bt , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} + if(defined $widget) {$table->attach ($widget , $column, $column+1, $row,$row+1,'fill','shrink',2,2);$column++;} + #$table->attach ($tmp , $column+3, $column+4, $row,$row+1,'fill','shrink',2,2); } -sub gen_Hsep { - return Gtk3::HSeparator->new; +sub gen_Hsep { + return Gtk3::HSeparator->new; } -sub gen_Vsep { - return Gtk3::VSeparator->new; +sub gen_Vsep { + return Gtk3::VSeparator->new; } - sub add_Hsep_to_table { - my($table,$col0,$col1,$row)=@_; - my $separator = gen_Hsep(); - $table->attach ($separator ,$col0,$col1 , $row, $row+1,'fill','fill',2,2); + my($table,$col0,$col1,$row)=@_; + my $separator = gen_Hsep(); + $table->attach ($separator ,$col0,$col1 , $row, $row+1,'fill','fill',2,2); } sub add_Vsep_to_table { - my($table,$col,$row1,$row2)=@_; - my $separator = gen_Vsep(); - $table->attach ($separator ,$col,$col+1 , $row1, $row2,'fill','fill',2,2); + my($table,$col,$row1,$row2)=@_; + my $separator = gen_Vsep(); + $table->attach ($separator ,$col,$col+1 , $row1, $row2,'fill','fill',2,2); } - ################## -# show_info +# show_info ################## sub show_info{ - my ($textview,$info)=@_; - #return;# if(!defined $textview_ref); - #print "$textview_ref\n"; - my $buffer = $textview->get_buffer(); - $buffer->set_text($info); - txview_scrol_to_end($textview); + my ($textview,$info)=@_; + #return;# if(!defined $textview_ref); + #print "$textview_ref\n"; + my $buffer = $textview->get_buffer(); + $buffer->set_text($info); + txview_scrol_to_end($textview); } sub add_info{ - my ($textview,$info)=@_; - my $buffer = $textview->get_buffer(); - my $textiter = $buffer->get_end_iter(); - #Insert some text into the buffer - $buffer->insert($textiter,$info); - txview_scrol_to_end($textview); - + my ($textview,$info)=@_; + my $buffer = $textview->get_buffer(); + my $textiter = $buffer->get_end_iter(); + #Insert some text into the buffer + $buffer->insert($textiter,$info); + txview_scrol_to_end($textview); } - - - sub show_colored_info{ - my ($textview,$info,$color)=@_; - my $buffer = $textview->get_buffer(); - #$buffer->set_text($info); - my $textiter = $buffer->get_start_iter(); - $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); - txview_scrol_to_end($textview); + my ($textview,$info,$color)=@_; + my $buffer = $textview->get_buffer(); + #$buffer->set_text($info); + my $textiter = $buffer->get_start_iter(); + $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); + txview_scrol_to_end($textview); } sub add_colored_info{ - my ($textview,$info,$color)=@_; - my $buffer = $textview->get_buffer(); - my $textiter = $buffer->get_end_iter(); - #Insert some text into the buffer - #$buffer->insert($textiter,$info); - $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); - txview_scrol_to_end($textview); + my ($textview,$info,$color)=@_; + my $buffer = $textview->get_buffer(); + my $textiter = $buffer->get_end_iter(); + #Insert some text into the buffer + #$buffer->insert($textiter,$info); + $buffer->insert_with_tags_by_name ($textiter, "$info", "${color}_tag"); + txview_scrol_to_end($textview); } sub add_colors_to_textview{ - my $tview= shift; - add_colored_tag($tview,'red'); - add_colored_tag($tview,'blue'); - add_colored_tag($tview,'brown'); - add_colored_tag($tview,'green'); + my $tview= shift; + add_colored_tag($tview,'red'); + add_colored_tag($tview,'blue'); + add_colored_tag($tview,'brown'); + add_colored_tag($tview,'green'); } - sub add_colored_tag{ - my ($textview_ref,$color)=@_; - my $buffer = $textview_ref->get_buffer(); - $buffer->create_tag ("${color}_tag", foreground => $color); + my ($textview_ref,$color)=@_; + my $buffer = $textview_ref->get_buffer(); + $buffer->create_tag ("${color}_tag", foreground => $color); } sub add_color_to_gd{ - foreach (my $i=0;$i<32;$i++ ) { - my ($red,$green,$blue)=get_color($i); - add_colour("my_color$i"=>[$red>>8,$green>>8,$blue>>8]); - - } + foreach (my $i=0;$i<32;$i++ ) { + my ($red,$green,$blue)=get_color($i); + add_colour("my_color$i"=>[$red>>8,$green>>8,$blue>>8]); + } } - - ############ -# get file folder list +# get file folder list ########### - sub get_directory_name_widget { - my ($object,$title,$entry,$attribute1,$attribute2,$status,$timeout)= @_; - my $browse= def_image_button("icons/browse.png"); - - $browse->signal_connect("clicked"=> sub{ - my $entry_ref=$_[1]; - my $file; - $title ='select directory' if(!defined $title); - my $dialog = Gtk3::FileChooserDialog->new( - $title, undef, - # 'open', - 'select-folder', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - $$entry_ref->set_text($file); - $object->object_add_attribute($attribute1,$attribute2,$file); - set_gui_status($object,$status,$timeout) if(defined $status); - #check_input_file($file,$socgen,$soc_state,$info); - #print "file = $file\n"; - } - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - $dialog->destroy; - - - - } , \$entry); - - return $browse; - + my ($object,$title,$entry,$attribute1,$attribute2,$status,$timeout)= @_; + my $browse= def_image_button("icons/browse.png"); + $browse->signal_connect("clicked"=> sub{ + my $entry_ref=$_[1]; + my $file; + $title ='select directory' if(!defined $title); + my $dialog = Gtk3::FileChooserDialog->new( + $title, undef, + # 'open', + 'select-folder', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + $$entry_ref->set_text($file); + $object->object_add_attribute($attribute1,$attribute2,$file); + set_gui_status($object,$status,$timeout) if(defined $status); + #check_input_file($file,$socgen,$soc_state,$info); + #print "file = $file\n"; + } + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + $dialog->destroy; + } , \$entry); + return $browse; } - sub get_dir_name { - my ($object,$title,$attribute1,$attribute2,$open_in,$status,$timeout)= @_; - my $dir; - $title ='select directory' if(!defined $title); - my $dialog = Gtk3::FileChooserDialog->new( - $title, undef, - # 'open', - 'select-folder', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - - if(defined $open_in){ - $dialog->set_current_folder ($open_in); - } - - if ( "ok" eq $dialog->run ) { - $dir = $dialog->get_filename; - $object->object_add_attribute($attribute1,$attribute2,$dir); - set_gui_status($object,$status,$timeout) if(defined $status); - $dialog->destroy; - } + my ($object,$title,$attribute1,$attribute2,$open_in,$status,$timeout)= @_; + my $dir; + $title ='select directory' if(!defined $title); + my $dialog = Gtk3::FileChooserDialog->new( + $title, undef, + # 'open', + 'select-folder', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + if(defined $open_in){ + $dialog->set_current_folder ($open_in); + } + if ( "ok" eq $dialog->run ) { + $dir = $dialog->get_filename; + $object->object_add_attribute($attribute1,$attribute2,$dir); + set_gui_status($object,$status,$timeout) if(defined $status); + $dialog->destroy; + } } - - sub get_file_name { - my ($object,$title,$entry,$attribute1,$attribute2,$extension,$label,$open_in,$new_status,$ref_delay)= @_; - my $browse= def_image_button("icons/browse.png"); - - $browse->signal_connect("clicked"=> sub{ - my $entry_ref=$_[1]; - my $file; - $title ='select a file' if(!defined $title); - my $dialog = Gtk3::FileChooserDialog->new( - 'Select a File', undef, - 'open', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - - if(defined $extension){ - my $filter = Gtk3::FileFilter->new(); - $filter->set_name($extension); - $filter->add_pattern("*.$extension"); - $dialog->add_filter ($filter); - } - if(defined $open_in){ - $dialog->set_current_folder ($open_in); - # print "$open_in\n"; - - } - - if ( "ok" eq $dialog->run ) { - $file = $dialog->get_filename; - #remove $project_dir form beginig of each file - $file =remove_project_dir_from_addr($file); - $$entry_ref->set_text($file); - $object->object_add_attribute($attribute1,$attribute2,$file) if(defined $object); - set_gui_status($object,$new_status,$ref_delay) if(defined $ref_delay); - my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); - if(defined $label){ - $label->set_markup("$name$suffix"); - $label->show; - } - - #check_input_file($file,$socgen,$soc_state,$info); - #print "file = $file\n"; - } - $dialog->destroy; - - - - } , \$entry); - - return $browse; - + my ($object,$title,$entry,$attribute1,$attribute2,$extension,$label,$open_in,$new_status,$ref_delay)= @_; + my $browse= def_image_button("icons/browse.png"); + $browse->signal_connect("clicked"=> sub{ + my $entry_ref=$_[1]; + my $file; + $title ='select a file' if(!defined $title); + my $dialog = Gtk3::FileChooserDialog->new( + 'Select a File', undef, + 'open', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + if(defined $extension){ + my $filter = Gtk3::FileFilter->new(); + $filter->set_name($extension); + $filter->add_pattern("*.$extension"); + $dialog->add_filter ($filter); + } + if(defined $open_in){ + $dialog->set_current_folder ($open_in); + # print "$open_in\n"; + } + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + #remove $project_dir form beginig of each file + $file =remove_project_dir_from_addr($file); + $$entry_ref->set_text($file); + $object->object_add_attribute($attribute1,$attribute2,$file) if(defined $object); + set_gui_status($object,$new_status,$ref_delay) if(defined $ref_delay); + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if(defined $label){ + $label->set_markup("$name$suffix"); + $label->show; + } + #check_input_file($file,$socgen,$soc_state,$info); + #print "file = $file\n"; + } + $dialog->destroy; + } , \$entry); + return $browse; } sub gen_file_dialog { - my ($title, @extension)=@_; - $title = 'Select a File' if (!defined $title); - - my $dialog = Gtk3::FileChooserDialog->new( - $title, - undef, - 'open', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - $dialog->set_modal(TRUE); - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - - foreach my $ext (@extension){ - my $filter = Gtk3::FileFilter->new(); - $filter->set_name("$ext"); - $filter->add_pattern("*.$ext"); - $dialog->add_filter ($filter); - } - - return $dialog; - + my ($title, @extension)=@_; + $title = 'Select a File' if (!defined $title); + my $dialog = Gtk3::FileChooserDialog->new( + $title, + undef, + 'open', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + $dialog->set_modal(TRUE); + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + foreach my $ext (@extension){ + my $filter = Gtk3::FileFilter->new(); + $filter->set_name("$ext"); + $filter->add_pattern("*.$ext"); + $dialog->add_filter ($filter); + } + return $dialog; } - sub save_file_dialog { - my ($title, @extension)=@_; - $title = 'Select a File' if (!defined $title); - - my $dialog = Gtk3::FileChooserDialog->new( - $title, - undef, - 'save', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - - $dialog->set_modal(TRUE); - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - - foreach my $ext (@extension){ - my $filter = Gtk3::FileFilter->new(); - $filter->set_name("$ext"); - $filter->add_pattern("*.$ext"); - $dialog->add_filter ($filter); - } - - return $dialog; - + my ($title, @extension)=@_; + $title = 'Select a File' if (!defined $title); + my $dialog = Gtk3::FileChooserDialog->new( + $title, + undef, + 'save', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + $dialog->set_modal(TRUE); + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + foreach my $ext (@extension){ + my $filter = Gtk3::FileFilter->new(); + $filter->set_name("$ext"); + $filter->add_pattern("*.$ext"); + $dialog->add_filter ($filter); + } + return $dialog; } - - - sub gen_folder_dialog { - my ($title)=@_; - $title = 'Select Folder' if (!defined $title); - - - - my $dialog = Gtk3::FileChooserDialog->new( - $title, - undef, - 'select-folder', - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - $dialog->set_modal(TRUE); - $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - - return $dialog; - + my ($title)=@_; + $title = 'Select Folder' if (!defined $title); + my $dialog = Gtk3::FileChooserDialog->new( + $title, + undef, + 'select-folder', + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); + $dialog->set_modal(TRUE); + $dialog->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning + return $dialog; } - sub get_filenames_from_dialog{ - my $dialog=shift; - my $ref = $dialog->get_filenames; - my @files; - @files = @{$ref} if (defined $ref); - return @files; + my $dialog=shift; + my $ref = $dialog->get_filenames; + my @files; + @files = @{$ref} if (defined $ref); + return @files; } - sub new_dialog_with_buttons { - my $self =shift; - return Gtk3::Dialog->new_with_buttons( - "Goto to line", - $self->window, - [ 'modal' ], - 'gtk-cancel' => 'cancel', - 'gtk-ok' => 'ok', - ); - + my $self =shift; + return Gtk3::Dialog->new_with_buttons( + "Goto to line", + $self->window, + [ 'modal' ], + 'gtk-cancel' => 'cancel', + 'gtk-ok' => 'ok', + ); } - ################# -# widget update object +# widget update object ################# - sub gen_entry_object { - my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; - my $old=$object->object_get_attribute($attribute1,$attribute2); - my $widget; - if(defined $old ){ - $widget=gen_entry($old); - } - else - { - $widget=gen_entry($default); - $object->object_add_attribute($attribute1,$attribute2,$default); - } - $widget-> signal_connect("changed" => sub{ - my $new_param_value=$widget->get_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; + my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; + my $old=$object->object_get_attribute($attribute1,$attribute2); + my $widget; + if(defined $old ){ + $widget=gen_entry($old); + } + else + { + $widget=gen_entry($default); + $object->object_add_attribute($attribute1,$attribute2,$default); + } + $widget-> signal_connect("changed" => sub{ + my $new_param_value=$widget->get_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - sub gen_combobox_object { - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - my @combo_list=split(/\s*,\s*/,$content); - my $value=$object->object_get_attribute($attribute1,$attribute2); - my $pos; - $pos=get_pos($value, @combo_list) if (defined $value); - if(!defined $pos && defined $default){ - $object->object_add_attribute($attribute1,$attribute2,$default); - $pos=get_item_pos($default, @combo_list); - } - #print " my $pos=get_item_pos($value, @combo_list);\n"; - my $widget=gen_combo(\@combo_list, $pos); - $widget-> signal_connect("changed" => sub{ - my $new_param_value=$widget->get_active_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; + my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; + my @combo_list=split(/\s*,\s*/,$content); + my $value=$object->object_get_attribute($attribute1,$attribute2); + my $pos; + $pos=get_pos($value, @combo_list) if (defined $value); + if(!defined $pos && defined $default){ + $object->object_add_attribute($attribute1,$attribute2,$default); + $pos=get_item_pos($default, @combo_list); + } + #print " my $pos=get_item_pos($value, @combo_list);\n"; + my $widget=gen_combo(\@combo_list, $pos); + $widget-> signal_connect("changed" => sub{ + my $new_param_value=$widget->get_active_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - sub gen_comboentry_object { - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - my @combo_list; - @combo_list=split(/\s*,\s*/,$content) if(defined $content ); - my $value=$object->object_get_attribute($attribute1,$attribute2); - my $pos; - $pos=get_pos($value, @combo_list) if (defined $value); - if(!defined $pos && defined $default){ - $object->object_add_attribute($attribute1,$attribute2,$default); - $pos=get_item_pos($default, @combo_list); - } - #print " my $pos=get_item_pos($value, @combo_list);\n"; - - my $widget=gen_combo_entry(\@combo_list, $pos); - my $child = combo_entry_get_chiled($widget); - $child->signal_connect('changed' => sub { - my ($entry) = @_; - my $new_param_value=$entry->get_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; - + my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; + my @combo_list; + @combo_list=split(/\s*,\s*/,$content) if(defined $content ); + my $value=$object->object_get_attribute($attribute1,$attribute2); + my $pos; + $pos=get_pos($value, @combo_list) if (defined $value); + if(!defined $pos && defined $default){ + $object->object_add_attribute($attribute1,$attribute2,$default); + $pos=get_item_pos($default, @combo_list); + } + #print " my $pos=get_item_pos($value, @combo_list);\n"; + my $widget=gen_combo_entry(\@combo_list, $pos); + my $child = combo_entry_get_chiled($widget); + $child->signal_connect('changed' => sub { + my ($entry) = @_; + my $new_param_value=$entry->get_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - - sub gen_spin_object { - my ($object,$attribute1,$attribute2,$content, $default,$status,$timeout)=@_; - my $value=$object->object_get_attribute($attribute1,$attribute2); - my ($min,$max,$step,$digit)=split(/\s*,\s*/,$content); - if(!defined $value){ - $value=$default; - $object->object_add_attribute($attribute1,$attribute2,$value); - } - - $value=~ s/[^0-9.\-]//g; - $min=~ s/[^0-9.\-]//g; - $max=~ s/[^0-9.\-]//g; - $step=~ s/[^0-9.\-]//g; - $digit=~ s/[^0-9.\-]//g if (defined $digit); - - my $widget=gen_spin($min,$max,$step,$digit); - $widget->set_value($value); - $widget-> signal_connect("value_changed" => sub{ - my $new_param_value=$widget->get_value(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - }); - return $widget; + my ($object,$attribute1,$attribute2,$content, $default,$status,$timeout)=@_; + my $value=$object->object_get_attribute($attribute1,$attribute2); + my ($min,$max,$step,$digit)=split(/\s*,\s*/,$content); + if(!defined $value){ + $value=$default; + $object->object_add_attribute($attribute1,$attribute2,$value); + } + $value=~ s/[^0-9.\-]//g; + $min=~ s/[^0-9.\-]//g; + $max=~ s/[^0-9.\-]//g; + $step=~ s/[^0-9.\-]//g; + $digit=~ s/[^0-9.\-]//g if (defined $digit); + my $widget=gen_spin($min,$max,$step,$digit); + $widget->set_value($value); + $widget-> signal_connect("value_changed" => sub{ + my $new_param_value=$widget->get_value(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - sub gen_check_box_object_array { - my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; - my $value=$object->object_get_attribute($attribute1,$attribute2); - $value = $default if (!defined $value); - my $widget = def_hbox(FALSE,0); - my @check; - for (my $i=0;$i<$content;$i++){ - $check[$i]= gen_checkbutton(); - } - for (my $i=0;$i<$content;$i++){ - $widget->pack_end( $check[$i], FALSE, FALSE, 0); - - my @chars = split("",$value); - #check if saved value match the size of check box - if($chars[0] ne $content ) { - $object->object_add_attribute($attribute1,$attribute2,$default); - $value=$default; - @chars = split("",$value); - } - #set initial value - - #print "\@chars=@chars\n"; - for (my $i=0;$i<$content;$i++){ - my $loc= (scalar @chars) -($i+1); - if( $chars[$loc] eq '1') {$check[$i]->set_active(TRUE);} - else {$check[$i]->set_active(FALSE);} - } - - - #get new value - $check[$i]-> signal_connect("toggled" => sub{ - my $new_val="$content\'b"; - - for (my $i=$content-1; $i >= 0; $i--){ - if($check[$i]->get_active()) {$new_val="${new_val}1" ;} - else {$new_val="${new_val}0" ;} - } - $object->object_add_attribute($attribute1,$attribute2,$new_val); - #print "\$new_val=$new_val\n"; - set_gui_status($object,$status,$timeout) if (defined $status); - }); - } - return $widget; - + my ($object,$attribute1,$attribute2,$content,$default,$status,$timeout)=@_; + my $value=$object->object_get_attribute($attribute1,$attribute2); + $value = $default if (!defined $value); + my $widget = def_hbox(FALSE,0); + my @check; + for (my $i=0;$i<$content;$i++){ + $check[$i]= gen_checkbutton(); + } + for (my $i=0;$i<$content;$i++){ + $widget->pack_end( $check[$i], FALSE, FALSE, 0); + my @chars = split("",$value); + #check if saved value match the size of check box + if($chars[0] ne $content ) { + $object->object_add_attribute($attribute1,$attribute2,$default); + $value=$default; + @chars = split("",$value); + } + #set initial value + #print "\@chars=@chars\n"; + for (my $i=0;$i<$content;$i++){ + my $loc= (scalar @chars) -($i+1); + if( $chars[$loc] eq '1') {$check[$i]->set_active(TRUE);} + else {$check[$i]->set_active(FALSE);} + } + #get new value + $check[$i]-> signal_connect("toggled" => sub{ + my $new_val="$content\'b"; + for (my $i=$content-1; $i >= 0; $i--){ + if($check[$i]->get_active()) {$new_val="${new_val}1" ;} + else {$new_val="${new_val}0" ;} + } + $object->object_add_attribute($attribute1,$attribute2,$new_val); + #print "\$new_val=$new_val\n"; + set_gui_status($object,$status,$timeout) if (defined $status); + }); + } + return $widget; } - - - - sub gen_check_box_object { - my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; - my $value=$object->object_get_attribute($attribute1,$attribute2); - if (!defined $value){ - #set initial value - $object->object_add_attribute($attribute1,$attribute2,$default); - $value = $default - } - my $widget = Gtk3::CheckButton->new; - if($value == 1) {$widget->set_active(TRUE);} - else {$widget->set_active(FALSE);} - - #get new value - $widget-> signal_connect("toggled" => sub{ - my $new_val; - if($widget->get_active()) {$new_val=1;} - else {$new_val=0;} - $object->object_add_attribute($attribute1,$attribute2,$new_val); - #print "\$new_val=$new_val\n"; - set_gui_status($object,$status,$timeout) if (defined $status); - }); - - return $widget; - + my ($object,$attribute1,$attribute2,$default,$status,$timeout)=@_; + my $value=$object->object_get_attribute($attribute1,$attribute2); + if (!defined $value){ + #set initial value + $object->object_add_attribute($attribute1,$attribute2,$default); + $value = $default + } + my $widget = Gtk3::CheckButton->new; + if($value == 1) {$widget->set_active(TRUE);} + else {$widget->set_active(FALSE);} + #get new value + $widget-> signal_connect("toggled" => sub{ + my $new_val; + if($widget->get_active()) {$new_val=1;} + else {$new_val=0;} + $object->object_add_attribute($attribute1,$attribute2,$new_val); + #print "\$new_val=$new_val\n"; + set_gui_status($object,$status,$timeout) if (defined $status); + }); + return $widget; } - - - - - sub get_dir_in_object { - my ($object,$attribute1,$attribute2,$content,$status,$timeout,$default)=@_; - my $widget = def_hbox(FALSE,0); - my $value=$object->object_get_attribute($attribute1,$attribute2); - $object->object_add_attribute($attribute1,$attribute2, $default) if (!defined $value ); - $value = $default if (!defined $value ); - if (defined $default){ - $object->object_add_attribute($attribute1,$attribute2, $default) if !(-d $value ); - $value = $default if !(-d $value ); - }; - - my $warning; - - my $entry=gen_entry($value); - $entry-> signal_connect("changed" => sub{ - my $new_param_value=$entry->get_text(); - $object->object_add_attribute($attribute1,$attribute2,$new_param_value); - set_gui_status($object,$status,$timeout) if (defined $status); - unless (-d $new_param_value ){ - if (!defined $warning){ - $warning = def_icon("icons/warning.png"); - $widget->pack_start( $warning, FALSE, FALSE, 0); - set_tip($warning,"$new_param_value is not a valid directory"); - $widget->show_all; - } - - }else{ - $warning->destroy if (defined $warning); - undef $warning; - - } - - }); - my $browse= get_directory_name_widget($object,undef,$entry,$attribute1,$attribute2,$status,$timeout); - - $widget->pack_start( $entry, FALSE, FALSE, 0); - $widget->pack_start( $browse, FALSE, FALSE, 0); - - if(defined $value){ - unless (-d $value ){ - $warning= def_icon("icons/warning.png"); - $widget->pack_start( $warning, FALSE, FALSE, 0); - set_tip($warning,"$value is not a valid directory path"); - } - } - return $widget; + my ($object,$attribute1,$attribute2,$content,$status,$timeout,$default)=@_; + my $widget = def_hbox(FALSE,0); + my $value=$object->object_get_attribute($attribute1,$attribute2); + $object->object_add_attribute($attribute1,$attribute2, $default) if (!defined $value ); + $value = $default if (!defined $value ); + if (defined $default){ + $object->object_add_attribute($attribute1,$attribute2, $default) if !(-d $value ); + $value = $default if !(-d $value ); + }; + my $warning; + my $entry=gen_entry($value); + $entry-> signal_connect("changed" => sub{ + my $new_param_value=$entry->get_text(); + $object->object_add_attribute($attribute1,$attribute2,$new_param_value); + set_gui_status($object,$status,$timeout) if (defined $status); + unless (-d $new_param_value ){ + if (!defined $warning){ + $warning = def_icon("icons/warning.png"); + $widget->pack_start( $warning, FALSE, FALSE, 0); + set_tip($warning,"$new_param_value is not a valid directory"); + $widget->show_all; + } + }else{ + $warning->destroy if (defined $warning); + undef $warning; + } + }); + my $browse= get_directory_name_widget($object,undef,$entry,$attribute1,$attribute2,$status,$timeout); + $widget->pack_start( $entry, FALSE, FALSE, 0); + $widget->pack_start( $browse, FALSE, FALSE, 0); + if(defined $value){ + unless (-d $value ){ + $warning= def_icon("icons/warning.png"); + $widget->pack_start( $warning, FALSE, FALSE, 0); + set_tip($warning,"$value is not a valid directory path"); + } + } + return $widget; } - - - sub get_file_name_object { - my ($object,$attribute1,$attribute2,$extension,$open_in,$new_status,$ref_delay)=@_; - my $widget = def_hbox(FALSE,0); - my $value=$object->object_get_attribute($attribute1,$attribute2); - my $label; - if(defined $value){ - my ($name,$path,$suffix) = fileparse("$value",qr"\..[^.]*$"); - $label=gen_label_in_center($name.$suffix); - - } else { - $label=gen_label_in_center("Selecet a file"); - $label->set_markup("No file has been selected yet"); - } - my $entry=gen_entry(); - my $browse= get_file_name($object,undef,$entry,$attribute1,$attribute2,$extension,$label,$open_in,$new_status,$ref_delay); - $widget->pack_start( $label, FALSE, FALSE, 0); - $widget->pack_start( $browse, FALSE, FALSE, 0); - return $widget; + my ($object,$attribute1,$attribute2,$extension,$open_in,$new_status,$ref_delay)=@_; + my $widget = def_hbox(FALSE,0); + my $value=$object->object_get_attribute($attribute1,$attribute2); + my $label; + if(defined $value){ + my ($name,$path,$suffix) = fileparse("$value",qr"\..[^.]*$"); + $label=gen_label_in_center($name.$suffix); + } else { + $label=gen_label_in_center("Selecet a file"); + $label->set_markup("No file has been selected yet"); + } + my $entry=gen_entry(); + my $browse= get_file_name($object,undef,$entry,$attribute1,$attribute2,$extension,$label,$open_in,$new_status,$ref_delay); + $widget->pack_start( $label, FALSE, FALSE, 0); + $widget->pack_start( $browse, FALSE, FALSE, 0); + return $widget; } - - - - sub gen_notebook { - my $notebook = Gtk3::Notebook->new; - return $notebook; + my $notebook = Gtk3::Notebook->new; + return $notebook; } + ################ # ADD info and label to widget ################ - - sub gen_label_info{ - my ($label_name,$widget,$info)=@_; - my $box = def_hbox(FALSE,0); - #label - if(defined $label_name){ - my $label= gen_label_in_left($label_name); - $box->pack_start( $label, FALSE, FALSE, 3); - } - $box->pack_start( $widget, FALSE, FALSE, 3); - #info - if(defined $info){ - my $button=def_image_button("icons/help.png"); - $button->signal_connect("clicked" => sub {message_dialog($info);}); - $box->pack_start( $button, FALSE, FALSE, 3); - } - $box->show_all; - return $box; -} - + my ($label_name,$widget,$info)=@_; + my $box = def_hbox(FALSE,0); + #label + if(defined $label_name){ + my $label= gen_label_in_left($label_name); + $box->pack_start( $label, FALSE, FALSE, 3); + } + $box->pack_start( $widget, FALSE, FALSE, 3); + #info + if(defined $info){ + my $button=def_image_button("icons/help.png"); + $button->signal_connect("clicked" => sub {message_dialog($info);}); + $box->pack_start( $button, FALSE, FALSE, 3); + } + $box->show_all; + return $box; +} ############ # ########### - sub gen_MenuBar{ - my ($window,@menu_items)=@_; - - my $accel_group = Gtk3::AccelGroup->new; - $window->add_accel_group ($accel_group); - my $menubar = Gtk3::MenuBar->new; - my $menu = Gtk3::Menu->new; + my ($window,@menu_items)=@_; + my $accel_group = Gtk3::AccelGroup->new; + $window->add_accel_group ($accel_group); + my $menubar = Gtk3::MenuBar->new; + my $menu = Gtk3::Menu->new; $menu->set_accel_group ($accel_group); - - my %all_menus; - foreach my $p (@menu_items){ - my ($name,$key,$func,$u,$type)=@{$p}; - $name =~ s/_//; - my @l =split ('/',$name); - - my $m= pop @l; - $m =~ s/_//; - my $parent = join('/',@l); - $parent =~ s/_//; - - - # print "\$parent= $parent ** \$m=$m\n"; - # print " all_menus{$parent} = $all_menus{$parent}\n"; - my $menuitem = Gtk3::MenuItem->new_with_label($m); - - if(!defined $all_menus{$parent}){ - my $menu = Gtk3::Menu->new; - $menu->set_accel_group ($accel_group); - $menuitem->set_submenu($menu); - $all_menus{$name}{'menu'}=$menu; - $all_menus{$name}{'num'}=0; - $menubar->append($menuitem) - }else { - my $menu = $all_menus{$parent}{'menu'}; - my $pos = $all_menus{$parent}{'num'}; - $menu->insert($menuitem,$pos); - $all_menus{$parent}{'num'}= $pos+1; - if(defined $type){ - if($type eq ""){ - $all_menus{$name}{'menu'}=$menu; - $all_menus{$name}{'num'}=0; - }} - - } - if(defined $key){ - $menuitem->add_accelerator('activate',$accel_group,Gtk3::accelerator_parse($key),'visible'); - } - if(defined $func){ - $menuitem->signal_connect('activate' => \&$func); - } - #print "$name,$key,$func,$u,$type\n"; - $menuitem->show(); - } - - my $box = Gtk3::Box->new( 'vertical', 0 ); - $box->pack_start( $menubar, FALSE, TRUE, 0 ); - $menubar->show(); - - return $box; + my %all_menus; + foreach my $p (@menu_items){ + my ($name,$key,$func,$u,$type)=@{$p}; + $name =~ s/_//; + my @l =split ('/',$name); + my $m= pop @l; + $m =~ s/_//; + my $parent = join('/',@l); + $parent =~ s/_//; + # print "\$parent= $parent ** \$m=$m\n"; + # print " all_menus{$parent} = $all_menus{$parent}\n"; + my $menuitem = Gtk3::MenuItem->new_with_label($m); + if(!defined $all_menus{$parent}){ + my $menu = Gtk3::Menu->new; + $menu->set_accel_group ($accel_group); + $menuitem->set_submenu($menu); + $all_menus{$name}{'menu'}=$menu; + $all_menus{$name}{'num'}=0; + $menubar->append($menuitem) + }else { + my $menu = $all_menus{$parent}{'menu'}; + my $pos = $all_menus{$parent}{'num'}; + $menu->insert($menuitem,$pos); + $all_menus{$parent}{'num'}= $pos+1; + if(defined $type){ + if($type eq ""){ + $all_menus{$name}{'menu'}=$menu; + $all_menus{$name}{'num'}=0; + }} + } + if(defined $key){ + $menuitem->add_accelerator('activate',$accel_group,Gtk3::accelerator_parse($key),'visible'); + } + if(defined $func){ + $menuitem->signal_connect('activate' => \&$func); + } + #print "$name,$key,$func,$u,$type\n"; + $menuitem->show(); + } + my $box = Gtk3::Box->new( 'vertical', 0 ); + $box->pack_start( $menubar, FALSE, TRUE, 0 ); + $menubar->show(); + return $box; } - - sub creating_detachable_toolbar{ - my @attachments=@_; - return def_pack_hbox('FALSE', 0, @_); - #The handle box helps in creating a detachable toolbar - my $hb = Gtk3::HandleBox->new; - #create a toolbar, and do some initial settings - my $toolbar = Gtk3::Toolbar->new; - $toolbar->set_icon_size ('small-toolbar'); - $toolbar->set_show_arrow (FALSE); - foreach my $p (@attachments){ - $toolbar->insert($p,-1); - - } - $hb->add($toolbar); - return $hb; + my @attachments=@_; + return def_pack_hbox('FALSE', 0, @_); + #The handle box helps in creating a detachable toolbar + my $hb = Gtk3::HandleBox->new; + #create a toolbar, and do some initial settings + my $toolbar = Gtk3::Toolbar->new; + $toolbar->set_icon_size ('small-toolbar'); + $toolbar->set_show_arrow (FALSE); + foreach my $p (@attachments){ + $toolbar->insert($p,-1); + } + $hb->add($toolbar); + return $hb; } sub gui_quite{ - Gtk3->main_quit; + Gtk3->main_quit; } sub gtk_gui_run{ - my ($main)=@_; - Gtk3->init; - &$main; - Gtk3->main(); - return 1; + my ($main)=@_; + Gtk3->init; + &$main; + Gtk3->main(); + return 1; } - - - sub refresh_gui{ - while (Gtk3::events_pending) { - Gtk3::main_iteration; + while (Gtk3::events_pending) { + Gtk3::main_iteration; } - Gtk3::Gdk::flush; + Gtk3::Gdk::flush; } - sub about { my $version=shift; my $about = Gtk3::AboutDialog->new; - my @authors=("Alireza Monemi", "Email: alirezamonemi\@opencores.org"); + my @authors=("Alireza Monemi", "Email: alirezamonemi\@opencores.org"); $about->set_authors(\@authors); $about->set_version( $version ); $about->set_website('http://opencores.org/project,an-fpga-implementation-of-low-latency-noc-based-mpsoc'); @@ -1875,135 +1553,93 @@ sub about { $about->set_program_name('ProNoC'); my $pixbuf = Gtk3::Gdk::Pixbuf->new_from_file_at_scale("icons/ProNoC.png",50,50,FALSE); $about->set_logo($pixbuf); - $about->set_license( - "This program is free software; you can redistribute it\n" + "This program is free software; you can redistribute it\n" . "and/or modify it under the terms of the GNU General \n" - . "Public License as published by the Free Software \n" - . "Foundation; either version 1, or (at your option)\n" - . "any later version.\n\n" - + . "Public License as published by the Free Software \n" + . "Foundation; either version 1, or (at your option)\n" + . "any later version.\n\n" ); - # Add the Hide action to the 'Close' button in the AboutDialog(): + # Add the Hide action to the 'Close' button in the AboutDialog(): $about->signal_connect('response' => sub { $about->hide; }); - - $about->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning - + $about->set_transient_for (Gtk3::Window->new('toplevel'));#just to get rid of transient warning $about->run; $about->destroy; return; } - - ############ # list_store ########### - sub gen_list_store { - my ($dref,$clmn_type_ref, $clmn_lables_ref)=@_; - - -# my @data = ( -# {0 => "Average distance", 1 =>"$avg"}, -# {0 => "Max distance", 1 =>"$max" }, -# {0 => "Min distance",1 => "$min"}, -# {0 => "Normlized data per hop", 1 =>"$norm" } -# ); - -# my @clmn_type = (#'Glib::Boolean', # => G_TYPE_BOOLEAN -# #'Glib::Uint', # => G_TYPE_UINT -# 'Glib::String', # => G_TYPE_STRING -# 'Glib::String'); # you get the idea - - - my @data = @{$dref}; - my @clmn_type = @{$clmn_type_ref}; - my @clmn_lables= @{$clmn_lables_ref}; - - + my ($dref,$clmn_type_ref, $clmn_lables_ref)=@_; + # my @data = ( + # {0 => "Average distance", 1 =>"$avg"}, + # {0 => "Max distance", 1 =>"$max" }, + # {0 => "Min distance",1 => "$min"}, + # {0 => "Normlized data per hop", 1 =>"$norm" } + # ); + # my @clmn_type = (#'Glib::Boolean', # => G_TYPE_BOOLEAN + # #'Glib::Uint', # => G_TYPE_UINT + # 'Glib::String', # => G_TYPE_STRING + # 'Glib::String'); # you get the idea + my @data = @{$dref}; + my @clmn_type = @{$clmn_type_ref}; + my @clmn_lables= @{$clmn_lables_ref}; # create list store my $store = Gtk3::ListStore->new ( @clmn_type); - - - # add data to the list store - foreach my $d (@data) { - my $iter = $store->append; - my @clmns = sort keys %{$d}; - my @a=($iter); - foreach my $c (@clmns){ - push (@a,($c,$d->{$c})); - - } - $store->set (@a); - - } - - + # add data to the list store + foreach my $d (@data) { + my $iter = $store->append; + my @clmns = sort keys %{$d}; + my @a=($iter); + foreach my $c (@clmns){ + push (@a,($c,$d->{$c})); + } + $store->set (@a); + } my $treeview = Gtk3::TreeView->new ($store); $treeview->set_rules_hint (TRUE); - $treeview->set_search_column (1); + $treeview->set_search_column (1); #my $renderer = Gtk3::CellRendererToggle->new; #$renderer->signal_connect (toggled => \&fixed_toggled, $store); - - - # column for severities - my $c=0; - foreach my $l (@clmn_lables){ - my $renderer = Gtk3::CellRendererText->new; - my $column = Gtk3::TreeViewColumn->new_with_attributes ("$l", - $renderer, - text => $c - ); - $column->set_sort_column_id ($c ); - $treeview->append_column ($column); - $c++; - } - - - return $treeview; + # column for severities + my $c=0; + foreach my $l (@clmn_lables){ + my $renderer = Gtk3::CellRendererText->new; + my $column = Gtk3::TreeViewColumn->new_with_attributes ( + "$l", + $renderer, + text => $c + ); + $column->set_sort_column_id ($c ); + $treeview->append_column ($column); + $c++; + } + return $treeview; } - - - - ############## -# create tree +# create tree ############## - - sub create_tree_model_network_maker{ - my $model = Gtk3::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); - my $tree_view = Gtk3::TreeView->new; - $tree_view->set_model ($model); - my $selection = $tree_view->get_selection; - $selection->set_mode ("single"); - my $cell = Gtk3::CellRendererText->new; - $cell->set ('style' => 'italic'); - my $column = Gtk3::TreeViewColumn->new_with_attributes ("select", $cell, 'text' => 0, 'style_set' => 3); - return ($model,$tree_view,$column); + my $model = Gtk3::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); + my $tree_view = Gtk3::TreeView->new; + $tree_view->set_model ($model); + my $selection = $tree_view->get_selection; + $selection->set_mode ("single"); + my $cell = Gtk3::CellRendererText->new; + $cell->set ('style' => 'italic'); + my $column = Gtk3::TreeViewColumn->new_with_attributes ("select", $cell, 'text' => 0, 'style_set' => 3); + return ($model,$tree_view,$column); } - sub treemodel_next_iter{ - my ($child , $tree_model)=@_; - $tree_model->iter_next ($child); - return $child; + my ($child , $tree_model)=@_; + $tree_model->iter_next ($child); + return $child; } - - - - - - - - - - - - # clean names for column numbers. use constant DISPLAY_COLUMN => 0; use constant CATRGORY_COLUMN => 1; @@ -2012,239 +1648,184 @@ sub treemodel_next_iter{ use constant NUM_COLUMNS => 4; sub create_tree { - my ($self,$label,$info,$tree_ref,$row_selected_func,$row_activated_func)=@_; - my %tree_in = %{$tree_ref}; - my $model = Gtk3::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); - my $tree_view = Gtk3::TreeView->new; - $tree_view->set_model ($model); - my $selection = $tree_view->get_selection; - $selection->set_mode ('browse'); - - - - foreach my $p (sort keys %tree_in) - { - - my @modules= @{$tree_in{$p}}; - #my @dev_entry= @{$tree_entry{$p}}; - my $iter = $model->append (undef); - $model->set ($iter, - DISPLAY_COLUMN, $p, - CATRGORY_COLUMN, $p || '', - MODULE_COLUMN, 0 || '', - ITALIC_COLUMN, FALSE); - - next unless @modules; - - foreach my $v ( @modules){ - my $child_iter = $model->append ($iter); - my $entry= ''; - - $model->set ($child_iter, - DISPLAY_COLUMN, $v, - CATRGORY_COLUMN, $p|| '', - MODULE_COLUMN, $v || '', - ITALIC_COLUMN, FALSE); - } - - - - } - - my $cell = Gtk3::CellRendererText->new; - $cell->set ('style' => 'italic'); - my $column = Gtk3::TreeViewColumn->new_with_attributes - ("$label", - $cell, - 'text' => DISPLAY_COLUMN, - 'style_set' => ITALIC_COLUMN); - - $tree_view->append_column ($column); - my @ll=($model,$info); - #row selected - $selection->signal_connect (changed =>sub { - my ($selection, $ref) = @_; - my ($model,$info)=@{$ref}; - my $iter = $selection->get_selected; - return unless defined $iter; - - my ($category) = $model->get ($iter, CATRGORY_COLUMN); - my ($module) = $model->get ($iter,MODULE_COLUMN ); - $row_selected_func->($self,$category,$module,$info) if(defined $row_selected_func); - - - + my ($self,$label,$info,$tree_ref,$row_selected_func,$row_activated_func)=@_; + my %tree_in = %{$tree_ref}; + my $model = Gtk3::TreeStore->new ('Glib::String', 'Glib::String', 'Glib::Scalar', 'Glib::Boolean'); + my $tree_view = Gtk3::TreeView->new; + $tree_view->set_model ($model); + my $selection = $tree_view->get_selection; + $selection->set_mode ('browse'); + foreach my $p (sort keys %tree_in) + { + my @modules= @{$tree_in{$p}}; + #my @dev_entry= @{$tree_entry{$p}}; + my $iter = $model->append (undef); + $model->set ( + $iter, + DISPLAY_COLUMN, $p, + CATRGORY_COLUMN, $p || '', + MODULE_COLUMN, 0 || '', + ITALIC_COLUMN, FALSE); + next unless @modules; + foreach my $v ( @modules){ + my $child_iter = $model->append ($iter); + my $entry= ''; + $model->set ($child_iter, + DISPLAY_COLUMN, $v, + CATRGORY_COLUMN, $p|| '', + MODULE_COLUMN, $v || '', + ITALIC_COLUMN, FALSE); + } + } + my $cell = Gtk3::CellRendererText->new; + $cell->set ('style' => 'italic'); + my $column = Gtk3::TreeViewColumn->new_with_attributes ( + "$label", + $cell, + 'text' => DISPLAY_COLUMN, + 'style_set' => ITALIC_COLUMN); + $tree_view->append_column ($column); + my @ll=($model,$info); + #row selected + $selection->signal_connect (changed =>sub { + my ($selection, $ref) = @_; + my ($model,$info)=@{$ref}; + my $iter = $selection->get_selected; + return unless defined $iter; + my ($category) = $model->get ($iter, CATRGORY_COLUMN); + my ($module) = $model->get ($iter,MODULE_COLUMN ); + $row_selected_func->($self,$category,$module,$info) if(defined $row_selected_func); }, \@ll); - -# row_activated - $tree_view->signal_connect (row_activated => sub{ - - my ($tree_view, $path, $column) = @_; - my $model = $tree_view->get_model; - my $iter = $model->get_iter ($path); - my ($category) = $model->get ($iter, CATRGORY_COLUMN); - my ($module) = $model->get ($iter,MODULE_COLUMN ); - - - if($module){ - #print "$module is selected via row activaton!\n"; - $row_activated_func->($self,$category,$module,$info) if(defined $row_activated_func); - #add_module_to_soc($soc,$ip,$category,$module,$info); - - } - +# row_activated + $tree_view->signal_connect (row_activated => sub{ + my ($tree_view, $path, $column) = @_; + my $model = $tree_view->get_model; + my $iter = $model->get_iter ($path); + my ($category) = $model->get ($iter, CATRGORY_COLUMN); + my ($module) = $model->get ($iter,MODULE_COLUMN ); + if($module){ + #print "$module is selected via row activaton!\n"; + $row_activated_func->($self,$category,$module,$info) if(defined $row_activated_func); + #add_module_to_soc($soc,$ip,$category,$module,$info); + } }, \@ll); - - #$tree_view->expand_all; - - my $scrolled_window = Gtk3::ScrolledWindow->new; - $scrolled_window->set_policy ('automatic', 'automatic'); - $scrolled_window->set_shadow_type ('in'); - $scrolled_window->add($tree_view); - - my $hbox = Gtk3::HBox->new (FALSE, 0); - $hbox->pack_start ( $scrolled_window, TRUE, TRUE, 0); - - return $hbox; + #$tree_view->expand_all; + my $scrolled_window = Gtk3::ScrolledWindow->new; + $scrolled_window->set_policy ('automatic', 'automatic'); + $scrolled_window->set_shadow_type ('in'); + $scrolled_window->add($tree_view); + my $hbox = Gtk3::HBox->new (FALSE, 0); + $hbox->pack_start ( $scrolled_window, TRUE, TRUE, 0); + return $hbox; } - sub row_activated_cb{ - my ($tree_view, $path, $column) = @_; - my $model = $tree_view->get_model; - my $iter = $model->get_iter ($path); - my ($category) = $model->get ($iter, DISPLAY_COLUMN); - my ($module) = $model->get ($iter, CATRGORY_COLUMN); - + my ($tree_view, $path, $column) = @_; + my $model = $tree_view->get_model; + my $iter = $model->get_iter ($path); + my ($category) = $model->get ($iter, DISPLAY_COLUMN); + my ($module) = $model->get ($iter, CATRGORY_COLUMN); } - - sub file_edit_tree { - my $model = Gtk3::TreeStore->new('Glib::String', 'Glib::String'); - my $tree_view = Gtk3::TreeView->new; - $tree_view->set_model ($model); - my $selection = $tree_view->get_selection; - $selection->set_mode ("single"); - my $cell = Gtk3::CellRendererText->new; - $cell->set ('style' => 'italic'); - my $column = Gtk3::TreeViewColumn->new_with_attributes('Double-click to open',$cell, text => "0"); - $tree_view->append_column($column); - $tree_view->set_headers_visible(TRUE); - return ($model,$tree_view); -} - - -# my $column = Gtk3::TreeViewColumn->new_with_attributes ("select", $cell, 'text' => 0, 'style_set' => 3); - - - - - + my $model = Gtk3::TreeStore->new('Glib::String', 'Glib::String'); + my $tree_view = Gtk3::TreeView->new; + $tree_view->set_model ($model); + my $selection = $tree_view->get_selection; + $selection->set_mode ("single"); + my $cell = Gtk3::CellRendererText->new; + $cell->set ('style' => 'italic'); + my $column = Gtk3::TreeViewColumn->new_with_attributes('Double-click to open',$cell, text => "0"); + $tree_view->append_column($column); + $tree_view->set_headers_visible(TRUE); + return ($model,$tree_view); +} +# my $column = Gtk3::TreeViewColumn->new_with_attributes ("select", $cell, 'text' => 0, 'style_set' => 3); ########## # run external commands ########## - - - sub run_cmd_in_back_ground { - my $command = shift; - #print "\t$command\n"; - - ### Start running the Background Job: + my $command = shift; + #print "\t$command\n"; + ### Start running the Background Job: my $proc = Proc::Background->new($command); my $PID = $proc->pid; my $start_time = $proc->start_time; my $alive = $proc->alive; - - ### While $alive is NOT '0', then keep checking till it is... - # *When $alive is '0', it has finished executing. - while($alive ne 0) - { + ### While $alive is NOT '0', then keep checking till it is... + # *When $alive is '0', it has finished executing. + while($alive ne 0) + { $alive = $proc->alive; - # This while loop will cause Gtk3 to continue processing events, if # there are events pending... *which there are... while (Gtk3::events_pending) { - - Gtk3::main_iteration; + Gtk3::main_iteration; } Gtk3::Gdk::flush; - usleep(1000); - } - - my $end_time = $proc->end_time; - # print "*Command Completed at $end_time, with PID = $PID\n\n"; - - # Since the while loop has exited, the BG job has finished running: - # so close the pop-up window... - # $popup_window->hide; - - # Get the RETCODE from the Background Job using the 'wait' method - my $retcode = $proc->wait; - $retcode /= 256; - - #print "\t*RETCODE == $retcode\n\n"; - Gtk3::Gdk::flush; - ### Check if the RETCODE returned with an Error: - if ($retcode ne 0) { + } + my $end_time = $proc->end_time; + # print "*Command Completed at $end_time, with PID = $PID\n\n"; + # Since the while loop has exited, the BG job has finished running: + # so close the pop-up window... + # $popup_window->hide; + # Get the RETCODE from the Background Job using the 'wait' method + my $retcode = $proc->wait; + $retcode /= 256; + #print "\t*RETCODE == $retcode\n\n"; + Gtk3::Gdk::flush; + ### Check if the RETCODE returned with an Error: + if ($retcode ne 0) { print "Error: The Background Job ($command) returned with an Error...!\n"; return 1; - } else { + } else { #print "Success: The Background Job Completed Successfully...!\n"; return 0; - } - + } } sub run_cmd_in_back_ground_get_stdout { - my $cmd=shift; - my $exit; - my ($stdout, $stderr); - STDOUT->flush(); - STDERR->flush(); - - capture { $exit=run_cmd_in_back_ground($cmd) } \$stdout, \$stderr; - - return ($stdout,$exit,$stderr); - -} - -sub run_cmd_message_dialog_errors{ - my ($cmd)=@_; - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - message_dialog("$stderr\n",'error'); - return 1; - }if($exit){ - message_dialog("Error $cmd failed: $stdout\n",'error'); - return 1; - } - return 0; - + my $cmd=shift; + my $exit; + my ($stdout, $stderr); + STDOUT->flush(); + STDERR->flush(); + capture { $exit=run_cmd_in_back_ground($cmd) } \$stdout, \$stderr; + return ($stdout,$exit,$stderr); } +sub run_cmd_message_dialog_errors{ + my ($cmd)=@_; + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + message_dialog("$stderr\n",'error'); + return 1; + }if($exit){ + message_dialog("Error $cmd failed: $stdout\n",'error'); + return 1; + } + return 0; +} sub run_cmd_textview_errors{ - my ($cmd,$tview)=@_; - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); - if(length $stderr>1){ - add_colored_info($tview,"Error: $stderr\n",'red'); - add_colored_info($tview,"$cmd did not run successfully!\n",'red'); - return undef; - } - if($exit){ - add_colored_info($tview,"Error:$stdout\n",'red'); - add_colored_info($tview,"$cmd did not run successfully!\n",'red'); - return undef; - } - $stdout = "" if (!defined $stdout); - return $stdout -} - + my ($cmd,$tview)=@_; + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd); + if(length $stderr>1){ + add_colored_info($tview,"Error: $stderr\n",'red'); + add_colored_info($tview,"$cmd did not run successfully!\n",'red'); + return undef; + } + if($exit){ + add_colored_info($tview,"Error:$stdout\n",'red'); + add_colored_info($tview,"$cmd did not run successfully!\n",'red'); + return undef; + } + $stdout = "" if (!defined $stdout); + return $stdout +} sub create_iconview_model { #---------------------------------------------------- @@ -2254,90 +1835,63 @@ sub create_iconview_model { #text of the icon, and the last for the icon self---- #Gtk3::ListStore is ideal for this ------------------ #---------------------------------------------------- - my ($self,$name,$ref)=@_; - my @sources= (defined $ref)? @{$ref}:(); + my ($self,$name,$ref)=@_; + my @sources= (defined $ref)? @{$ref}:(); my $list_store = Gtk3::ListStore->new(qw/Glib::String Gtk3::Gdk::Pixbuf Glib::String/); - #****************************************************** #we populate the Gtk3::ListStore with Gtk3::Stock icons #****************************************************** - - - foreach my $val(@sources){ #get the iconset from the icon_factory #my $iconset = $icon_factory->lookup_default($val); #try and extract the icon from it add_icon_to_tree($self,$name,$list_store,$val); } - return $list_store; } #################### -# SourceView +# SourceView #################### - -sub gen_SourceView_with_buffer{ - return Gtk3::SourceView::View->new_with_buffer(@_); +sub gen_SourceView_with_buffer{ + return Gtk3::SourceView::View->new_with_buffer(@_); } - - - - sub create_SourceView_buffer { - my $self = shift; - my $tags = Gtk3::TextTagTable->new(); - - add_tag_to_SourceView($tags, search => { - background => 'yellow', - }); - add_tag_to_SourceView($tags, goto_line => { - 'paragraph-background' => 'orange', - }); - - my $buffer = Gtk3::SourceView::Buffer->new($tags); - $buffer->signal_connect('notify::cursor-position' => sub { - $self->clear_highlighted(); - }); - - return $buffer; + my $self = shift; + my $tags = Gtk3::TextTagTable->new(); + add_tag_to_SourceView($tags, search => { + background => 'yellow', + }); + add_tag_to_SourceView($tags, goto_line => { + 'paragraph-background' => 'orange', + }); + my $buffer = Gtk3::SourceView::Buffer->new($tags); + $buffer->signal_connect('notify::cursor-position' => sub { + $self->clear_highlighted(); + }); + return $buffer; } - sub add_tag_to_SourceView { - my ($tags, $name, $properties) = @_; - - my $tag = Gtk3::TextTag->new($name); - $tag->set(%{ $properties }); - $tags->add($tag); + my ($tags, $name, $properties) = @_; + my $tag = Gtk3::TextTag->new($name); + $tag->set(%{ $properties }); + $tags->add($tag); } - sub detect_language { - my $self = shift; - my ($filename) = @_; - - # Guess the programming language of the file - my $manager = Gtk3::SourceView::LanguageManager->get_default; - my $language = $manager->guess_language($filename); - $self->buffer->set_language($language); + my $self = shift; + my ($filename) = @_; + # Guess the programming language of the file + my $manager = Gtk3::SourceView::LanguageManager->get_default; + my $language = $manager->guess_language($filename); + $self->buffer->set_language($language); } - -sub get_pressed_key{ - my $event=shift; - my $key = Gtk3::Gdk::keyval_name( $event->keyval ); - return $key; +sub get_pressed_key{ + my $event=shift; + my $key = Gtk3::Gdk::keyval_name( $event->keyval ); + return $key; } - - - - - - - - - -1 +1; \ No newline at end of file diff --git a/mpsoc/rtl/src_topology/common/custom_lkh_routing.v b/mpsoc/rtl/src_topology/common/custom_lkh_routing.v index 2976de0..34ac188 100644 --- a/mpsoc/rtl/src_topology/common/custom_lkh_routing.v +++ b/mpsoc/rtl/src_topology/common/custom_lkh_routing.v @@ -1,77 +1,44 @@ `timescale 1ns / 1ps module custom_lkh_routing #( - parameter TOPOLOGY = "CUSTOM_NAME", + parameter TOPOLOGY = "CUSTOM_NAME", parameter ROUTE_NAME = "CUSTOM_NAME", - parameter ROUTE_TYPE = "DETERMINISTIC", - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 -) -( - current_r_addr, - dest_e_addr, - src_e_addr, - destport, - reset, - clk + parameter ROUTE_TYPE = "DETERMINISTIC", + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + current_r_addr, + dest_e_addr, + src_e_addr, + destport, + reset, + clk ); - input [RAw-1 :0] current_r_addr; - input [EAw-1 :0] dest_e_addr; - input [EAw-1 :0] src_e_addr; - output [DSTPw-1 :0] destport; - input reset,clk; + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output [DSTPw-1 :0] destport; + input reset,clk; - generate - - + generate - //do not modify this line ===Tcustom1Rcustom=== + //do not modify this line ===Tcustom1Rcustom=== if(TOPOLOGY == "custom1" && ROUTE_NAME== "custom" ) begin : Tcustom1Rcustom - - Tcustom1Rcustom_look_ahead_routing #( + Tcustom1Rcustom_look_ahead_routing #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) - ) - the_lkh_routing - ( + ) the_lkh_routing ( .current_r_addr(current_r_addr), .dest_e_addr(dest_e_addr), .src_e_addr(src_e_addr), .destport(destport), .reset(reset), - .clk(clk) - ); - - end - + .clk(clk) + ); + end endgenerate - - - - - - - - - - - - - - - - - - - - - - - - - endmodule diff --git a/mpsoc/rtl/src_topology/common/custom_noc_top.sv b/mpsoc/rtl/src_topology/common/custom_noc_top.sv index ecafc7d..aed0cfc 100644 --- a/mpsoc/rtl/src_topology/common/custom_noc_top.sv +++ b/mpsoc/rtl/src_topology/common/custom_noc_top.sv @@ -1,72 +1,38 @@ `include "pronoc_def.v" module custom_noc_top - #( - parameter NOC_ID=0 - )( - + #( + parameter NOC_ID=0 + )( reset, clk, chan_in_all, chan_out_all, router_event ); - `NOC_CONF - input clk,reset; - //local ports - input smartflit_chanel_t chan_in_all [NE-1 : 0]; - output smartflit_chanel_t chan_out_all [NE-1 : 0]; - - //Events - output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - - - generate - - - - - - - + input clk,reset; + //local ports + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; - - + //Events + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; + generate - - //do not modify this line ===custom1=== + //do not modify this line ===custom1=== if(TOPOLOGY == "custom1" ) begin : Tcustom1 - - custom1_noc_genvar #( - .NOC_ID(NOC_ID) - ) the_noc ( - .reset(reset), - .clk(clk), - .chan_in_all(chan_in_all), - .chan_out_all(chan_out_all), - .router_event(router_event) - ); + custom1_noc_genvar #( + .NOC_ID(NOC_ID) + ) the_noc ( + .reset(reset), + .clk(clk), + .chan_in_all(chan_in_all), + .chan_out_all(chan_out_all), + .router_event(router_event) + ); end - endgenerate - - - - - - - - - - - - - - - - - - -endmodule + +endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v index c737378..46e6a3e 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v @@ -1,323 +1,319 @@ /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/ /********************************************************************** -** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v +** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v ** -** Copyright (C) 2014-2022 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.2.0 +** This file is part of ProNoC 2.2.0 ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ module Tcustom1Rcustom_conventional_routing #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 ) ( - dest_e_addr, - src_e_addr, - destport + dest_e_addr, + src_e_addr, + destport ); + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output reg [DSTPw-1 :0] destport; - input [EAw-1 :0] dest_e_addr; - input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; - - - always@(*)begin - destport=0; - case(src_e_addr) //source address of each individual NI is fixed. So this CASE will be optimized by the synthesizer for each endpoint. - 0: begin - case(dest_e_addr) - 1,2,3,7,10: begin - destport= 1; - end - 4,5,6,8,9,11,12,13,14,15: begin - destport= 2; - end + always@(*)begin + destport=0; + case(src_e_addr) //source address of each individual NI is fixed. So this CASE will be optimized by the synthesizer for each endpoint. + 0: begin + case(dest_e_addr) + 1,2,3,7,10: begin + destport= 1; + end + 4,5,6,8,9,11,12,13,14,15: begin + destport= 2; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//0 - 1: begin - case(dest_e_addr) - 0,4,7,8,9,10,12,15: begin - destport= 1; - end - 2,3,5,6,11,13,14: begin - destport= 2; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//0 + 1: begin + case(dest_e_addr) + 0,4,7,8,9,10,12,15: begin + destport= 1; + end + 2,3,5,6,11,13,14: begin + destport= 2; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//1 - 2: begin - case(dest_e_addr) - 3,4,5,6,8,11,13,14,15: begin - destport= 1; - end - 0,1,7,9,10,12: begin - destport= 2; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//1 + 2: begin + case(dest_e_addr) + 3,4,5,6,8,11,13,14,15: begin + destport= 1; + end + 0,1,7,9,10,12: begin + destport= 2; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//2 - 3: begin - case(dest_e_addr) - 2,10,11,12: begin - destport= 1; - end - 0,1,4,5,6,7,8,9,13,14,15: begin - destport= 2; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//2 + 3: begin + case(dest_e_addr) + 2,10,11,12: begin + destport= 1; + end + 0,1,4,5,6,7,8,9,13,14,15: begin + destport= 2; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//3 - 4: begin - case(dest_e_addr) - 1,6,7,8,10,13: begin - destport= 1; - end - 3: begin - destport= 2; - end - 0,2,5,9,11,12,14,15: begin - destport= 3; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//3 + 4: begin + case(dest_e_addr) + 1,6,7,8,10,13: begin + destport= 1; + end + 3: begin + destport= 2; + end + 0,2,5,9,11,12,14,15: begin + destport= 3; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//4 - 5: begin - case(dest_e_addr) - 1,7,8,10,11,12,15: begin - destport= 1; - end - 2,3,4,6,13,14: begin - destport= 2; - end - 0,9: begin - destport= 3; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//4 + 5: begin + case(dest_e_addr) + 1,7,8,10,11,12,15: begin + destport= 1; + end + 2,3,4,6,13,14: begin + destport= 2; + end + 0,9: begin + destport= 3; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//5 - 6: begin - case(dest_e_addr) - 3,4,13: begin - destport= 1; - end - 0,1,2,5,7,8,9,10,11,12,14,15: begin - destport= 2; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//5 + 6: begin + case(dest_e_addr) + 3,4,13: begin + destport= 1; + end + 0,1,2,5,7,8,9,10,11,12,14,15: begin + destport= 2; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//6 - 7: begin - case(dest_e_addr) - 2,3,4,5,6,8,9,11,12,13,14,15: begin - destport= 1; - end - 0,10: begin - destport= 2; - end - 1: begin - destport= 3; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//6 + 7: begin + case(dest_e_addr) + 2,3,4,5,6,8,9,11,12,13,14,15: begin + destport= 1; + end + 0,10: begin + destport= 2; + end + 1: begin + destport= 3; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//7 - 8: begin - case(dest_e_addr) - 0,4,5,9,10,12: begin - destport= 1; - end - 2,3,6,11,13,14,15: begin - destport= 2; - end - 1,7: begin - destport= 3; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//7 + 8: begin + case(dest_e_addr) + 0,4,5,9,10,12: begin + destport= 1; + end + 2,3,6,11,13,14,15: begin + destport= 2; + end + 1,7: begin + destport= 3; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//8 - 9: begin - case(dest_e_addr) - 1,7,8,10,12: begin - destport= 1; - end - 2,3,4,5,6,11,13,14,15: begin - destport= 2; - end - 0: begin - destport= 3; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//8 + 9: begin + case(dest_e_addr) + 1,7,8,10,12: begin + destport= 1; + end + 2,3,4,5,6,11,13,14,15: begin + destport= 2; + end + 0: begin + destport= 3; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//9 - 10: begin - case(dest_e_addr) - 2,3,4,5,6,8,9,11,12,13,14,15: begin - destport= 1; - end - 1,7: begin - destport= 2; - end - 0: begin - destport= 3; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//9 + 10: begin + case(dest_e_addr) + 2,3,4,5,6,8,9,11,12,13,14,15: begin + destport= 1; + end + 1,7: begin + destport= 2; + end + 0: begin + destport= 3; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//10 - 11: begin - case(dest_e_addr) - 0,1,4,5,6,7,8,9,10,12,13,14,15: begin - destport= 1; - end - 2: begin - destport= 2; - end - 3: begin - destport= 3; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//10 + 11: begin + case(dest_e_addr) + 0,1,4,5,6,7,8,9,10,12,13,14,15: begin + destport= 1; + end + 2: begin + destport= 2; + end + 3: begin + destport= 3; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//11 - 12: begin - case(dest_e_addr) - 2,3,4,5,6,11,13,14,15: begin - destport= 1; - end - 0,9: begin - destport= 2; - end - 1,7,10: begin - destport= 3; - end - 8: begin - destport= 4; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//11 + 12: begin + case(dest_e_addr) + 2,3,4,5,6,11,13,14,15: begin + destport= 1; + end + 0,9: begin + destport= 2; + end + 1,7,10: begin + destport= 3; + end + 8: begin + destport= 4; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//12 - 13: begin - case(dest_e_addr) - 3,4: begin - destport= 2; - end - 6: begin - destport= 3; - end - 0,1,2,5,7,8,9,10,11,12,14,15: begin - destport= 4; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//12 + 13: begin + case(dest_e_addr) + 3,4: begin + destport= 2; + end + 6: begin + destport= 3; + end + 0,1,2,5,7,8,9,10,11,12,14,15: begin + destport= 4; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//13 - 14: begin - case(dest_e_addr) - 5,9,12,15: begin - destport= 1; - end - 3,4,6,13: begin - destport= 2; - end - 0,1,7,8,10: begin - destport= 3; - end - 2,11: begin - destport= 4; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//13 + 14: begin + case(dest_e_addr) + 5,9,12,15: begin + destport= 1; + end + 3,4,6,13: begin + destport= 2; + end + 0,1,7,8,10: begin + destport= 3; + end + 2,11: begin + destport= 4; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//14 - 15: begin - case(dest_e_addr) - 1,7,8,10,12: begin - destport= 1; - end - 2,11,14: begin - destport= 2; - end - 3,4,6,13: begin - destport= 3; - end - 0,5,9: begin - destport= 4; - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//14 + 15: begin + case(dest_e_addr) + 1,7,8,10,12: begin + destport= 1; + end + 2,11,14: begin + destport= 2; + end + 3,4,6,13: begin + destport= 3; + end + 0,5,9: begin + destport= 4; + end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//15 + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//15 - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end - endmodule - diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v index b9721d7..1ad3a54 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v @@ -1,380 +1,358 @@ /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/ /********************************************************************** -** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v +** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v ** -** Copyright (C) 2014-2022 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.2.0 +** This file is part of ProNoC 2.2.0 ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ module Tcustom1Rcustom_conventional_routing_genvar #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4, - parameter SRC_E_ADDR=0 -) -( - dest_e_addr, - destport + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter SRC_E_ADDR=0 +) ( + dest_e_addr, + destport ); + input [EAw-1 :0] dest_e_addr; + output reg [DSTPw-1 :0] destport; - input [EAw-1 :0] dest_e_addr; - output reg [DSTPw-1 :0] destport; - - - generate - - if(SRC_E_ADDR == 0) begin : SRC0 - always@(*)begin - destport= 0; - case(dest_e_addr) - 1,2,3,7,10: begin - destport= 1; - end - 4,5,6,8,9,11,12,13,14,15: begin - destport= 2; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC0 - - if(SRC_E_ADDR == 1) begin : SRC1 - always@(*)begin - destport= 0; - case(dest_e_addr) - 0,4,7,8,9,10,12,15: begin - destport= 1; - end - 2,3,5,6,11,13,14: begin - destport= 2; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC1 - - if(SRC_E_ADDR == 2) begin : SRC2 - always@(*)begin - destport= 0; - case(dest_e_addr) - 3,4,5,6,8,11,13,14,15: begin - destport= 1; - end - 0,1,7,9,10,12: begin - destport= 2; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC2 - - if(SRC_E_ADDR == 3) begin : SRC3 - always@(*)begin - destport= 0; - case(dest_e_addr) - 2,10,11,12: begin - destport= 1; - end - 0,1,4,5,6,7,8,9,13,14,15: begin - destport= 2; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC3 - - if(SRC_E_ADDR == 4) begin : SRC4 - always@(*)begin - destport= 0; - case(dest_e_addr) - 1,6,7,8,10,13: begin - destport= 1; - end - 3: begin - destport= 2; - end - 0,2,5,9,11,12,14,15: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC4 - - if(SRC_E_ADDR == 5) begin : SRC5 - always@(*)begin - destport= 0; - case(dest_e_addr) - 1,7,8,10,11,12,15: begin - destport= 1; - end - 2,3,4,6,13,14: begin - destport= 2; - end - 0,9: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC5 - - if(SRC_E_ADDR == 6) begin : SRC6 - always@(*)begin - destport= 0; - case(dest_e_addr) - 3,4,13: begin - destport= 1; - end - 0,1,2,5,7,8,9,10,11,12,14,15: begin - destport= 2; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC6 - - if(SRC_E_ADDR == 7) begin : SRC7 - always@(*)begin - destport= 0; - case(dest_e_addr) - 2,3,4,5,6,8,9,11,12,13,14,15: begin - destport= 1; - end - 0,10: begin - destport= 2; - end - 1: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC7 - - if(SRC_E_ADDR == 8) begin : SRC8 - always@(*)begin - destport= 0; - case(dest_e_addr) - 0,4,5,9,10,12: begin - destport= 1; - end - 2,3,6,11,13,14,15: begin - destport= 2; - end - 1,7: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end + generate + if(SRC_E_ADDR == 0) begin : SRC0 + always@(*)begin + destport= 0; + case(dest_e_addr) + 1,2,3,7,10: begin + destport= 1; + end + 4,5,6,8,9,11,12,13,14,15: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC0 + + if(SRC_E_ADDR == 1) begin : SRC1 + always@(*)begin + destport= 0; + case(dest_e_addr) + 0,4,7,8,9,10,12,15: begin + destport= 1; + end + 2,3,5,6,11,13,14: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC1 + + if(SRC_E_ADDR == 2) begin : SRC2 + always@(*)begin + destport= 0; + case(dest_e_addr) + 3,4,5,6,8,11,13,14,15: begin + destport= 1; + end + 0,1,7,9,10,12: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC2 + + if(SRC_E_ADDR == 3) begin : SRC3 + always@(*)begin + destport= 0; + case(dest_e_addr) + 2,10,11,12: begin + destport= 1; + end + 0,1,4,5,6,7,8,9,13,14,15: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC3 + + if(SRC_E_ADDR == 4) begin : SRC4 + always@(*)begin + destport= 0; + case(dest_e_addr) + 1,6,7,8,10,13: begin + destport= 1; + end + 3: begin + destport= 2; + end + 0,2,5,9,11,12,14,15: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC4 + + if(SRC_E_ADDR == 5) begin : SRC5 + always@(*)begin + destport= 0; + case(dest_e_addr) + 1,7,8,10,11,12,15: begin + destport= 1; + end + 2,3,4,6,13,14: begin + destport= 2; + end + 0,9: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC5 + + if(SRC_E_ADDR == 6) begin : SRC6 + always@(*)begin + destport= 0; + case(dest_e_addr) + 3,4,13: begin + destport= 1; + end + 0,1,2,5,7,8,9,10,11,12,14,15: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC6 + + if(SRC_E_ADDR == 7) begin : SRC7 + always@(*)begin + destport= 0; + case(dest_e_addr) + 2,3,4,5,6,8,9,11,12,13,14,15: begin + destport= 1; + end + 0,10: begin + destport= 2; + end + 1: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC7 + + if(SRC_E_ADDR == 8) begin : SRC8 + always@(*)begin + destport= 0; + case(dest_e_addr) + 0,4,5,9,10,12: begin + destport= 1; + end + 2,3,6,11,13,14,15: begin + destport= 2; + end + 1,7: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC8 + + if(SRC_E_ADDR == 9) begin : SRC9 + always@(*)begin + destport= 0; + case(dest_e_addr) + 1,7,8,10,12: begin + destport= 1; + end + 2,3,4,5,6,11,13,14,15: begin + destport= 2; + end + 0: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC9 + + if(SRC_E_ADDR == 10) begin : SRC10 + always@(*)begin + destport= 0; + case(dest_e_addr) + 2,3,4,5,6,8,9,11,12,13,14,15: begin + destport= 1; + end + 1,7: begin + destport= 2; + end + 0: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC10 + + if(SRC_E_ADDR == 11) begin : SRC11 + always@(*)begin + destport= 0; + case(dest_e_addr) + 0,1,4,5,6,7,8,9,10,12,13,14,15: begin + destport= 1; + end + 2: begin + destport= 2; + end + 3: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC11 + + if(SRC_E_ADDR == 12) begin : SRC12 + always@(*)begin + destport= 0; + case(dest_e_addr) + 2,3,4,5,6,11,13,14,15: begin + destport= 1; + end + 0,9: begin + destport= 2; + end + 1,7,10: begin + destport= 3; + end + 8: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC12 + + if(SRC_E_ADDR == 13) begin : SRC13 + always@(*)begin + destport= 0; + case(dest_e_addr) + 3,4: begin + destport= 2; + end + 6: begin + destport= 3; + end + 0,1,2,5,7,8,9,10,11,12,14,15: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC13 + + if(SRC_E_ADDR == 14) begin : SRC14 + always@(*)begin + destport= 0; + case(dest_e_addr) + 5,9,12,15: begin + destport= 1; + end + 3,4,6,13: begin + destport= 2; + end + 0,1,7,8,10: begin + destport= 3; + end + 2,11: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC14 + + if(SRC_E_ADDR == 15) begin : SRC15 + always@(*)begin + destport= 0; + case(dest_e_addr) + 1,7,8,10,12: begin + destport= 1; + end + 2,11,14: begin + destport= 2; + end + 3,4,6,13: begin + destport= 3; + end + 0,5,9: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + end//SRC15 + + endgenerate - endcase - end - end//SRC8 - - if(SRC_E_ADDR == 9) begin : SRC9 - always@(*)begin - destport= 0; - case(dest_e_addr) - 1,7,8,10,12: begin - destport= 1; - end - 2,3,4,5,6,11,13,14,15: begin - destport= 2; - end - 0: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC9 - - if(SRC_E_ADDR == 10) begin : SRC10 - always@(*)begin - destport= 0; - case(dest_e_addr) - 2,3,4,5,6,8,9,11,12,13,14,15: begin - destport= 1; - end - 1,7: begin - destport= 2; - end - 0: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC10 - - if(SRC_E_ADDR == 11) begin : SRC11 - always@(*)begin - destport= 0; - case(dest_e_addr) - 0,1,4,5,6,7,8,9,10,12,13,14,15: begin - destport= 1; - end - 2: begin - destport= 2; - end - 3: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC11 - - if(SRC_E_ADDR == 12) begin : SRC12 - always@(*)begin - destport= 0; - case(dest_e_addr) - 2,3,4,5,6,11,13,14,15: begin - destport= 1; - end - 0,9: begin - destport= 2; - end - 1,7,10: begin - destport= 3; - end - 8: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC12 - - if(SRC_E_ADDR == 13) begin : SRC13 - always@(*)begin - destport= 0; - case(dest_e_addr) - 3,4: begin - destport= 2; - end - 6: begin - destport= 3; - end - 0,1,2,5,7,8,9,10,11,12,14,15: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC13 - - if(SRC_E_ADDR == 14) begin : SRC14 - always@(*)begin - destport= 0; - case(dest_e_addr) - 5,9,12,15: begin - destport= 1; - end - 3,4,6,13: begin - destport= 2; - end - 0,1,7,8,10: begin - destport= 3; - end - 2,11: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC14 - - if(SRC_E_ADDR == 15) begin : SRC15 - always@(*)begin - destport= 0; - case(dest_e_addr) - 1,7,8,10,12: begin - destport= 1; - end - 2,11,14: begin - destport= 2; - end - 3,4,6,13: begin - destport= 3; - end - 0,5,9: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - - endcase - end - end//SRC15 - - endgenerate - - - -endmodule +endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v index 6010234..c933352 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v @@ -1,452 +1,438 @@ /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/ /********************************************************************** -** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v +** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v ** -** Copyright (C) 2014-2022 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.2.0 +** This file is part of ProNoC 2.2.0 ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ - - `include "pronoc_def.v" + +`include "pronoc_def.v" /******************* * Tcustom1Rcustom_look_ahead_routing *******************/ module Tcustom1Rcustom_look_ahead_routing #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 -) -( - reset, - clk, - current_r_addr, - dest_e_addr, - src_e_addr, - destport + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + reset, + clk, + current_r_addr, + dest_e_addr, + src_e_addr, + destport ); - - input [RAw-1 :0] current_r_addr; - input [EAw-1 :0] dest_e_addr; - input [EAw-1 :0] src_e_addr; - output [DSTPw-1 :0] destport; - input reset,clk; - + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output [DSTPw-1 :0] destport; + input reset,clk; reg [EAw-1 :0] dest_e_addr_delay; reg [EAw-1 :0] src_e_addr_delay; - + always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset)begin dest_e_addr_delay<={EAw{1'b0}}; - src_e_addr_delay<={EAw{1'b0}}; + src_e_addr_delay<={EAw{1'b0}}; end else begin dest_e_addr_delay<=dest_e_addr; - src_e_addr_delay<=src_e_addr; + src_e_addr_delay<=src_e_addr; end end - + Tcustom1Rcustom_look_ahead_routing_comb #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) - ) - lkp_cmb - ( + ) lkp_cmb ( .current_r_addr(current_r_addr), .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), .destport(destport) ); - - - endmodule - + /******************* * Tcustom1Rcustom_look_ahead_routing_comb *******************/ - - module Tcustom1Rcustom_look_ahead_routing_comb #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 -) -( - current_r_addr, - dest_e_addr, - src_e_addr, - destport +module Tcustom1Rcustom_look_ahead_routing_comb #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + current_r_addr, + dest_e_addr, + src_e_addr, + destport ); - - input [RAw-1 :0] current_r_addr; - input [EAw-1 :0] dest_e_addr; - input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output reg [DSTPw-1 :0] destport; -localparam [EAw-1 : 0] E0=0; -localparam [EAw-1 : 0] E1=1; -localparam [EAw-1 : 0] E2=2; -localparam [EAw-1 : 0] E3=3; -localparam [EAw-1 : 0] E4=4; -localparam [EAw-1 : 0] E5=5; -localparam [EAw-1 : 0] E6=6; -localparam [EAw-1 : 0] E7=7; -localparam [EAw-1 : 0] E8=8; -localparam [EAw-1 : 0] E9=9; -localparam [EAw-1 : 0] E10=10; -localparam [EAw-1 : 0] E11=11; -localparam [EAw-1 : 0] E12=12; -localparam [EAw-1 : 0] E13=13; -localparam [EAw-1 : 0] E14=14; -localparam [EAw-1 : 0] E15=15; +localparam [EAw-1 : 0] E0=0; +localparam [EAw-1 : 0] E1=1; +localparam [EAw-1 : 0] E2=2; +localparam [EAw-1 : 0] E3=3; +localparam [EAw-1 : 0] E4=4; +localparam [EAw-1 : 0] E5=5; +localparam [EAw-1 : 0] E6=6; +localparam [EAw-1 : 0] E7=7; +localparam [EAw-1 : 0] E8=8; +localparam [EAw-1 : 0] E9=9; +localparam [EAw-1 : 0] E10=10; +localparam [EAw-1 : 0] E11=11; +localparam [EAw-1 : 0] E12=12; +localparam [EAw-1 : 0] E13=13; +localparam [EAw-1 : 0] E14=14; +localparam [EAw-1 : 0] E15=15; - - always@(*)begin - destport=0; - case(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. - 0: begin - case({src_e_addr,dest_e_addr}) - {E0,E9},{E0,E10}: begin - destport= 0; - end - {E0,E2},{E0,E3},{E0,E8},{E0,E11},{E0,E12}: begin - destport= 1; - end - {E0,E1},{E0,E4},{E0,E5},{E0,E6},{E0,E7},{E0,E13},{E0,E14},{E0,E15}: begin - destport= 2; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//0 - 1: begin - case({src_e_addr,dest_e_addr}) - {E1,E2},{E1,E7},{E2,E7}: begin - destport= 0; - end - {E1,E3},{E1,E4},{E1,E5},{E1,E6},{E1,E8},{E1,E9},{E1,E11},{E1,E12},{E1,E13},{E1,E14},{E1,E15},{E2,E9},{E2,E12}: begin - destport= 1; - end - {E1,E0},{E1,E10},{E2,E0},{E2,E10}: begin - destport= 2; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//1 - 2: begin - case({src_e_addr,dest_e_addr}) - {E1,E11},{E2,E1},{E2,E11}: begin - destport= 0; - end - {E1,E5},{E1,E6},{E1,E13},{E1,E14},{E2,E0},{E2,E4},{E2,E5},{E2,E6},{E2,E7},{E2,E8},{E2,E9},{E2,E10},{E2,E12},{E2,E13},{E2,E14},{E2,E15}: begin - destport= 1; - end - {E1,E3},{E2,E3}: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//2 - 3: begin - case({src_e_addr,dest_e_addr}) - {E3,E4},{E3,E11}: begin - destport= 0; - end - {E3,E1},{E3,E6},{E3,E7},{E3,E8},{E3,E10},{E3,E12},{E3,E13},{E3,E14}: begin - destport= 1; - end - {E3,E2}: begin - destport= 2; - end - {E3,E0},{E3,E5},{E3,E9},{E3,E15}: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//3 - 4: begin - case({src_e_addr,dest_e_addr}) - {E3,E13},{E4,E3},{E4,E13},{E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin - destport= 0; - end - {E4,E2},{E4,E11},{E4,E14}: begin - destport= 1; - end - {E3,E0},{E3,E5},{E3,E9},{E3,E15},{E4,E0},{E4,E5},{E4,E9},{E4,E12},{E4,E15}: begin - destport= 2; - end - {E3,E6},{E4,E6}: begin - destport= 3; - end - {E3,E1},{E3,E7},{E3,E8},{E3,E14},{E4,E1},{E4,E7},{E4,E8},{E4,E10}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//4 - 5: begin - case({src_e_addr,dest_e_addr}) - {E0,E6},{E0,E15},{E3,E9},{E3,E15},{E4,E9},{E4,E15},{E5,E6},{E5,E9},{E5,E15},{E6,E9},{E6,E15},{E9,E6},{E9,E15},{E13,E9},{E14,E9},{E15,E9}: begin - destport= 0; - end - {E0,E4},{E0,E13},{E4,E12},{E5,E1},{E5,E2},{E5,E3},{E5,E4},{E5,E7},{E5,E8},{E5,E10},{E5,E12},{E5,E13},{E5,E14},{E6,E1},{E6,E7},{E6,E8},{E6,E10},{E6,E12},{E9,E3},{E9,E4},{E9,E13},{E9,E14}: begin - destport= 1; - end - {E0,E14},{E5,E11},{E6,E2},{E6,E11},{E6,E14},{E9,E2},{E9,E11}: begin - destport= 2; - end - {E3,E0},{E4,E0},{E5,E0},{E6,E0},{E11,E0},{E13,E0},{E15,E0}: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//5 - 6: begin - case({src_e_addr,dest_e_addr}) - {E0,E13},{E3,E5},{E4,E5},{E5,E13},{E6,E5},{E6,E13},{E9,E13}: begin - destport= 0; - end - {E3,E15},{E4,E12},{E4,E15},{E6,E1},{E6,E2},{E6,E7},{E6,E8},{E6,E10},{E6,E11},{E6,E12},{E6,E14},{E6,E15}: begin - destport= 1; - end - {E0,E4},{E5,E3},{E5,E4},{E6,E3},{E6,E4},{E9,E3},{E9,E4}: begin - destport= 2; - end - {E3,E0},{E3,E9},{E4,E0},{E4,E9},{E6,E0},{E6,E9}: begin - destport= 3; - end - {E4,E2},{E4,E11},{E4,E14},{E5,E2},{E5,E14},{E9,E14}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//6 - 7: begin - case({src_e_addr,dest_e_addr}) - {E0,E1},{E1,E8},{E1,E10},{E2,E10},{E3,E1},{E3,E10},{E4,E1},{E4,E10},{E5,E1},{E6,E1},{E7,E1},{E7,E8},{E7,E10},{E8,E1},{E9,E1},{E10,E1},{E11,E1},{E11,E10},{E12,E1},{E13,E1},{E13,E10},{E14,E1},{E14,E10},{E15,E1}: begin - destport= 0; - end - {E1,E9},{E1,E12},{E1,E15},{E2,E9},{E2,E12},{E7,E9},{E7,E12}: begin - destport= 1; - end - {E1,E4},{E7,E2},{E7,E3},{E7,E4},{E7,E5},{E7,E6},{E7,E11},{E7,E13},{E7,E14},{E7,E15}: begin - destport= 2; - end - {E1,E0},{E2,E0},{E7,E0},{E14,E0}: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//7 - 8: begin - case({src_e_addr,dest_e_addr}) - {E1,E12},{E2,E12},{E3,E7},{E4,E7},{E7,E12},{E7,E14},{E8,E7},{E8,E12},{E8,E14},{E9,E7},{E11,E7},{E13,E7},{E14,E7}: begin - destport= 0; - end - {E1,E15},{E7,E5},{E7,E15},{E8,E4},{E8,E5},{E8,E15}: begin - destport= 1; - end - {E1,E4},{E1,E9},{E2,E9},{E3,E10},{E4,E10},{E7,E3},{E7,E4},{E7,E6},{E7,E9},{E7,E13},{E8,E0},{E8,E3},{E8,E6},{E8,E9},{E8,E13},{E11,E10},{E13,E10},{E14,E0},{E14,E10}: begin - destport= 2; - end - {E3,E1},{E4,E1},{E8,E1},{E8,E10},{E9,E1},{E11,E1},{E13,E1},{E14,E1}: begin - destport= 3; - end - {E7,E2},{E7,E11},{E8,E2},{E8,E11}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//8 - 9: begin - case({src_e_addr,dest_e_addr}) - {E0,E5},{E0,E12},{E3,E0},{E4,E0},{E5,E0},{E6,E0},{E8,E0},{E9,E0},{E9,E5},{E9,E12},{E11,E0},{E12,E0},{E13,E0},{E15,E0}: begin - destport= 0; - end - {E0,E11},{E0,E14},{E0,E15},{E9,E2},{E9,E11},{E9,E15}: begin - destport= 1; - end - {E0,E4},{E0,E6},{E0,E13},{E9,E3},{E9,E4},{E9,E6},{E9,E13},{E9,E14}: begin - destport= 2; - end - {E9,E10}: begin - destport= 3; - end - {E0,E8},{E9,E1},{E9,E7},{E9,E8}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//9 - 10: begin - case({src_e_addr,dest_e_addr}) - {E0,E7},{E1,E0},{E2,E0},{E5,E7},{E6,E7},{E7,E0},{E10,E0},{E10,E7},{E10,E12},{E12,E7},{E14,E0},{E15,E7}: begin - destport= 0; - end - {E0,E2},{E0,E3},{E10,E2},{E10,E3},{E10,E4},{E10,E5},{E10,E6},{E10,E11},{E10,E13},{E10,E14},{E10,E15}: begin - destport= 1; - end - {E10,E9}: begin - destport= 2; - end - {E0,E1},{E5,E1},{E6,E1},{E10,E1},{E12,E1},{E15,E1}: begin - destport= 3; - end - {E10,E8}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//10 - 11: begin - case({src_e_addr,dest_e_addr}) - {E0,E2},{E0,E3},{E1,E3},{E1,E14},{E2,E3},{E2,E14},{E3,E2},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E8,E2},{E9,E2},{E10,E2},{E11,E2},{E11,E3},{E11,E14},{E12,E2},{E13,E2},{E14,E2},{E15,E2}: begin - destport= 0; - end - {E1,E5},{E1,E13},{E2,E5},{E2,E15},{E3,E12},{E11,E0},{E11,E5},{E11,E9},{E11,E12},{E11,E15}: begin - destport= 1; - end - {E1,E6},{E2,E4},{E2,E6},{E2,E13},{E11,E4},{E11,E6},{E11,E13}: begin - destport= 2; - end - {E2,E8},{E3,E10},{E11,E1},{E11,E7},{E11,E8},{E11,E10}: begin - destport= 3; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//11 - 12: begin - case({src_e_addr,dest_e_addr}) - {E0,E8},{E1,E9},{E1,E15},{E2,E9},{E5,E8},{E5,E10},{E6,E8},{E6,E10},{E7,E9},{E8,E9},{E8,E10},{E9,E8},{E9,E10},{E10,E8},{E10,E9},{E10,E15},{E11,E9},{E12,E8},{E12,E9},{E12,E10},{E12,E15},{E15,E8},{E15,E10}: begin - destport= 0; - end - {E0,E2},{E0,E3},{E0,E11},{E5,E1},{E5,E7},{E6,E1},{E6,E7},{E10,E2},{E10,E11},{E10,E14},{E12,E1},{E12,E2},{E12,E7},{E12,E11},{E12,E14},{E15,E1},{E15,E7}: begin - destport= 2; - end - {E8,E0},{E8,E4},{E9,E1},{E9,E7},{E10,E3},{E10,E4},{E10,E6},{E10,E13},{E12,E0},{E12,E3},{E12,E4},{E12,E6},{E12,E13}: begin - destport= 3; - end - {E8,E5},{E10,E5},{E12,E5}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//12 - 13: begin - case({src_e_addr,dest_e_addr}) - {E0,E4},{E1,E4},{E1,E6},{E2,E4},{E2,E6},{E3,E6},{E3,E14},{E4,E6},{E4,E14},{E5,E4},{E5,E14},{E6,E4},{E7,E4},{E7,E6},{E8,E4},{E8,E6},{E9,E4},{E9,E14},{E10,E4},{E10,E6},{E11,E4},{E11,E6},{E12,E4},{E12,E6},{E13,E4},{E13,E6},{E13,E14},{E14,E4},{E14,E6},{E15,E4},{E15,E6}: begin - destport= 0; - end - {E13,E0},{E13,E5},{E13,E9},{E13,E12},{E13,E15}: begin - destport= 1; - end - {E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin - destport= 2; - end - {E3,E1},{E3,E7},{E3,E8},{E4,E1},{E4,E7},{E4,E8},{E4,E10},{E13,E1},{E13,E7},{E13,E8},{E13,E10}: begin - destport= 3; - end - {E4,E2},{E4,E11},{E5,E2},{E13,E2},{E13,E11}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//13 - 14: begin - case({src_e_addr,dest_e_addr}) - {E0,E11},{E2,E8},{E2,E13},{E2,E15},{E3,E8},{E4,E8},{E4,E11},{E5,E11},{E6,E11},{E7,E11},{E7,E13},{E7,E15},{E8,E11},{E8,E13},{E8,E15},{E9,E11},{E10,E11},{E11,E8},{E11,E13},{E11,E15},{E12,E11},{E13,E8},{E13,E11},{E13,E15},{E14,E8},{E14,E11},{E14,E13},{E14,E15},{E15,E11}: begin - destport= 0; - end - {E3,E12},{E11,E9},{E11,E12},{E13,E12},{E14,E12}: begin - destport= 1; - end - {E0,E2},{E1,E4},{E2,E4},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E7,E3},{E7,E4},{E8,E2},{E8,E3},{E9,E2},{E10,E2},{E11,E4},{E12,E2},{E13,E2},{E14,E2},{E14,E3},{E14,E4},{E15,E2}: begin - destport= 2; - end - {E0,E3},{E1,E6},{E1,E13},{E2,E6},{E3,E1},{E3,E7},{E3,E10},{E4,E1},{E4,E7},{E4,E10},{E7,E6},{E8,E6},{E11,E1},{E11,E6},{E11,E7},{E11,E10},{E13,E1},{E13,E7},{E13,E10},{E14,E0},{E14,E1},{E14,E6},{E14,E7},{E14,E10}: begin - destport= 3; - end - {E1,E5},{E2,E5},{E7,E5},{E11,E0},{E11,E5},{E13,E0},{E13,E5},{E13,E9},{E14,E5},{E14,E9}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//14 - 15: begin - case({src_e_addr,dest_e_addr}) - {E0,E14},{E1,E5},{E1,E13},{E2,E5},{E3,E12},{E4,E12},{E5,E12},{E6,E12},{E6,E14},{E7,E5},{E8,E5},{E10,E5},{E10,E13},{E10,E14},{E11,E5},{E11,E12},{E12,E5},{E12,E13},{E12,E14},{E13,E5},{E13,E12},{E14,E5},{E14,E12},{E15,E5},{E15,E12},{E15,E13},{E15,E14}: begin - destport= 0; - end - {E8,E4},{E10,E3},{E10,E4},{E11,E9},{E12,E3},{E12,E4},{E15,E3},{E15,E4}: begin - destport= 2; - end - {E5,E1},{E5,E7},{E5,E10},{E6,E1},{E6,E7},{E6,E10},{E10,E6},{E11,E0},{E12,E6},{E13,E0},{E13,E9},{E14,E9},{E15,E0},{E15,E1},{E15,E6},{E15,E7},{E15,E9},{E15,E10}: begin - destport= 3; - end - {E0,E2},{E0,E3},{E0,E11},{E5,E8},{E5,E11},{E6,E2},{E6,E8},{E6,E11},{E9,E2},{E9,E11},{E10,E2},{E10,E11},{E12,E2},{E12,E11},{E15,E2},{E15,E8},{E15,E11}: begin - destport= 4; - end - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end//15 - default: begin - destport= {DSTPw{1'bX}}; - end - endcase - end - - - -endmodule + always@(*)begin + destport=0; + case(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. + 0: begin + case({src_e_addr,dest_e_addr}) + {E0,E9},{E0,E10}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E0,E8},{E0,E11},{E0,E12}: begin + destport= 1; + end + {E0,E1},{E0,E4},{E0,E5},{E0,E6},{E0,E7},{E0,E13},{E0,E14},{E0,E15}: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//0 + 1: begin + case({src_e_addr,dest_e_addr}) + {E1,E2},{E1,E7},{E2,E7}: begin + destport= 0; + end + {E1,E3},{E1,E4},{E1,E5},{E1,E6},{E1,E8},{E1,E9},{E1,E11},{E1,E12},{E1,E13},{E1,E14},{E1,E15},{E2,E9},{E2,E12}: begin + destport= 1; + end + {E1,E0},{E1,E10},{E2,E0},{E2,E10}: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//1 + 2: begin + case({src_e_addr,dest_e_addr}) + {E1,E11},{E2,E1},{E2,E11}: begin + destport= 0; + end + {E1,E5},{E1,E6},{E1,E13},{E1,E14},{E2,E0},{E2,E4},{E2,E5},{E2,E6},{E2,E7},{E2,E8},{E2,E9},{E2,E10},{E2,E12},{E2,E13},{E2,E14},{E2,E15}: begin + destport= 1; + end + {E1,E3},{E2,E3}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//2 + 3: begin + case({src_e_addr,dest_e_addr}) + {E3,E4},{E3,E11}: begin + destport= 0; + end + {E3,E1},{E3,E6},{E3,E7},{E3,E8},{E3,E10},{E3,E12},{E3,E13},{E3,E14}: begin + destport= 1; + end + {E3,E2}: begin + destport= 2; + end + {E3,E0},{E3,E5},{E3,E9},{E3,E15}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//3 + 4: begin + case({src_e_addr,dest_e_addr}) + {E3,E13},{E4,E3},{E4,E13},{E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin + destport= 0; + end + {E4,E2},{E4,E11},{E4,E14}: begin + destport= 1; + end + {E3,E0},{E3,E5},{E3,E9},{E3,E15},{E4,E0},{E4,E5},{E4,E9},{E4,E12},{E4,E15}: begin + destport= 2; + end + {E3,E6},{E4,E6}: begin + destport= 3; + end + {E3,E1},{E3,E7},{E3,E8},{E3,E14},{E4,E1},{E4,E7},{E4,E8},{E4,E10}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//4 + 5: begin + case({src_e_addr,dest_e_addr}) + {E0,E6},{E0,E15},{E3,E9},{E3,E15},{E4,E9},{E4,E15},{E5,E6},{E5,E9},{E5,E15},{E6,E9},{E6,E15},{E9,E6},{E9,E15},{E13,E9},{E14,E9},{E15,E9}: begin + destport= 0; + end + {E0,E4},{E0,E13},{E4,E12},{E5,E1},{E5,E2},{E5,E3},{E5,E4},{E5,E7},{E5,E8},{E5,E10},{E5,E12},{E5,E13},{E5,E14},{E6,E1},{E6,E7},{E6,E8},{E6,E10},{E6,E12},{E9,E3},{E9,E4},{E9,E13},{E9,E14}: begin + destport= 1; + end + {E0,E14},{E5,E11},{E6,E2},{E6,E11},{E6,E14},{E9,E2},{E9,E11}: begin + destport= 2; + end + {E3,E0},{E4,E0},{E5,E0},{E6,E0},{E11,E0},{E13,E0},{E15,E0}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//5 + 6: begin + case({src_e_addr,dest_e_addr}) + {E0,E13},{E3,E5},{E4,E5},{E5,E13},{E6,E5},{E6,E13},{E9,E13}: begin + destport= 0; + end + {E3,E15},{E4,E12},{E4,E15},{E6,E1},{E6,E2},{E6,E7},{E6,E8},{E6,E10},{E6,E11},{E6,E12},{E6,E14},{E6,E15}: begin + destport= 1; + end + {E0,E4},{E5,E3},{E5,E4},{E6,E3},{E6,E4},{E9,E3},{E9,E4}: begin + destport= 2; + end + {E3,E0},{E3,E9},{E4,E0},{E4,E9},{E6,E0},{E6,E9}: begin + destport= 3; + end + {E4,E2},{E4,E11},{E4,E14},{E5,E2},{E5,E14},{E9,E14}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//6 + 7: begin + case({src_e_addr,dest_e_addr}) + {E0,E1},{E1,E8},{E1,E10},{E2,E10},{E3,E1},{E3,E10},{E4,E1},{E4,E10},{E5,E1},{E6,E1},{E7,E1},{E7,E8},{E7,E10},{E8,E1},{E9,E1},{E10,E1},{E11,E1},{E11,E10},{E12,E1},{E13,E1},{E13,E10},{E14,E1},{E14,E10},{E15,E1}: begin + destport= 0; + end + {E1,E9},{E1,E12},{E1,E15},{E2,E9},{E2,E12},{E7,E9},{E7,E12}: begin + destport= 1; + end + {E1,E4},{E7,E2},{E7,E3},{E7,E4},{E7,E5},{E7,E6},{E7,E11},{E7,E13},{E7,E14},{E7,E15}: begin + destport= 2; + end + {E1,E0},{E2,E0},{E7,E0},{E14,E0}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//7 + 8: begin + case({src_e_addr,dest_e_addr}) + {E1,E12},{E2,E12},{E3,E7},{E4,E7},{E7,E12},{E7,E14},{E8,E7},{E8,E12},{E8,E14},{E9,E7},{E11,E7},{E13,E7},{E14,E7}: begin + destport= 0; + end + {E1,E15},{E7,E5},{E7,E15},{E8,E4},{E8,E5},{E8,E15}: begin + destport= 1; + end + {E1,E4},{E1,E9},{E2,E9},{E3,E10},{E4,E10},{E7,E3},{E7,E4},{E7,E6},{E7,E9},{E7,E13},{E8,E0},{E8,E3},{E8,E6},{E8,E9},{E8,E13},{E11,E10},{E13,E10},{E14,E0},{E14,E10}: begin + destport= 2; + end + {E3,E1},{E4,E1},{E8,E1},{E8,E10},{E9,E1},{E11,E1},{E13,E1},{E14,E1}: begin + destport= 3; + end + {E7,E2},{E7,E11},{E8,E2},{E8,E11}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//8 + 9: begin + case({src_e_addr,dest_e_addr}) + {E0,E5},{E0,E12},{E3,E0},{E4,E0},{E5,E0},{E6,E0},{E8,E0},{E9,E0},{E9,E5},{E9,E12},{E11,E0},{E12,E0},{E13,E0},{E15,E0}: begin + destport= 0; + end + {E0,E11},{E0,E14},{E0,E15},{E9,E2},{E9,E11},{E9,E15}: begin + destport= 1; + end + {E0,E4},{E0,E6},{E0,E13},{E9,E3},{E9,E4},{E9,E6},{E9,E13},{E9,E14}: begin + destport= 2; + end + {E9,E10}: begin + destport= 3; + end + {E0,E8},{E9,E1},{E9,E7},{E9,E8}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//9 + 10: begin + case({src_e_addr,dest_e_addr}) + {E0,E7},{E1,E0},{E2,E0},{E5,E7},{E6,E7},{E7,E0},{E10,E0},{E10,E7},{E10,E12},{E12,E7},{E14,E0},{E15,E7}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E10,E2},{E10,E3},{E10,E4},{E10,E5},{E10,E6},{E10,E11},{E10,E13},{E10,E14},{E10,E15}: begin + destport= 1; + end + {E10,E9}: begin + destport= 2; + end + {E0,E1},{E5,E1},{E6,E1},{E10,E1},{E12,E1},{E15,E1}: begin + destport= 3; + end + {E10,E8}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//10 + 11: begin + case({src_e_addr,dest_e_addr}) + {E0,E2},{E0,E3},{E1,E3},{E1,E14},{E2,E3},{E2,E14},{E3,E2},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E8,E2},{E9,E2},{E10,E2},{E11,E2},{E11,E3},{E11,E14},{E12,E2},{E13,E2},{E14,E2},{E15,E2}: begin + destport= 0; + end + {E1,E5},{E1,E13},{E2,E5},{E2,E15},{E3,E12},{E11,E0},{E11,E5},{E11,E9},{E11,E12},{E11,E15}: begin + destport= 1; + end + {E1,E6},{E2,E4},{E2,E6},{E2,E13},{E11,E4},{E11,E6},{E11,E13}: begin + destport= 2; + end + {E2,E8},{E3,E10},{E11,E1},{E11,E7},{E11,E8},{E11,E10}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//11 + 12: begin + case({src_e_addr,dest_e_addr}) + {E0,E8},{E1,E9},{E1,E15},{E2,E9},{E5,E8},{E5,E10},{E6,E8},{E6,E10},{E7,E9},{E8,E9},{E8,E10},{E9,E8},{E9,E10},{E10,E8},{E10,E9},{E10,E15},{E11,E9},{E12,E8},{E12,E9},{E12,E10},{E12,E15},{E15,E8},{E15,E10}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E0,E11},{E5,E1},{E5,E7},{E6,E1},{E6,E7},{E10,E2},{E10,E11},{E10,E14},{E12,E1},{E12,E2},{E12,E7},{E12,E11},{E12,E14},{E15,E1},{E15,E7}: begin + destport= 2; + end + {E8,E0},{E8,E4},{E9,E1},{E9,E7},{E10,E3},{E10,E4},{E10,E6},{E10,E13},{E12,E0},{E12,E3},{E12,E4},{E12,E6},{E12,E13}: begin + destport= 3; + end + {E8,E5},{E10,E5},{E12,E5}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//12 + 13: begin + case({src_e_addr,dest_e_addr}) + {E0,E4},{E1,E4},{E1,E6},{E2,E4},{E2,E6},{E3,E6},{E3,E14},{E4,E6},{E4,E14},{E5,E4},{E5,E14},{E6,E4},{E7,E4},{E7,E6},{E8,E4},{E8,E6},{E9,E4},{E9,E14},{E10,E4},{E10,E6},{E11,E4},{E11,E6},{E12,E4},{E12,E6},{E13,E4},{E13,E6},{E13,E14},{E14,E4},{E14,E6},{E15,E4},{E15,E6}: begin + destport= 0; + end + {E13,E0},{E13,E5},{E13,E9},{E13,E12},{E13,E15}: begin + destport= 1; + end + {E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin + destport= 2; + end + {E3,E1},{E3,E7},{E3,E8},{E4,E1},{E4,E7},{E4,E8},{E4,E10},{E13,E1},{E13,E7},{E13,E8},{E13,E10}: begin + destport= 3; + end + {E4,E2},{E4,E11},{E5,E2},{E13,E2},{E13,E11}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//13 + 14: begin + case({src_e_addr,dest_e_addr}) + {E0,E11},{E2,E8},{E2,E13},{E2,E15},{E3,E8},{E4,E8},{E4,E11},{E5,E11},{E6,E11},{E7,E11},{E7,E13},{E7,E15},{E8,E11},{E8,E13},{E8,E15},{E9,E11},{E10,E11},{E11,E8},{E11,E13},{E11,E15},{E12,E11},{E13,E8},{E13,E11},{E13,E15},{E14,E8},{E14,E11},{E14,E13},{E14,E15},{E15,E11}: begin + destport= 0; + end + {E3,E12},{E11,E9},{E11,E12},{E13,E12},{E14,E12}: begin + destport= 1; + end + {E0,E2},{E1,E4},{E2,E4},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E7,E3},{E7,E4},{E8,E2},{E8,E3},{E9,E2},{E10,E2},{E11,E4},{E12,E2},{E13,E2},{E14,E2},{E14,E3},{E14,E4},{E15,E2}: begin + destport= 2; + end + {E0,E3},{E1,E6},{E1,E13},{E2,E6},{E3,E1},{E3,E7},{E3,E10},{E4,E1},{E4,E7},{E4,E10},{E7,E6},{E8,E6},{E11,E1},{E11,E6},{E11,E7},{E11,E10},{E13,E1},{E13,E7},{E13,E10},{E14,E0},{E14,E1},{E14,E6},{E14,E7},{E14,E10}: begin + destport= 3; + end + {E1,E5},{E2,E5},{E7,E5},{E11,E0},{E11,E5},{E13,E0},{E13,E5},{E13,E9},{E14,E5},{E14,E9}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//14 + 15: begin + case({src_e_addr,dest_e_addr}) + {E0,E14},{E1,E5},{E1,E13},{E2,E5},{E3,E12},{E4,E12},{E5,E12},{E6,E12},{E6,E14},{E7,E5},{E8,E5},{E10,E5},{E10,E13},{E10,E14},{E11,E5},{E11,E12},{E12,E5},{E12,E13},{E12,E14},{E13,E5},{E13,E12},{E14,E5},{E14,E12},{E15,E5},{E15,E12},{E15,E13},{E15,E14}: begin + destport= 0; + end + {E8,E4},{E10,E3},{E10,E4},{E11,E9},{E12,E3},{E12,E4},{E15,E3},{E15,E4}: begin + destport= 2; + end + {E5,E1},{E5,E7},{E5,E10},{E6,E1},{E6,E7},{E6,E10},{E10,E6},{E11,E0},{E12,E6},{E13,E0},{E13,E9},{E14,E9},{E15,E0},{E15,E1},{E15,E6},{E15,E7},{E15,E9},{E15,E10}: begin + destport= 3; + end + {E0,E2},{E0,E3},{E0,E11},{E5,E8},{E5,E11},{E6,E2},{E6,E8},{E6,E11},{E9,E2},{E9,E11},{E10,E2},{E10,E11},{E12,E2},{E12,E11},{E15,E2},{E15,E8},{E15,E11}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//15 + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + +endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v index d5a7c21..a5264fa 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v @@ -1,462 +1,445 @@ /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/ /********************************************************************** -** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v +** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v ** -** Copyright (C) 2014-2022 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.2.0 +** This file is part of ProNoC 2.2.0 ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ - `include "pronoc_def.v" - +`include "pronoc_def.v" /***************************** * Tcustom1Rcustom_look_ahead_routing_genvar ******************************/ module Tcustom1Rcustom_look_ahead_routing_genvar #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4, - parameter CURRENT_R_ADDR=0 -) -( - dest_e_addr, - src_e_addr, - destport, - reset, - clk + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter CURRENT_R_ADDR=0 +)( + dest_e_addr, + src_e_addr, + destport, + reset, + clk ); - - input [EAw-1 :0] dest_e_addr; - input [EAw-1 :0] src_e_addr; - output [DSTPw-1 :0] destport; - input reset,clk; - + + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output [DSTPw-1 :0] destport; + input reset,clk; + reg [EAw-1 :0] dest_e_addr_delay; reg [EAw-1 :0] src_e_addr_delay; - - always @ (`pronoc_clk_reset_edge )begin + + always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin dest_e_addr_delay<={EAw{1'b0}}; - src_e_addr_delay<={EAw{1'b0}}; + src_e_addr_delay<={EAw{1'b0}}; end else begin dest_e_addr_delay<=dest_e_addr; - src_e_addr_delay<=src_e_addr; - end + src_e_addr_delay<=src_e_addr; + end end - custom1_look_ahead_routing_genvar_comb #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw), .CURRENT_R_ADDR(CURRENT_R_ADDR) - ) - lkp_cmb - ( - + ) lkp_cmb ( .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), .destport(destport) ); +endmodule - - -endmodule - /******************* * Tcustom1Rcustom_look_ahead_routing_genvar_comb ********************/ - - - module Tcustom1Rcustom_look_ahead_routing_genvar_comb #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4, - parameter CURRENT_R_ADDR=0 -) -( - dest_e_addr, - src_e_addr, - destport +module Tcustom1Rcustom_look_ahead_routing_genvar_comb #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter CURRENT_R_ADDR=0 +) ( + dest_e_addr, + src_e_addr, + destport ); - - input [EAw-1 :0] dest_e_addr; - input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; - -localparam [EAw-1 : 0] E0=0; -localparam [EAw-1 : 0] E1=1; -localparam [EAw-1 : 0] E2=2; -localparam [EAw-1 : 0] E3=3; -localparam [EAw-1 : 0] E4=4; -localparam [EAw-1 : 0] E5=5; -localparam [EAw-1 : 0] E6=6; -localparam [EAw-1 : 0] E7=7; -localparam [EAw-1 : 0] E8=8; -localparam [EAw-1 : 0] E9=9; -localparam [EAw-1 : 0] E10=10; -localparam [EAw-1 : 0] E11=11; -localparam [EAw-1 : 0] E12=12; -localparam [EAw-1 : 0] E13=13; -localparam [EAw-1 : 0] E14=14; -localparam [EAw-1 : 0] E15=15; - - - generate - if(CURRENT_R_ADDR == 0) begin :R0 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E9},{E0,E10}: begin - destport= 0; - end - {E0,E2},{E0,E3},{E0,E8},{E0,E11},{E0,E12}: begin - destport= 1; - end - {E0,E1},{E0,E4},{E0,E5},{E0,E6},{E0,E7},{E0,E13},{E0,E14},{E0,E15}: begin - destport= 2; - end - endcase - end - end//R0 - - if(CURRENT_R_ADDR == 1) begin :R1 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E1,E2},{E1,E7},{E2,E7}: begin - destport= 0; - end - {E1,E3},{E1,E4},{E1,E5},{E1,E6},{E1,E8},{E1,E9},{E1,E11},{E1,E12},{E1,E13},{E1,E14},{E1,E15},{E2,E9},{E2,E12}: begin - destport= 1; - end - {E1,E0},{E1,E10},{E2,E0},{E2,E10}: begin - destport= 2; - end - endcase - end - end//R1 - - if(CURRENT_R_ADDR == 2) begin :R2 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E1,E11},{E2,E1},{E2,E11}: begin - destport= 0; - end - {E1,E5},{E1,E6},{E1,E13},{E1,E14},{E2,E0},{E2,E4},{E2,E5},{E2,E6},{E2,E7},{E2,E8},{E2,E9},{E2,E10},{E2,E12},{E2,E13},{E2,E14},{E2,E15}: begin - destport= 1; - end - {E1,E3},{E2,E3}: begin - destport= 3; - end - endcase - end - end//R2 - - if(CURRENT_R_ADDR == 3) begin :R3 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E3,E4},{E3,E11}: begin - destport= 0; - end - {E3,E1},{E3,E6},{E3,E7},{E3,E8},{E3,E10},{E3,E12},{E3,E13},{E3,E14}: begin - destport= 1; - end - {E3,E2}: begin - destport= 2; - end - {E3,E0},{E3,E5},{E3,E9},{E3,E15}: begin - destport= 3; - end - endcase - end - end//R3 - - if(CURRENT_R_ADDR == 4) begin :R4 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E3,E13},{E4,E3},{E4,E13},{E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin - destport= 0; - end - {E4,E2},{E4,E11},{E4,E14}: begin - destport= 1; - end - {E3,E0},{E3,E5},{E3,E9},{E3,E15},{E4,E0},{E4,E5},{E4,E9},{E4,E12},{E4,E15}: begin - destport= 2; - end - {E3,E6},{E4,E6}: begin - destport= 3; - end - {E3,E1},{E3,E7},{E3,E8},{E3,E14},{E4,E1},{E4,E7},{E4,E8},{E4,E10}: begin - destport= 4; - end - endcase - end - end//R4 - - if(CURRENT_R_ADDR == 5) begin :R5 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E6},{E0,E15},{E3,E9},{E3,E15},{E4,E9},{E4,E15},{E5,E6},{E5,E9},{E5,E15},{E6,E9},{E6,E15},{E9,E6},{E9,E15},{E13,E9},{E14,E9},{E15,E9}: begin - destport= 0; - end - {E0,E4},{E0,E13},{E4,E12},{E5,E1},{E5,E2},{E5,E3},{E5,E4},{E5,E7},{E5,E8},{E5,E10},{E5,E12},{E5,E13},{E5,E14},{E6,E1},{E6,E7},{E6,E8},{E6,E10},{E6,E12},{E9,E3},{E9,E4},{E9,E13},{E9,E14}: begin - destport= 1; - end - {E0,E14},{E5,E11},{E6,E2},{E6,E11},{E6,E14},{E9,E2},{E9,E11}: begin - destport= 2; - end - {E3,E0},{E4,E0},{E5,E0},{E6,E0},{E11,E0},{E13,E0},{E15,E0}: begin - destport= 3; - end - endcase - end - end//R5 - - if(CURRENT_R_ADDR == 6) begin :R6 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E13},{E3,E5},{E4,E5},{E5,E13},{E6,E5},{E6,E13},{E9,E13}: begin - destport= 0; - end - {E3,E15},{E4,E12},{E4,E15},{E6,E1},{E6,E2},{E6,E7},{E6,E8},{E6,E10},{E6,E11},{E6,E12},{E6,E14},{E6,E15}: begin - destport= 1; - end - {E0,E4},{E5,E3},{E5,E4},{E6,E3},{E6,E4},{E9,E3},{E9,E4}: begin - destport= 2; - end - {E3,E0},{E3,E9},{E4,E0},{E4,E9},{E6,E0},{E6,E9}: begin - destport= 3; - end - {E4,E2},{E4,E11},{E4,E14},{E5,E2},{E5,E14},{E9,E14}: begin - destport= 4; - end - endcase - end - end//R6 - - if(CURRENT_R_ADDR == 7) begin :R7 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E1},{E1,E8},{E1,E10},{E2,E10},{E3,E1},{E3,E10},{E4,E1},{E4,E10},{E5,E1},{E6,E1},{E7,E1},{E7,E8},{E7,E10},{E8,E1},{E9,E1},{E10,E1},{E11,E1},{E11,E10},{E12,E1},{E13,E1},{E13,E10},{E14,E1},{E14,E10},{E15,E1}: begin - destport= 0; - end - {E1,E9},{E1,E12},{E1,E15},{E2,E9},{E2,E12},{E7,E9},{E7,E12}: begin - destport= 1; - end - {E1,E4},{E7,E2},{E7,E3},{E7,E4},{E7,E5},{E7,E6},{E7,E11},{E7,E13},{E7,E14},{E7,E15}: begin - destport= 2; - end - {E1,E0},{E2,E0},{E7,E0},{E14,E0}: begin - destport= 3; - end - endcase - end - end//R7 - - if(CURRENT_R_ADDR == 8) begin :R8 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E1,E12},{E2,E12},{E3,E7},{E4,E7},{E7,E12},{E7,E14},{E8,E7},{E8,E12},{E8,E14},{E9,E7},{E11,E7},{E13,E7},{E14,E7}: begin - destport= 0; - end - {E1,E15},{E7,E5},{E7,E15},{E8,E4},{E8,E5},{E8,E15}: begin - destport= 1; - end - {E1,E4},{E1,E9},{E2,E9},{E3,E10},{E4,E10},{E7,E3},{E7,E4},{E7,E6},{E7,E9},{E7,E13},{E8,E0},{E8,E3},{E8,E6},{E8,E9},{E8,E13},{E11,E10},{E13,E10},{E14,E0},{E14,E10}: begin - destport= 2; - end - {E3,E1},{E4,E1},{E8,E1},{E8,E10},{E9,E1},{E11,E1},{E13,E1},{E14,E1}: begin - destport= 3; - end - {E7,E2},{E7,E11},{E8,E2},{E8,E11}: begin - destport= 4; - end - endcase - end - end//R8 - - if(CURRENT_R_ADDR == 9) begin :R9 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E5},{E0,E12},{E3,E0},{E4,E0},{E5,E0},{E6,E0},{E8,E0},{E9,E0},{E9,E5},{E9,E12},{E11,E0},{E12,E0},{E13,E0},{E15,E0}: begin - destport= 0; - end - {E0,E11},{E0,E14},{E0,E15},{E9,E2},{E9,E11},{E9,E15}: begin - destport= 1; - end - {E0,E4},{E0,E6},{E0,E13},{E9,E3},{E9,E4},{E9,E6},{E9,E13},{E9,E14}: begin - destport= 2; - end - {E9,E10}: begin - destport= 3; - end - {E0,E8},{E9,E1},{E9,E7},{E9,E8}: begin - destport= 4; - end - endcase - end - end//R9 - - if(CURRENT_R_ADDR == 10) begin :R10 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E7},{E1,E0},{E2,E0},{E5,E7},{E6,E7},{E7,E0},{E10,E0},{E10,E7},{E10,E12},{E12,E7},{E14,E0},{E15,E7}: begin - destport= 0; - end - {E0,E2},{E0,E3},{E10,E2},{E10,E3},{E10,E4},{E10,E5},{E10,E6},{E10,E11},{E10,E13},{E10,E14},{E10,E15}: begin - destport= 1; - end - {E10,E9}: begin - destport= 2; - end - {E0,E1},{E5,E1},{E6,E1},{E10,E1},{E12,E1},{E15,E1}: begin - destport= 3; - end - {E10,E8}: begin - destport= 4; - end - endcase - end - end//R10 - - if(CURRENT_R_ADDR == 11) begin :R11 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E2},{E0,E3},{E1,E3},{E1,E14},{E2,E3},{E2,E14},{E3,E2},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E8,E2},{E9,E2},{E10,E2},{E11,E2},{E11,E3},{E11,E14},{E12,E2},{E13,E2},{E14,E2},{E15,E2}: begin - destport= 0; - end - {E1,E5},{E1,E13},{E2,E5},{E2,E15},{E3,E12},{E11,E0},{E11,E5},{E11,E9},{E11,E12},{E11,E15}: begin - destport= 1; - end - {E1,E6},{E2,E4},{E2,E6},{E2,E13},{E11,E4},{E11,E6},{E11,E13}: begin - destport= 2; - end - {E2,E8},{E3,E10},{E11,E1},{E11,E7},{E11,E8},{E11,E10}: begin - destport= 3; - end - endcase - end - end//R11 - - if(CURRENT_R_ADDR == 12) begin :R12 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E8},{E1,E9},{E1,E15},{E2,E9},{E5,E8},{E5,E10},{E6,E8},{E6,E10},{E7,E9},{E8,E9},{E8,E10},{E9,E8},{E9,E10},{E10,E8},{E10,E9},{E10,E15},{E11,E9},{E12,E8},{E12,E9},{E12,E10},{E12,E15},{E15,E8},{E15,E10}: begin - destport= 0; - end - {E0,E2},{E0,E3},{E0,E11},{E5,E1},{E5,E7},{E6,E1},{E6,E7},{E10,E2},{E10,E11},{E10,E14},{E12,E1},{E12,E2},{E12,E7},{E12,E11},{E12,E14},{E15,E1},{E15,E7}: begin - destport= 2; - end - {E8,E0},{E8,E4},{E9,E1},{E9,E7},{E10,E3},{E10,E4},{E10,E6},{E10,E13},{E12,E0},{E12,E3},{E12,E4},{E12,E6},{E12,E13}: begin - destport= 3; - end - {E8,E5},{E10,E5},{E12,E5}: begin - destport= 4; - end - endcase - end - end//R12 - - if(CURRENT_R_ADDR == 13) begin :R13 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E4},{E1,E4},{E1,E6},{E2,E4},{E2,E6},{E3,E6},{E3,E14},{E4,E6},{E4,E14},{E5,E4},{E5,E14},{E6,E4},{E7,E4},{E7,E6},{E8,E4},{E8,E6},{E9,E4},{E9,E14},{E10,E4},{E10,E6},{E11,E4},{E11,E6},{E12,E4},{E12,E6},{E13,E4},{E13,E6},{E13,E14},{E14,E4},{E14,E6},{E15,E4},{E15,E6}: begin - destport= 0; - end - {E13,E0},{E13,E5},{E13,E9},{E13,E12},{E13,E15}: begin - destport= 1; - end - {E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin - destport= 2; - end - {E3,E1},{E3,E7},{E3,E8},{E4,E1},{E4,E7},{E4,E8},{E4,E10},{E13,E1},{E13,E7},{E13,E8},{E13,E10}: begin - destport= 3; - end - {E4,E2},{E4,E11},{E5,E2},{E13,E2},{E13,E11}: begin - destport= 4; - end - endcase - end - end//R13 - - if(CURRENT_R_ADDR == 14) begin :R14 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E11},{E2,E8},{E2,E13},{E2,E15},{E3,E8},{E4,E8},{E4,E11},{E5,E11},{E6,E11},{E7,E11},{E7,E13},{E7,E15},{E8,E11},{E8,E13},{E8,E15},{E9,E11},{E10,E11},{E11,E8},{E11,E13},{E11,E15},{E12,E11},{E13,E8},{E13,E11},{E13,E15},{E14,E8},{E14,E11},{E14,E13},{E14,E15},{E15,E11}: begin - destport= 0; - end - {E3,E12},{E11,E9},{E11,E12},{E13,E12},{E14,E12}: begin - destport= 1; - end - {E0,E2},{E1,E4},{E2,E4},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E7,E3},{E7,E4},{E8,E2},{E8,E3},{E9,E2},{E10,E2},{E11,E4},{E12,E2},{E13,E2},{E14,E2},{E14,E3},{E14,E4},{E15,E2}: begin - destport= 2; - end - {E0,E3},{E1,E6},{E1,E13},{E2,E6},{E3,E1},{E3,E7},{E3,E10},{E4,E1},{E4,E7},{E4,E10},{E7,E6},{E8,E6},{E11,E1},{E11,E6},{E11,E7},{E11,E10},{E13,E1},{E13,E7},{E13,E10},{E14,E0},{E14,E1},{E14,E6},{E14,E7},{E14,E10}: begin - destport= 3; - end - {E1,E5},{E2,E5},{E7,E5},{E11,E0},{E11,E5},{E13,E0},{E13,E5},{E13,E9},{E14,E5},{E14,E9}: begin - destport= 4; - end - endcase - end - end//R14 - - if(CURRENT_R_ADDR == 15) begin :R15 - always@(*)begin - destport= 0; - case({src_e_addr,dest_e_addr}) - {E0,E14},{E1,E5},{E1,E13},{E2,E5},{E3,E12},{E4,E12},{E5,E12},{E6,E12},{E6,E14},{E7,E5},{E8,E5},{E10,E5},{E10,E13},{E10,E14},{E11,E5},{E11,E12},{E12,E5},{E12,E13},{E12,E14},{E13,E5},{E13,E12},{E14,E5},{E14,E12},{E15,E5},{E15,E12},{E15,E13},{E15,E14}: begin - destport= 0; - end - {E8,E4},{E10,E3},{E10,E4},{E11,E9},{E12,E3},{E12,E4},{E15,E3},{E15,E4}: begin - destport= 2; - end - {E5,E1},{E5,E7},{E5,E10},{E6,E1},{E6,E7},{E6,E10},{E10,E6},{E11,E0},{E12,E6},{E13,E0},{E13,E9},{E14,E9},{E15,E0},{E15,E1},{E15,E6},{E15,E7},{E15,E9},{E15,E10}: begin - destport= 3; - end - {E0,E2},{E0,E3},{E0,E11},{E5,E8},{E5,E11},{E6,E2},{E6,E8},{E6,E11},{E9,E2},{E9,E11},{E10,E2},{E10,E11},{E12,E2},{E12,E11},{E15,E2},{E15,E8},{E15,E11}: begin - destport= 4; - end - endcase - end - end//R15 - - endgenerate + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output reg [DSTPw-1 :0] destport; +localparam [EAw-1 : 0] E0=0; +localparam [EAw-1 : 0] E1=1; +localparam [EAw-1 : 0] E2=2; +localparam [EAw-1 : 0] E3=3; +localparam [EAw-1 : 0] E4=4; +localparam [EAw-1 : 0] E5=5; +localparam [EAw-1 : 0] E6=6; +localparam [EAw-1 : 0] E7=7; +localparam [EAw-1 : 0] E8=8; +localparam [EAw-1 : 0] E9=9; +localparam [EAw-1 : 0] E10=10; +localparam [EAw-1 : 0] E11=11; +localparam [EAw-1 : 0] E12=12; +localparam [EAw-1 : 0] E13=13; +localparam [EAw-1 : 0] E14=14; +localparam [EAw-1 : 0] E15=15; + + + generate + if(CURRENT_R_ADDR == 0) begin :R0 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E9},{E0,E10}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E0,E8},{E0,E11},{E0,E12}: begin + destport= 1; + end + {E0,E1},{E0,E4},{E0,E5},{E0,E6},{E0,E7},{E0,E13},{E0,E14},{E0,E15}: begin + destport= 2; + end + endcase + end + end//R0 + + if(CURRENT_R_ADDR == 1) begin :R1 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E1,E2},{E1,E7},{E2,E7}: begin + destport= 0; + end + {E1,E3},{E1,E4},{E1,E5},{E1,E6},{E1,E8},{E1,E9},{E1,E11},{E1,E12},{E1,E13},{E1,E14},{E1,E15},{E2,E9},{E2,E12}: begin + destport= 1; + end + {E1,E0},{E1,E10},{E2,E0},{E2,E10}: begin + destport= 2; + end + endcase + end + end//R1 + + if(CURRENT_R_ADDR == 2) begin :R2 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E1,E11},{E2,E1},{E2,E11}: begin + destport= 0; + end + {E1,E5},{E1,E6},{E1,E13},{E1,E14},{E2,E0},{E2,E4},{E2,E5},{E2,E6},{E2,E7},{E2,E8},{E2,E9},{E2,E10},{E2,E12},{E2,E13},{E2,E14},{E2,E15}: begin + destport= 1; + end + {E1,E3},{E2,E3}: begin + destport= 3; + end + endcase + end + end//R2 + + if(CURRENT_R_ADDR == 3) begin :R3 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E3,E4},{E3,E11}: begin + destport= 0; + end + {E3,E1},{E3,E6},{E3,E7},{E3,E8},{E3,E10},{E3,E12},{E3,E13},{E3,E14}: begin + destport= 1; + end + {E3,E2}: begin + destport= 2; + end + {E3,E0},{E3,E5},{E3,E9},{E3,E15}: begin + destport= 3; + end + endcase + end + end//R3 + + if(CURRENT_R_ADDR == 4) begin :R4 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E3,E13},{E4,E3},{E4,E13},{E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin + destport= 0; + end + {E4,E2},{E4,E11},{E4,E14}: begin + destport= 1; + end + {E3,E0},{E3,E5},{E3,E9},{E3,E15},{E4,E0},{E4,E5},{E4,E9},{E4,E12},{E4,E15}: begin + destport= 2; + end + {E3,E6},{E4,E6}: begin + destport= 3; + end + {E3,E1},{E3,E7},{E3,E8},{E3,E14},{E4,E1},{E4,E7},{E4,E8},{E4,E10}: begin + destport= 4; + end + endcase + end + end//R4 + + if(CURRENT_R_ADDR == 5) begin :R5 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E6},{E0,E15},{E3,E9},{E3,E15},{E4,E9},{E4,E15},{E5,E6},{E5,E9},{E5,E15},{E6,E9},{E6,E15},{E9,E6},{E9,E15},{E13,E9},{E14,E9},{E15,E9}: begin + destport= 0; + end + {E0,E4},{E0,E13},{E4,E12},{E5,E1},{E5,E2},{E5,E3},{E5,E4},{E5,E7},{E5,E8},{E5,E10},{E5,E12},{E5,E13},{E5,E14},{E6,E1},{E6,E7},{E6,E8},{E6,E10},{E6,E12},{E9,E3},{E9,E4},{E9,E13},{E9,E14}: begin + destport= 1; + end + {E0,E14},{E5,E11},{E6,E2},{E6,E11},{E6,E14},{E9,E2},{E9,E11}: begin + destport= 2; + end + {E3,E0},{E4,E0},{E5,E0},{E6,E0},{E11,E0},{E13,E0},{E15,E0}: begin + destport= 3; + end + endcase + end + end//R5 + + if(CURRENT_R_ADDR == 6) begin :R6 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E13},{E3,E5},{E4,E5},{E5,E13},{E6,E5},{E6,E13},{E9,E13}: begin + destport= 0; + end + {E3,E15},{E4,E12},{E4,E15},{E6,E1},{E6,E2},{E6,E7},{E6,E8},{E6,E10},{E6,E11},{E6,E12},{E6,E14},{E6,E15}: begin + destport= 1; + end + {E0,E4},{E5,E3},{E5,E4},{E6,E3},{E6,E4},{E9,E3},{E9,E4}: begin + destport= 2; + end + {E3,E0},{E3,E9},{E4,E0},{E4,E9},{E6,E0},{E6,E9}: begin + destport= 3; + end + {E4,E2},{E4,E11},{E4,E14},{E5,E2},{E5,E14},{E9,E14}: begin + destport= 4; + end + endcase + end + end//R6 + + if(CURRENT_R_ADDR == 7) begin :R7 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E1},{E1,E8},{E1,E10},{E2,E10},{E3,E1},{E3,E10},{E4,E1},{E4,E10},{E5,E1},{E6,E1},{E7,E1},{E7,E8},{E7,E10},{E8,E1},{E9,E1},{E10,E1},{E11,E1},{E11,E10},{E12,E1},{E13,E1},{E13,E10},{E14,E1},{E14,E10},{E15,E1}: begin + destport= 0; + end + {E1,E9},{E1,E12},{E1,E15},{E2,E9},{E2,E12},{E7,E9},{E7,E12}: begin + destport= 1; + end + {E1,E4},{E7,E2},{E7,E3},{E7,E4},{E7,E5},{E7,E6},{E7,E11},{E7,E13},{E7,E14},{E7,E15}: begin + destport= 2; + end + {E1,E0},{E2,E0},{E7,E0},{E14,E0}: begin + destport= 3; + end + endcase + end + end//R7 + + if(CURRENT_R_ADDR == 8) begin :R8 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E1,E12},{E2,E12},{E3,E7},{E4,E7},{E7,E12},{E7,E14},{E8,E7},{E8,E12},{E8,E14},{E9,E7},{E11,E7},{E13,E7},{E14,E7}: begin + destport= 0; + end + {E1,E15},{E7,E5},{E7,E15},{E8,E4},{E8,E5},{E8,E15}: begin + destport= 1; + end + {E1,E4},{E1,E9},{E2,E9},{E3,E10},{E4,E10},{E7,E3},{E7,E4},{E7,E6},{E7,E9},{E7,E13},{E8,E0},{E8,E3},{E8,E6},{E8,E9},{E8,E13},{E11,E10},{E13,E10},{E14,E0},{E14,E10}: begin + destport= 2; + end + {E3,E1},{E4,E1},{E8,E1},{E8,E10},{E9,E1},{E11,E1},{E13,E1},{E14,E1}: begin + destport= 3; + end + {E7,E2},{E7,E11},{E8,E2},{E8,E11}: begin + destport= 4; + end + endcase + end + end//R8 + + if(CURRENT_R_ADDR == 9) begin :R9 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E5},{E0,E12},{E3,E0},{E4,E0},{E5,E0},{E6,E0},{E8,E0},{E9,E0},{E9,E5},{E9,E12},{E11,E0},{E12,E0},{E13,E0},{E15,E0}: begin + destport= 0; + end + {E0,E11},{E0,E14},{E0,E15},{E9,E2},{E9,E11},{E9,E15}: begin + destport= 1; + end + {E0,E4},{E0,E6},{E0,E13},{E9,E3},{E9,E4},{E9,E6},{E9,E13},{E9,E14}: begin + destport= 2; + end + {E9,E10}: begin + destport= 3; + end + {E0,E8},{E9,E1},{E9,E7},{E9,E8}: begin + destport= 4; + end + endcase + end + end//R9 + + if(CURRENT_R_ADDR == 10) begin :R10 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E7},{E1,E0},{E2,E0},{E5,E7},{E6,E7},{E7,E0},{E10,E0},{E10,E7},{E10,E12},{E12,E7},{E14,E0},{E15,E7}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E10,E2},{E10,E3},{E10,E4},{E10,E5},{E10,E6},{E10,E11},{E10,E13},{E10,E14},{E10,E15}: begin + destport= 1; + end + {E10,E9}: begin + destport= 2; + end + {E0,E1},{E5,E1},{E6,E1},{E10,E1},{E12,E1},{E15,E1}: begin + destport= 3; + end + {E10,E8}: begin + destport= 4; + end + endcase + end + end//R10 + + if(CURRENT_R_ADDR == 11) begin :R11 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E2},{E0,E3},{E1,E3},{E1,E14},{E2,E3},{E2,E14},{E3,E2},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E8,E2},{E9,E2},{E10,E2},{E11,E2},{E11,E3},{E11,E14},{E12,E2},{E13,E2},{E14,E2},{E15,E2}: begin + destport= 0; + end + {E1,E5},{E1,E13},{E2,E5},{E2,E15},{E3,E12},{E11,E0},{E11,E5},{E11,E9},{E11,E12},{E11,E15}: begin + destport= 1; + end + {E1,E6},{E2,E4},{E2,E6},{E2,E13},{E11,E4},{E11,E6},{E11,E13}: begin + destport= 2; + end + {E2,E8},{E3,E10},{E11,E1},{E11,E7},{E11,E8},{E11,E10}: begin + destport= 3; + end + endcase + end + end//R11 + + if(CURRENT_R_ADDR == 12) begin :R12 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E8},{E1,E9},{E1,E15},{E2,E9},{E5,E8},{E5,E10},{E6,E8},{E6,E10},{E7,E9},{E8,E9},{E8,E10},{E9,E8},{E9,E10},{E10,E8},{E10,E9},{E10,E15},{E11,E9},{E12,E8},{E12,E9},{E12,E10},{E12,E15},{E15,E8},{E15,E10}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E0,E11},{E5,E1},{E5,E7},{E6,E1},{E6,E7},{E10,E2},{E10,E11},{E10,E14},{E12,E1},{E12,E2},{E12,E7},{E12,E11},{E12,E14},{E15,E1},{E15,E7}: begin + destport= 2; + end + {E8,E0},{E8,E4},{E9,E1},{E9,E7},{E10,E3},{E10,E4},{E10,E6},{E10,E13},{E12,E0},{E12,E3},{E12,E4},{E12,E6},{E12,E13}: begin + destport= 3; + end + {E8,E5},{E10,E5},{E12,E5}: begin + destport= 4; + end + endcase + end + end//R12 + + if(CURRENT_R_ADDR == 13) begin :R13 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E4},{E1,E4},{E1,E6},{E2,E4},{E2,E6},{E3,E6},{E3,E14},{E4,E6},{E4,E14},{E5,E4},{E5,E14},{E6,E4},{E7,E4},{E7,E6},{E8,E4},{E8,E6},{E9,E4},{E9,E14},{E10,E4},{E10,E6},{E11,E4},{E11,E6},{E12,E4},{E12,E6},{E13,E4},{E13,E6},{E13,E14},{E14,E4},{E14,E6},{E15,E4},{E15,E6}: begin + destport= 0; + end + {E13,E0},{E13,E5},{E13,E9},{E13,E12},{E13,E15}: begin + destport= 1; + end + {E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin + destport= 2; + end + {E3,E1},{E3,E7},{E3,E8},{E4,E1},{E4,E7},{E4,E8},{E4,E10},{E13,E1},{E13,E7},{E13,E8},{E13,E10}: begin + destport= 3; + end + {E4,E2},{E4,E11},{E5,E2},{E13,E2},{E13,E11}: begin + destport= 4; + end + endcase + end + end//R13 + + if(CURRENT_R_ADDR == 14) begin :R14 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E11},{E2,E8},{E2,E13},{E2,E15},{E3,E8},{E4,E8},{E4,E11},{E5,E11},{E6,E11},{E7,E11},{E7,E13},{E7,E15},{E8,E11},{E8,E13},{E8,E15},{E9,E11},{E10,E11},{E11,E8},{E11,E13},{E11,E15},{E12,E11},{E13,E8},{E13,E11},{E13,E15},{E14,E8},{E14,E11},{E14,E13},{E14,E15},{E15,E11}: begin + destport= 0; + end + {E3,E12},{E11,E9},{E11,E12},{E13,E12},{E14,E12}: begin + destport= 1; + end + {E0,E2},{E1,E4},{E2,E4},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E7,E3},{E7,E4},{E8,E2},{E8,E3},{E9,E2},{E10,E2},{E11,E4},{E12,E2},{E13,E2},{E14,E2},{E14,E3},{E14,E4},{E15,E2}: begin + destport= 2; + end + {E0,E3},{E1,E6},{E1,E13},{E2,E6},{E3,E1},{E3,E7},{E3,E10},{E4,E1},{E4,E7},{E4,E10},{E7,E6},{E8,E6},{E11,E1},{E11,E6},{E11,E7},{E11,E10},{E13,E1},{E13,E7},{E13,E10},{E14,E0},{E14,E1},{E14,E6},{E14,E7},{E14,E10}: begin + destport= 3; + end + {E1,E5},{E2,E5},{E7,E5},{E11,E0},{E11,E5},{E13,E0},{E13,E5},{E13,E9},{E14,E5},{E14,E9}: begin + destport= 4; + end + endcase + end + end//R14 + + if(CURRENT_R_ADDR == 15) begin :R15 + always@(*)begin + destport= 0; + case({src_e_addr,dest_e_addr}) + {E0,E14},{E1,E5},{E1,E13},{E2,E5},{E3,E12},{E4,E12},{E5,E12},{E6,E12},{E6,E14},{E7,E5},{E8,E5},{E10,E5},{E10,E13},{E10,E14},{E11,E5},{E11,E12},{E12,E5},{E12,E13},{E12,E14},{E13,E5},{E13,E12},{E14,E5},{E14,E12},{E15,E5},{E15,E12},{E15,E13},{E15,E14}: begin + destport= 0; + end + {E8,E4},{E10,E3},{E10,E4},{E11,E9},{E12,E3},{E12,E4},{E15,E3},{E15,E4}: begin + destport= 2; + end + {E5,E1},{E5,E7},{E5,E10},{E6,E1},{E6,E7},{E6,E10},{E10,E6},{E11,E0},{E12,E6},{E13,E0},{E13,E9},{E14,E9},{E15,E0},{E15,E1},{E15,E6},{E15,E7},{E15,E9},{E15,E10}: begin + destport= 3; + end + {E0,E2},{E0,E3},{E0,E11},{E5,E8},{E5,E11},{E6,E2},{E6,E8},{E6,E11},{E9,E2},{E9,E11},{E10,E2},{E10,E11},{E12,E2},{E12,E11},{E15,E2},{E15,E8},{E15,E11}: begin + destport= 4; + end + endcase + end + end//R15 + + endgenerate - endmodule - - diff --git a/mpsoc/rtl/src_topology/custom1/custom1.png b/mpsoc/rtl/src_topology/custom1/custom1.png index 584d953c128037c26f6cbc962ad5bf1c94fcf6ec..7f2128aa79a06dfa11ac4713761b176b2981efed 100644 GIT binary patch literal 103874 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

G>~aao;(>v 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

&;{z8Vdxv1{?s|>rf*TzTCT{P6@$m{g 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 DP0>y;pWBsQn(jsBZ~j&m*o-z415l-5G7wuOEp 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. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ `include "pronoc_def.v" @@ -31,400 +31,350 @@ module custom1_noc #( parameter NOC_ID=0 -) -( - reset, - clk, - //T0, - T0_chan_in, - T0_chan_out, - T0_router_event, - //T1, - T1_chan_in, - T1_chan_out, - T1_router_event, - //T2, - T2_chan_in, - T2_chan_out, - T2_router_event, - //T3, - T3_chan_in, - T3_chan_out, - T3_router_event, - //T4, - T4_chan_in, - T4_chan_out, - T4_router_event, - //T5, - T5_chan_in, - T5_chan_out, - T5_router_event, - //T6, - T6_chan_in, - T6_chan_out, - T6_router_event, - //T7, - T7_chan_in, - T7_chan_out, - T7_router_event, - //T8, - T8_chan_in, - T8_chan_out, - T8_router_event, - //T9, - T9_chan_in, - T9_chan_out, - T9_router_event, - //T10, - T10_chan_in, - T10_chan_out, - T10_router_event, - //T11, - T11_chan_in, - T11_chan_out, - T11_router_event, - //T12, - T12_chan_in, - T12_chan_out, - T12_router_event, - //T13, - T13_chan_in, - T13_chan_out, - T13_router_event, - //T14, - T14_chan_in, - T14_chan_out, - T14_router_event, - //T15, - T15_chan_in, - T15_chan_out, - T15_router_event +)( + reset, + clk, + //T0, + T0_chan_in, + T0_chan_out, + T0_router_event, + //T1, + T1_chan_in, + T1_chan_out, + T1_router_event, + //T2, + T2_chan_in, + T2_chan_out, + T2_router_event, + //T3, + T3_chan_in, + T3_chan_out, + T3_router_event, + //T4, + T4_chan_in, + T4_chan_out, + T4_router_event, + //T5, + T5_chan_in, + T5_chan_out, + T5_router_event, + //T6, + T6_chan_in, + T6_chan_out, + T6_router_event, + //T7, + T7_chan_in, + T7_chan_out, + T7_router_event, + //T8, + T8_chan_in, + T8_chan_out, + T8_router_event, + //T9, + T9_chan_in, + T9_chan_out, + T9_router_event, + //T10, + T10_chan_in, + T10_chan_out, + T10_router_event, + //T11, + T11_chan_in, + T11_chan_out, + T11_router_event, + //T12, + T12_chan_in, + T12_chan_out, + T12_router_event, + //T13, + T13_chan_in, + T13_chan_out, + T13_router_event, + //T14, + T14_chan_in, + T14_chan_out, + T14_router_event, + //T15, + T15_chan_in, + T15_chan_out, + T15_router_event ); - `NOC_CONF - + input reset,clk; - + /******************* * T0 *******************/ - input smartflit_chanel_t T0_chan_in; - output smartflit_chanel_t T0_chan_out; - output router_event_t T0_router_event; + input smartflit_chanel_t T0_chan_in; + output smartflit_chanel_t T0_chan_out; + output router_event_t T0_router_event; /******************* * T1 *******************/ - input smartflit_chanel_t T1_chan_in; - output smartflit_chanel_t T1_chan_out; - output router_event_t T1_router_event; + input smartflit_chanel_t T1_chan_in; + output smartflit_chanel_t T1_chan_out; + output router_event_t T1_router_event; /******************* * T2 *******************/ - input smartflit_chanel_t T2_chan_in; - output smartflit_chanel_t T2_chan_out; - output router_event_t T2_router_event; + input smartflit_chanel_t T2_chan_in; + output smartflit_chanel_t T2_chan_out; + output router_event_t T2_router_event; /******************* * T3 *******************/ - input smartflit_chanel_t T3_chan_in; - output smartflit_chanel_t T3_chan_out; - output router_event_t T3_router_event; + input smartflit_chanel_t T3_chan_in; + output smartflit_chanel_t T3_chan_out; + output router_event_t T3_router_event; /******************* * T4 *******************/ - input smartflit_chanel_t T4_chan_in; - output smartflit_chanel_t T4_chan_out; - output router_event_t T4_router_event; + input smartflit_chanel_t T4_chan_in; + output smartflit_chanel_t T4_chan_out; + output router_event_t T4_router_event; /******************* * T5 *******************/ - input smartflit_chanel_t T5_chan_in; - output smartflit_chanel_t T5_chan_out; - output router_event_t T5_router_event; + input smartflit_chanel_t T5_chan_in; + output smartflit_chanel_t T5_chan_out; + output router_event_t T5_router_event; /******************* * T6 *******************/ - input smartflit_chanel_t T6_chan_in; - output smartflit_chanel_t T6_chan_out; - output router_event_t T6_router_event; + input smartflit_chanel_t T6_chan_in; + output smartflit_chanel_t T6_chan_out; + output router_event_t T6_router_event; /******************* * T7 *******************/ - input smartflit_chanel_t T7_chan_in; - output smartflit_chanel_t T7_chan_out; - output router_event_t T7_router_event; + input smartflit_chanel_t T7_chan_in; + output smartflit_chanel_t T7_chan_out; + output router_event_t T7_router_event; /******************* * T8 *******************/ - input smartflit_chanel_t T8_chan_in; - output smartflit_chanel_t T8_chan_out; - output router_event_t T8_router_event; + input smartflit_chanel_t T8_chan_in; + output smartflit_chanel_t T8_chan_out; + output router_event_t T8_router_event; /******************* * T9 *******************/ - input smartflit_chanel_t T9_chan_in; - output smartflit_chanel_t T9_chan_out; - output router_event_t T9_router_event; + input smartflit_chanel_t T9_chan_in; + output smartflit_chanel_t T9_chan_out; + output router_event_t T9_router_event; /******************* * T10 *******************/ - input smartflit_chanel_t T10_chan_in; - output smartflit_chanel_t T10_chan_out; - output router_event_t T10_router_event; + input smartflit_chanel_t T10_chan_in; + output smartflit_chanel_t T10_chan_out; + output router_event_t T10_router_event; /******************* * T11 *******************/ - input smartflit_chanel_t T11_chan_in; - output smartflit_chanel_t T11_chan_out; - output router_event_t T11_router_event; + input smartflit_chanel_t T11_chan_in; + output smartflit_chanel_t T11_chan_out; + output router_event_t T11_router_event; /******************* * T12 *******************/ - input smartflit_chanel_t T12_chan_in; - output smartflit_chanel_t T12_chan_out; - output router_event_t T12_router_event; + input smartflit_chanel_t T12_chan_in; + output smartflit_chanel_t T12_chan_out; + output router_event_t T12_router_event; /******************* * T13 *******************/ - input smartflit_chanel_t T13_chan_in; - output smartflit_chanel_t T13_chan_out; - output router_event_t T13_router_event; + input smartflit_chanel_t T13_chan_in; + output smartflit_chanel_t T13_chan_out; + output router_event_t T13_router_event; /******************* * T14 *******************/ - input smartflit_chanel_t T14_chan_in; - output smartflit_chanel_t T14_chan_out; - output router_event_t T14_router_event; + input smartflit_chanel_t T14_chan_in; + output smartflit_chanel_t T14_chan_out; + output router_event_t T14_router_event; /******************* * T15 *******************/ - input smartflit_chanel_t T15_chan_in; - output smartflit_chanel_t T15_chan_out; - output router_event_t T15_router_event; + input smartflit_chanel_t T15_chan_in; + output smartflit_chanel_t T15_chan_out; + output router_event_t T15_router_event; /******************* * R0 *******************/ - wire R0_clk; - wire R0_reset; - - wire [RAw-1 : 0] R0_current_r_addr; - - smartflit_chanel_t R0_chan_in [3-1 : 0]; - smartflit_chanel_t R0_chan_out [3-1 : 0]; - router_event_t R0_router_event [3-1 : 0]; - + wire R0_clk; + wire R0_reset; + wire [RAw-1 : 0] R0_current_r_addr; + smartflit_chanel_t R0_chan_in [3-1 : 0]; + smartflit_chanel_t R0_chan_out [3-1 : 0]; + router_event_t R0_router_event [3-1 : 0]; /******************* * R1 *******************/ - wire R1_clk; - wire R1_reset; - - wire [RAw-1 : 0] R1_current_r_addr; - - smartflit_chanel_t R1_chan_in [3-1 : 0]; - smartflit_chanel_t R1_chan_out [3-1 : 0]; - router_event_t R1_router_event [3-1 : 0]; - + wire R1_clk; + wire R1_reset; + wire [RAw-1 : 0] R1_current_r_addr; + smartflit_chanel_t R1_chan_in [3-1 : 0]; + smartflit_chanel_t R1_chan_out [3-1 : 0]; + router_event_t R1_router_event [3-1 : 0]; /******************* * R2 *******************/ - wire R2_clk; - wire R2_reset; - - wire [RAw-1 : 0] R2_current_r_addr; - - smartflit_chanel_t R2_chan_in [3-1 : 0]; - smartflit_chanel_t R2_chan_out [3-1 : 0]; - router_event_t R2_router_event [3-1 : 0]; - + wire R2_clk; + wire R2_reset; + wire [RAw-1 : 0] R2_current_r_addr; + smartflit_chanel_t R2_chan_in [3-1 : 0]; + smartflit_chanel_t R2_chan_out [3-1 : 0]; + router_event_t R2_router_event [3-1 : 0]; /******************* * R3 *******************/ - wire R3_clk; - wire R3_reset; - - wire [RAw-1 : 0] R3_current_r_addr; - - smartflit_chanel_t R3_chan_in [3-1 : 0]; - smartflit_chanel_t R3_chan_out [3-1 : 0]; - router_event_t R3_router_event [3-1 : 0]; - + wire R3_clk; + wire R3_reset; + wire [RAw-1 : 0] R3_current_r_addr; + smartflit_chanel_t R3_chan_in [3-1 : 0]; + smartflit_chanel_t R3_chan_out [3-1 : 0]; + router_event_t R3_router_event [3-1 : 0]; /******************* * R4 *******************/ - wire R4_clk; - wire R4_reset; - - wire [RAw-1 : 0] R4_current_r_addr; - - smartflit_chanel_t R4_chan_in [4-1 : 0]; - smartflit_chanel_t R4_chan_out [4-1 : 0]; - router_event_t R4_router_event [4-1 : 0]; - + wire R4_clk; + wire R4_reset; + wire [RAw-1 : 0] R4_current_r_addr; + smartflit_chanel_t R4_chan_in [4-1 : 0]; + smartflit_chanel_t R4_chan_out [4-1 : 0]; + router_event_t R4_router_event [4-1 : 0]; /******************* * R5 *******************/ - wire R5_clk; - wire R5_reset; - - wire [RAw-1 : 0] R5_current_r_addr; - - smartflit_chanel_t R5_chan_in [4-1 : 0]; - smartflit_chanel_t R5_chan_out [4-1 : 0]; - router_event_t R5_router_event [4-1 : 0]; - + wire R5_clk; + wire R5_reset; + wire [RAw-1 : 0] R5_current_r_addr; + smartflit_chanel_t R5_chan_in [4-1 : 0]; + smartflit_chanel_t R5_chan_out [4-1 : 0]; + router_event_t R5_router_event [4-1 : 0]; /******************* * R6 *******************/ - wire R6_clk; - wire R6_reset; - - wire [RAw-1 : 0] R6_current_r_addr; - - smartflit_chanel_t R6_chan_in [4-1 : 0]; - smartflit_chanel_t R6_chan_out [4-1 : 0]; - router_event_t R6_router_event [4-1 : 0]; - + wire R6_clk; + wire R6_reset; + wire [RAw-1 : 0] R6_current_r_addr; + smartflit_chanel_t R6_chan_in [4-1 : 0]; + smartflit_chanel_t R6_chan_out [4-1 : 0]; + router_event_t R6_router_event [4-1 : 0]; /******************* * R7 *******************/ - wire R7_clk; - wire R7_reset; - - wire [RAw-1 : 0] R7_current_r_addr; - - smartflit_chanel_t R7_chan_in [4-1 : 0]; - smartflit_chanel_t R7_chan_out [4-1 : 0]; - router_event_t R7_router_event [4-1 : 0]; - + wire R7_clk; + wire R7_reset; + wire [RAw-1 : 0] R7_current_r_addr; + smartflit_chanel_t R7_chan_in [4-1 : 0]; + smartflit_chanel_t R7_chan_out [4-1 : 0]; + router_event_t R7_router_event [4-1 : 0]; /******************* * R12 *******************/ - wire R12_clk; - wire R12_reset; - - wire [RAw-1 : 0] R12_current_r_addr; - - smartflit_chanel_t R12_chan_in [4-1 : 0]; - smartflit_chanel_t R12_chan_out [4-1 : 0]; - router_event_t R12_router_event [4-1 : 0]; - + wire R12_clk; + wire R12_reset; + wire [RAw-1 : 0] R12_current_r_addr; + smartflit_chanel_t R12_chan_in [4-1 : 0]; + smartflit_chanel_t R12_chan_out [4-1 : 0]; + router_event_t R12_router_event [4-1 : 0]; /******************* * R13 *******************/ - wire R13_clk; - wire R13_reset; - - wire [RAw-1 : 0] R13_current_r_addr; - - smartflit_chanel_t R13_chan_in [4-1 : 0]; - smartflit_chanel_t R13_chan_out [4-1 : 0]; - router_event_t R13_router_event [4-1 : 0]; - + wire R13_clk; + wire R13_reset; + wire [RAw-1 : 0] R13_current_r_addr; + smartflit_chanel_t R13_chan_in [4-1 : 0]; + smartflit_chanel_t R13_chan_out [4-1 : 0]; + router_event_t R13_router_event [4-1 : 0]; /******************* * R14 *******************/ - wire R14_clk; - wire R14_reset; - - wire [RAw-1 : 0] R14_current_r_addr; - - smartflit_chanel_t R14_chan_in [4-1 : 0]; - smartflit_chanel_t R14_chan_out [4-1 : 0]; - router_event_t R14_router_event [4-1 : 0]; - + wire R14_clk; + wire R14_reset; + wire [RAw-1 : 0] R14_current_r_addr; + smartflit_chanel_t R14_chan_in [4-1 : 0]; + smartflit_chanel_t R14_chan_out [4-1 : 0]; + router_event_t R14_router_event [4-1 : 0]; /******************* * R15 *******************/ - wire R15_clk; - wire R15_reset; - - wire [RAw-1 : 0] R15_current_r_addr; - - smartflit_chanel_t R15_chan_in [4-1 : 0]; - smartflit_chanel_t R15_chan_out [4-1 : 0]; - router_event_t R15_router_event [4-1 : 0]; - + wire R15_clk; + wire R15_reset; + wire [RAw-1 : 0] R15_current_r_addr; + smartflit_chanel_t R15_chan_in [4-1 : 0]; + smartflit_chanel_t R15_chan_out [4-1 : 0]; + router_event_t R15_router_event [4-1 : 0]; /******************* * R8 *******************/ - wire R8_clk; - wire R8_reset; - - wire [RAw-1 : 0] R8_current_r_addr; - - smartflit_chanel_t R8_chan_in [5-1 : 0]; - smartflit_chanel_t R8_chan_out [5-1 : 0]; - router_event_t R8_router_event [5-1 : 0]; - + wire R8_clk; + wire R8_reset; + wire [RAw-1 : 0] R8_current_r_addr; + smartflit_chanel_t R8_chan_in [5-1 : 0]; + smartflit_chanel_t R8_chan_out [5-1 : 0]; + router_event_t R8_router_event [5-1 : 0]; /******************* * R9 *******************/ - wire R9_clk; - wire R9_reset; - - wire [RAw-1 : 0] R9_current_r_addr; - - smartflit_chanel_t R9_chan_in [5-1 : 0]; - smartflit_chanel_t R9_chan_out [5-1 : 0]; - router_event_t R9_router_event [5-1 : 0]; - + wire R9_clk; + wire R9_reset; + wire [RAw-1 : 0] R9_current_r_addr; + smartflit_chanel_t R9_chan_in [5-1 : 0]; + smartflit_chanel_t R9_chan_out [5-1 : 0]; + router_event_t R9_router_event [5-1 : 0]; /******************* * R10 *******************/ - wire R10_clk; - wire R10_reset; - - wire [RAw-1 : 0] R10_current_r_addr; - - smartflit_chanel_t R10_chan_in [5-1 : 0]; - smartflit_chanel_t R10_chan_out [5-1 : 0]; - router_event_t R10_router_event [5-1 : 0]; - + wire R10_clk; + wire R10_reset; + wire [RAw-1 : 0] R10_current_r_addr; + smartflit_chanel_t R10_chan_in [5-1 : 0]; + smartflit_chanel_t R10_chan_out [5-1 : 0]; + router_event_t R10_router_event [5-1 : 0]; /******************* * R11 *******************/ - wire R11_clk; - wire R11_reset; - - wire [RAw-1 : 0] R11_current_r_addr; - - smartflit_chanel_t R11_chan_in [5-1 : 0]; - smartflit_chanel_t R11_chan_out [5-1 : 0]; - router_event_t R11_router_event [5-1 : 0]; - + wire R11_clk; + wire R11_reset; + wire [RAw-1 : 0] R11_current_r_addr; + smartflit_chanel_t R11_chan_in [5-1 : 0]; + smartflit_chanel_t R11_chan_out [5-1 : 0]; + router_event_t R11_router_event [5-1 : 0]; @@ -445,17 +395,17 @@ module custom1_noc .router_event (R0_router_event) ); - assign R0_clk = clk; - assign R0_reset = reset; - assign R0_current_r_addr = 0; -//Connect R0 port 0 to T0 port 0 - assign R0_chan_in [0] = T0_chan_in; - assign T0_chan_out = R0_chan_out [0]; - assign T0_router_event = R0_router_event [0]; -//Connect R0 port 1 to R14 port 3 - assign R0_chan_in [1] = R14_chan_out [3]; -//Connect R0 port 2 to R13 port 3 - assign R0_chan_in [2] = R13_chan_out [3]; + assign R0_clk = clk; + assign R0_reset = reset; + assign R0_current_r_addr = 0; + //Connect R0 port 0 to T0 port 0 + assign R0_chan_in [0] = T0_chan_in; + assign T0_chan_out = R0_chan_out [0]; + assign T0_router_event = R0_router_event [0]; + //Connect R0 port 1 to R14 port 3 + assign R0_chan_in [1] = R14_chan_out [3]; + //Connect R0 port 2 to R13 port 3 + assign R0_chan_in [2] = R13_chan_out [3]; /******************* * R1 @@ -474,17 +424,17 @@ module custom1_noc .router_event (R1_router_event) ); - assign R1_clk = clk; - assign R1_reset = reset; - assign R1_current_r_addr = 1; -//Connect R1 port 0 to T1 port 0 - assign R1_chan_in [0] = T1_chan_in; - assign T1_chan_out = R1_chan_out [0]; - assign T1_router_event = R1_router_event [0]; -//Connect R1 port 1 to R7 port 3 - assign R1_chan_in [1] = R7_chan_out [3]; -//Connect R1 port 2 to R2 port 2 - assign R1_chan_in [2] = R2_chan_out [2]; + assign R1_clk = clk; + assign R1_reset = reset; + assign R1_current_r_addr = 1; + //Connect R1 port 0 to T1 port 0 + assign R1_chan_in [0] = T1_chan_in; + assign T1_chan_out = R1_chan_out [0]; + assign T1_router_event = R1_router_event [0]; + //Connect R1 port 1 to R7 port 3 + assign R1_chan_in [1] = R7_chan_out [3]; + //Connect R1 port 2 to R2 port 2 + assign R1_chan_in [2] = R2_chan_out [2]; /******************* * R2 @@ -503,17 +453,17 @@ module custom1_noc .router_event (R2_router_event) ); - assign R2_clk = clk; - assign R2_reset = reset; - assign R2_current_r_addr = 2; -//Connect R2 port 0 to T2 port 0 - assign R2_chan_in [0] = T2_chan_in; - assign T2_chan_out = R2_chan_out [0]; - assign T2_router_event = R2_router_event [0]; -//Connect R2 port 1 to R15 port 2 - assign R2_chan_in [1] = R15_chan_out [2]; -//Connect R2 port 2 to R1 port 2 - assign R2_chan_in [2] = R1_chan_out [2]; + assign R2_clk = clk; + assign R2_reset = reset; + assign R2_current_r_addr = 2; + //Connect R2 port 0 to T2 port 0 + assign R2_chan_in [0] = T2_chan_in; + assign T2_chan_out = R2_chan_out [0]; + assign T2_router_event = R2_router_event [0]; + //Connect R2 port 1 to R15 port 2 + assign R2_chan_in [1] = R15_chan_out [2]; + //Connect R2 port 2 to R1 port 2 + assign R2_chan_in [2] = R1_chan_out [2]; /******************* * R3 @@ -532,17 +482,17 @@ module custom1_noc .router_event (R3_router_event) ); - assign R3_clk = clk; - assign R3_reset = reset; - assign R3_current_r_addr = 3; -//Connect R3 port 0 to T3 port 0 - assign R3_chan_in [0] = T3_chan_in; - assign T3_chan_out = R3_chan_out [0]; - assign T3_router_event = R3_router_event [0]; -//Connect R3 port 1 to R15 port 3 - assign R3_chan_in [1] = R15_chan_out [3]; -//Connect R3 port 2 to R4 port 2 - assign R3_chan_in [2] = R4_chan_out [2]; + assign R3_clk = clk; + assign R3_reset = reset; + assign R3_current_r_addr = 3; + //Connect R3 port 0 to T3 port 0 + assign R3_chan_in [0] = T3_chan_in; + assign T3_chan_out = R3_chan_out [0]; + assign T3_router_event = R3_router_event [0]; + //Connect R3 port 1 to R15 port 3 + assign R3_chan_in [1] = R15_chan_out [3]; + //Connect R3 port 2 to R4 port 2 + assign R3_chan_in [2] = R4_chan_out [2]; /******************* * R4 @@ -561,19 +511,19 @@ module custom1_noc .router_event (R4_router_event) ); - assign R4_clk = clk; - assign R4_reset = reset; - assign R4_current_r_addr = 4; -//Connect R4 port 0 to T4 port 0 - assign R4_chan_in [0] = T4_chan_in; - assign T4_chan_out = R4_chan_out [0]; - assign T4_router_event = R4_router_event [0]; -//Connect R4 port 1 to R9 port 2 - assign R4_chan_in [1] = R9_chan_out [2]; -//Connect R4 port 2 to R3 port 2 - assign R4_chan_in [2] = R3_chan_out [2]; -//Connect R4 port 3 to R6 port 3 - assign R4_chan_in [3] = R6_chan_out [3]; + assign R4_clk = clk; + assign R4_reset = reset; + assign R4_current_r_addr = 4; + //Connect R4 port 0 to T4 port 0 + assign R4_chan_in [0] = T4_chan_in; + assign T4_chan_out = R4_chan_out [0]; + assign T4_router_event = R4_router_event [0]; + //Connect R4 port 1 to R9 port 2 + assign R4_chan_in [1] = R9_chan_out [2]; + //Connect R4 port 2 to R3 port 2 + assign R4_chan_in [2] = R3_chan_out [2]; + //Connect R4 port 3 to R6 port 3 + assign R4_chan_in [3] = R6_chan_out [3]; /******************* * R5 @@ -592,19 +542,19 @@ module custom1_noc .router_event (R5_router_event) ); - assign R5_clk = clk; - assign R5_reset = reset; - assign R5_current_r_addr = 5; -//Connect R5 port 0 to T5 port 0 - assign R5_chan_in [0] = T5_chan_in; - assign T5_chan_out = R5_chan_out [0]; - assign T5_router_event = R5_router_event [0]; -//Connect R5 port 1 to R11 port 4 - assign R5_chan_in [1] = R11_chan_out [4]; -//Connect R5 port 2 to R6 port 2 - assign R5_chan_in [2] = R6_chan_out [2]; -//Connect R5 port 3 to R13 port 2 - assign R5_chan_in [3] = R13_chan_out [2]; + assign R5_clk = clk; + assign R5_reset = reset; + assign R5_current_r_addr = 5; + //Connect R5 port 0 to T5 port 0 + assign R5_chan_in [0] = T5_chan_in; + assign T5_chan_out = R5_chan_out [0]; + assign T5_router_event = R5_router_event [0]; + //Connect R5 port 1 to R11 port 4 + assign R5_chan_in [1] = R11_chan_out [4]; + //Connect R5 port 2 to R6 port 2 + assign R5_chan_in [2] = R6_chan_out [2]; + //Connect R5 port 3 to R13 port 2 + assign R5_chan_in [3] = R13_chan_out [2]; /******************* * R6 @@ -623,19 +573,19 @@ module custom1_noc .router_event (R6_router_event) ); - assign R6_clk = clk; - assign R6_reset = reset; - assign R6_current_r_addr = 6; -//Connect R6 port 0 to T6 port 0 - assign R6_chan_in [0] = T6_chan_in; - assign T6_chan_out = R6_chan_out [0]; - assign T6_router_event = R6_router_event [0]; -//Connect R6 port 1 to R9 port 3 - assign R6_chan_in [1] = R9_chan_out [3]; -//Connect R6 port 2 to R5 port 2 - assign R6_chan_in [2] = R5_chan_out [2]; -//Connect R6 port 3 to R4 port 3 - assign R6_chan_in [3] = R4_chan_out [3]; + assign R6_clk = clk; + assign R6_reset = reset; + assign R6_current_r_addr = 6; + //Connect R6 port 0 to T6 port 0 + assign R6_chan_in [0] = T6_chan_in; + assign T6_chan_out = R6_chan_out [0]; + assign T6_router_event = R6_router_event [0]; + //Connect R6 port 1 to R9 port 3 + assign R6_chan_in [1] = R9_chan_out [3]; + //Connect R6 port 2 to R5 port 2 + assign R6_chan_in [2] = R5_chan_out [2]; + //Connect R6 port 3 to R4 port 3 + assign R6_chan_in [3] = R4_chan_out [3]; /******************* * R7 @@ -654,19 +604,19 @@ module custom1_noc .router_event (R7_router_event) ); - assign R7_clk = clk; - assign R7_reset = reset; - assign R7_current_r_addr = 7; -//Connect R7 port 0 to T7 port 0 - assign R7_chan_in [0] = T7_chan_in; - assign T7_chan_out = R7_chan_out [0]; - assign T7_router_event = R7_router_event [0]; -//Connect R7 port 1 to R12 port 3 - assign R7_chan_in [1] = R12_chan_out [3]; -//Connect R7 port 2 to R14 port 2 - assign R7_chan_in [2] = R14_chan_out [2]; -//Connect R7 port 3 to R1 port 1 - assign R7_chan_in [3] = R1_chan_out [1]; + assign R7_clk = clk; + assign R7_reset = reset; + assign R7_current_r_addr = 7; + //Connect R7 port 0 to T7 port 0 + assign R7_chan_in [0] = T7_chan_in; + assign T7_chan_out = R7_chan_out [0]; + assign T7_router_event = R7_router_event [0]; + //Connect R7 port 1 to R12 port 3 + assign R7_chan_in [1] = R12_chan_out [3]; + //Connect R7 port 2 to R14 port 2 + assign R7_chan_in [2] = R14_chan_out [2]; + //Connect R7 port 3 to R1 port 1 + assign R7_chan_in [3] = R1_chan_out [1]; /******************* * R12 @@ -685,19 +635,19 @@ module custom1_noc .router_event (R12_router_event) ); - assign R12_clk = clk; - assign R12_reset = reset; - assign R12_current_r_addr = 8; -//Connect R12 port 0 to T8 port 0 - assign R12_chan_in [0] = T8_chan_in; - assign T8_chan_out = R12_chan_out [0]; - assign T8_router_event = R12_router_event [0]; -//Connect R12 port 1 to R8 port 4 - assign R12_chan_in [1] = R8_chan_out [4]; -//Connect R12 port 2 to R10 port 3 - assign R12_chan_in [2] = R10_chan_out [3]; -//Connect R12 port 3 to R7 port 1 - assign R12_chan_in [3] = R7_chan_out [1]; + assign R12_clk = clk; + assign R12_reset = reset; + assign R12_current_r_addr = 8; + //Connect R12 port 0 to T8 port 0 + assign R12_chan_in [0] = T8_chan_in; + assign T8_chan_out = R12_chan_out [0]; + assign T8_router_event = R12_router_event [0]; + //Connect R12 port 1 to R8 port 4 + assign R12_chan_in [1] = R8_chan_out [4]; + //Connect R12 port 2 to R10 port 3 + assign R12_chan_in [2] = R10_chan_out [3]; + //Connect R12 port 3 to R7 port 1 + assign R12_chan_in [3] = R7_chan_out [1]; /******************* * R13 @@ -716,19 +666,19 @@ module custom1_noc .router_event (R13_router_event) ); - assign R13_clk = clk; - assign R13_reset = reset; - assign R13_current_r_addr = 9; -//Connect R13 port 0 to T9 port 0 - assign R13_chan_in [0] = T9_chan_in; - assign T9_chan_out = R13_chan_out [0]; - assign T9_router_event = R13_router_event [0]; -//Connect R13 port 1 to R8 port 2 - assign R13_chan_in [1] = R8_chan_out [2]; -//Connect R13 port 2 to R5 port 3 - assign R13_chan_in [2] = R5_chan_out [3]; -//Connect R13 port 3 to R0 port 2 - assign R13_chan_in [3] = R0_chan_out [2]; + assign R13_clk = clk; + assign R13_reset = reset; + assign R13_current_r_addr = 9; + //Connect R13 port 0 to T9 port 0 + assign R13_chan_in [0] = T9_chan_in; + assign T9_chan_out = R13_chan_out [0]; + assign T9_router_event = R13_router_event [0]; + //Connect R13 port 1 to R8 port 2 + assign R13_chan_in [1] = R8_chan_out [2]; + //Connect R13 port 2 to R5 port 3 + assign R13_chan_in [2] = R5_chan_out [3]; + //Connect R13 port 3 to R0 port 2 + assign R13_chan_in [3] = R0_chan_out [2]; /******************* * R14 @@ -747,19 +697,19 @@ module custom1_noc .router_event (R14_router_event) ); - assign R14_clk = clk; - assign R14_reset = reset; - assign R14_current_r_addr = 10; -//Connect R14 port 0 to T10 port 0 - assign R14_chan_in [0] = T10_chan_in; - assign T10_chan_out = R14_chan_out [0]; - assign T10_router_event = R14_router_event [0]; -//Connect R14 port 1 to R8 port 3 - assign R14_chan_in [1] = R8_chan_out [3]; -//Connect R14 port 2 to R7 port 2 - assign R14_chan_in [2] = R7_chan_out [2]; -//Connect R14 port 3 to R0 port 1 - assign R14_chan_in [3] = R0_chan_out [1]; + assign R14_clk = clk; + assign R14_reset = reset; + assign R14_current_r_addr = 10; + //Connect R14 port 0 to T10 port 0 + assign R14_chan_in [0] = T10_chan_in; + assign T10_chan_out = R14_chan_out [0]; + assign T10_router_event = R14_router_event [0]; + //Connect R14 port 1 to R8 port 3 + assign R14_chan_in [1] = R8_chan_out [3]; + //Connect R14 port 2 to R7 port 2 + assign R14_chan_in [2] = R7_chan_out [2]; + //Connect R14 port 3 to R0 port 1 + assign R14_chan_in [3] = R0_chan_out [1]; /******************* * R15 @@ -778,19 +728,19 @@ module custom1_noc .router_event (R15_router_event) ); - assign R15_clk = clk; - assign R15_reset = reset; - assign R15_current_r_addr = 11; -//Connect R15 port 0 to T11 port 0 - assign R15_chan_in [0] = T11_chan_in; - assign T11_chan_out = R15_chan_out [0]; - assign T11_router_event = R15_router_event [0]; -//Connect R15 port 1 to R10 port 4 - assign R15_chan_in [1] = R10_chan_out [4]; -//Connect R15 port 2 to R2 port 1 - assign R15_chan_in [2] = R2_chan_out [1]; -//Connect R15 port 3 to R3 port 1 - assign R15_chan_in [3] = R3_chan_out [1]; + assign R15_clk = clk; + assign R15_reset = reset; + assign R15_current_r_addr = 11; + //Connect R15 port 0 to T11 port 0 + assign R15_chan_in [0] = T11_chan_in; + assign T11_chan_out = R15_chan_out [0]; + assign T11_router_event = R15_router_event [0]; + //Connect R15 port 1 to R10 port 4 + assign R15_chan_in [1] = R10_chan_out [4]; + //Connect R15 port 2 to R2 port 1 + assign R15_chan_in [2] = R2_chan_out [1]; + //Connect R15 port 3 to R3 port 1 + assign R15_chan_in [3] = R3_chan_out [1]; /******************* * R8 @@ -809,21 +759,21 @@ module custom1_noc .router_event (R8_router_event) ); - assign R8_clk = clk; - assign R8_reset = reset; - assign R8_current_r_addr = 12; -//Connect R8 port 0 to T12 port 0 - assign R8_chan_in [0] = T12_chan_in; - assign T12_chan_out = R8_chan_out [0]; - assign T12_router_event = R8_router_event [0]; -//Connect R8 port 1 to R11 port 1 - assign R8_chan_in [1] = R11_chan_out [1]; -//Connect R8 port 2 to R13 port 1 - assign R8_chan_in [2] = R13_chan_out [1]; -//Connect R8 port 3 to R14 port 1 - assign R8_chan_in [3] = R14_chan_out [1]; -//Connect R8 port 4 to R12 port 1 - assign R8_chan_in [4] = R12_chan_out [1]; + assign R8_clk = clk; + assign R8_reset = reset; + assign R8_current_r_addr = 12; + //Connect R8 port 0 to T12 port 0 + assign R8_chan_in [0] = T12_chan_in; + assign T12_chan_out = R8_chan_out [0]; + assign T12_router_event = R8_router_event [0]; + //Connect R8 port 1 to R11 port 1 + assign R8_chan_in [1] = R11_chan_out [1]; + //Connect R8 port 2 to R13 port 1 + assign R8_chan_in [2] = R13_chan_out [1]; + //Connect R8 port 3 to R14 port 1 + assign R8_chan_in [3] = R14_chan_out [1]; + //Connect R8 port 4 to R12 port 1 + assign R8_chan_in [4] = R12_chan_out [1]; /******************* * R9 @@ -842,21 +792,21 @@ module custom1_noc .router_event (R9_router_event) ); - assign R9_clk = clk; - assign R9_reset = reset; - assign R9_current_r_addr = 13; -//Connect R9 port 0 to T13 port 0 - assign R9_chan_in [0] = T13_chan_in; - assign T13_chan_out = R9_chan_out [0]; - assign T13_router_event = R9_router_event [0]; -//Connect R9 port 1 to R11 port 3 - assign R9_chan_in [1] = R11_chan_out [3]; -//Connect R9 port 2 to R4 port 1 - assign R9_chan_in [2] = R4_chan_out [1]; -//Connect R9 port 3 to R6 port 1 - assign R9_chan_in [3] = R6_chan_out [1]; -//Connect R9 port 4 to R10 port 2 - assign R9_chan_in [4] = R10_chan_out [2]; + assign R9_clk = clk; + assign R9_reset = reset; + assign R9_current_r_addr = 13; + //Connect R9 port 0 to T13 port 0 + assign R9_chan_in [0] = T13_chan_in; + assign T13_chan_out = R9_chan_out [0]; + assign T13_router_event = R9_router_event [0]; + //Connect R9 port 1 to R11 port 3 + assign R9_chan_in [1] = R11_chan_out [3]; + //Connect R9 port 2 to R4 port 1 + assign R9_chan_in [2] = R4_chan_out [1]; + //Connect R9 port 3 to R6 port 1 + assign R9_chan_in [3] = R6_chan_out [1]; + //Connect R9 port 4 to R10 port 2 + assign R9_chan_in [4] = R10_chan_out [2]; /******************* * R10 @@ -875,21 +825,21 @@ module custom1_noc .router_event (R10_router_event) ); - assign R10_clk = clk; - assign R10_reset = reset; - assign R10_current_r_addr = 14; -//Connect R10 port 0 to T14 port 0 - assign R10_chan_in [0] = T14_chan_in; - assign T14_chan_out = R10_chan_out [0]; - assign T14_router_event = R10_router_event [0]; -//Connect R10 port 1 to R11 port 2 - assign R10_chan_in [1] = R11_chan_out [2]; -//Connect R10 port 2 to R9 port 4 - assign R10_chan_in [2] = R9_chan_out [4]; -//Connect R10 port 3 to R12 port 2 - assign R10_chan_in [3] = R12_chan_out [2]; -//Connect R10 port 4 to R15 port 1 - assign R10_chan_in [4] = R15_chan_out [1]; + assign R10_clk = clk; + assign R10_reset = reset; + assign R10_current_r_addr = 14; + //Connect R10 port 0 to T14 port 0 + assign R10_chan_in [0] = T14_chan_in; + assign T14_chan_out = R10_chan_out [0]; + assign T14_router_event = R10_router_event [0]; + //Connect R10 port 1 to R11 port 2 + assign R10_chan_in [1] = R11_chan_out [2]; + //Connect R10 port 2 to R9 port 4 + assign R10_chan_in [2] = R9_chan_out [4]; + //Connect R10 port 3 to R12 port 2 + assign R10_chan_in [3] = R12_chan_out [2]; + //Connect R10 port 4 to R15 port 1 + assign R10_chan_in [4] = R15_chan_out [1]; /******************* * R11 @@ -908,23 +858,23 @@ module custom1_noc .router_event (R11_router_event) ); - assign R11_clk = clk; - assign R11_reset = reset; - assign R11_current_r_addr = 15; -//Connect R11 port 0 to T15 port 0 - assign R11_chan_in [0] = T15_chan_in; - assign T15_chan_out = R11_chan_out [0]; - assign T15_router_event = R11_router_event [0]; -//Connect R11 port 1 to R8 port 1 - assign R11_chan_in [1] = R8_chan_out [1]; -//Connect R11 port 2 to R10 port 1 - assign R11_chan_in [2] = R10_chan_out [1]; -//Connect R11 port 3 to R9 port 1 - assign R11_chan_in [3] = R9_chan_out [1]; -//Connect R11 port 4 to R5 port 1 - assign R11_chan_in [4] = R5_chan_out [1]; + assign R11_clk = clk; + assign R11_reset = reset; + assign R11_current_r_addr = 15; + //Connect R11 port 0 to T15 port 0 + assign R11_chan_in [0] = T15_chan_in; + assign T15_chan_out = R11_chan_out [0]; + assign T15_router_event = R11_router_event [0]; + //Connect R11 port 1 to R8 port 1 + assign R11_chan_in [1] = R8_chan_out [1]; + //Connect R11 port 2 to R10 port 1 + assign R11_chan_in [2] = R10_chan_out [1]; + //Connect R11 port 3 to R9 port 1 + assign R11_chan_in [3] = R9_chan_out [1]; + //Connect R11 port 4 to R5 port 1 + assign R11_chan_in [4] = R5_chan_out [1]; - + endmodule diff --git a/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv b/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv index 2ead929..cf5599f 100644 --- a/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv +++ b/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv @@ -1,288 +1,261 @@ /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/ /********************************************************************** -** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv +** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv ** -** Copyright (C) 2014-2022 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.2.0 +** This file is part of ProNoC 2.2.0 ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ `include "pronoc_def.v" -module custom1_noc_genvar +module custom1_noc_genvar #( parameter NOC_ID=0 )( - reset, clk, chan_in_all, chan_out_all, router_event ); - `NOC_CONF - - - input reset; - input clk; - input smartflit_chanel_t chan_in_all [NE-1 : 0]; - output smartflit_chanel_t chan_out_all [NE-1 : 0]; - -//Events - output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; - -//all routers port - smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; - smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; - - - wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; - - - + input reset; + input clk; + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; + + //Events + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; + //all routers port + smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; + smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; + wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; - genvar i; generate - for( i=0; i<4; i=i+1) begin : router_3_port_lp - localparam RID = i; - assign current_r_addr [RID] = RID[RAw-1: 0]; + for( i=0; i<4; i=i+1) begin : router_3_port_lp + localparam RID = i; + assign current_r_addr [RID] = RID[RAw-1: 0]; + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P(3) + ) router_3_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr[RID]), + .chan_in (router_chan_in [RID] [2 : 0]), + .chan_out (router_chan_out[RID] [2 : 0]), + .router_event(router_event[RID] [2 : 0]) + ); + end - router_top #( - .NOC_ID(NOC_ID), - .ROUTER_ID(RID), - .P(3) - ) router_3_port ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr[RID]), - .chan_in (router_chan_in [RID] [2 : 0]), - .chan_out (router_chan_out[RID] [2 : 0]), - .router_event(router_event[RID] [2 : 0]) - ); - - - - end - - for( i=0; i<8; i=i+1) begin : router_4_port_lp - localparam RID = i+4; - assign current_r_addr [RID] = RID[RAw-1: 0]; - - router_top #( - .NOC_ID(NOC_ID), - .ROUTER_ID(RID), - .P(4) - ) router_4_port ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr[RID]), - .chan_in (router_chan_in [RID] [3 : 0]), - .chan_out (router_chan_out[RID] [3 : 0]), - .router_event(router_event[RID] [3 : 0]) - ); - - - - end - - for( i=0; i<4; i=i+1) begin : router_5_port_lp - localparam RID = i+12; - assign current_r_addr [RID] = RID[RAw-1: 0]; + for( i=0; i<8; i=i+1) begin : router_4_port_lp + localparam RID = i+4; + assign current_r_addr [RID] = RID[RAw-1: 0]; + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P(4) + ) router_4_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr[RID]), + .chan_in (router_chan_in [RID] [3 : 0]), + .chan_out (router_chan_out[RID] [3 : 0]), + .router_event(router_event[RID] [3 : 0]) + ); + end - router_top #( - .NOC_ID(NOC_ID), - .ROUTER_ID(RID), - .P(5) - ) router_5_port ( - .clk(clk), - .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr[RID]), - .chan_in (router_chan_in [RID] [4 : 0]), - .chan_out (router_chan_out[RID] [4 : 0]), - .router_event(router_event[RID] [4 : 0]) - ); - - - - end - endgenerate - - -//Connect R0 input ports 0 to T0 output ports 0 - assign router_chan_in [0][0] = chan_in_all [0]; - assign chan_out_all [0] = router_chan_out [0][0]; -//Connect R0 input ports 1 to R14 output ports 3 - assign router_chan_in [0][1] = router_chan_out [10][3]; -//Connect R0 input ports 2 to R13 output ports 3 - assign router_chan_in [0][2] = router_chan_out [9][3]; -//Connect R1 input ports 0 to T1 output ports 0 - assign router_chan_in [1][0] = chan_in_all [1]; - assign chan_out_all [1] = router_chan_out [1][0]; -//Connect R1 input ports 1 to R7 output ports 3 - assign router_chan_in [1][1] = router_chan_out [7][3]; -//Connect R1 input ports 2 to R2 output ports 2 - assign router_chan_in [1][2] = router_chan_out [2][2]; -//Connect R2 input ports 0 to T2 output ports 0 - assign router_chan_in [2][0] = chan_in_all [2]; - assign chan_out_all [2] = router_chan_out [2][0]; -//Connect R2 input ports 1 to R15 output ports 2 - assign router_chan_in [2][1] = router_chan_out [11][2]; -//Connect R2 input ports 2 to R1 output ports 2 - assign router_chan_in [2][2] = router_chan_out [1][2]; -//Connect R3 input ports 0 to T3 output ports 0 - assign router_chan_in [3][0] = chan_in_all [3]; - assign chan_out_all [3] = router_chan_out [3][0]; -//Connect R3 input ports 1 to R15 output ports 3 - assign router_chan_in [3][1] = router_chan_out [11][3]; -//Connect R3 input ports 2 to R4 output ports 2 - assign router_chan_in [3][2] = router_chan_out [4][2]; -//Connect R4 input ports 0 to T4 output ports 0 - assign router_chan_in [4][0] = chan_in_all [4]; - assign chan_out_all [4] = router_chan_out [4][0]; -//Connect R4 input ports 1 to R9 output ports 2 - assign router_chan_in [4][1] = router_chan_out [13][2]; -//Connect R4 input ports 2 to R3 output ports 2 - assign router_chan_in [4][2] = router_chan_out [3][2]; -//Connect R4 input ports 3 to R6 output ports 3 - assign router_chan_in [4][3] = router_chan_out [6][3]; -//Connect R5 input ports 0 to T5 output ports 0 - assign router_chan_in [5][0] = chan_in_all [5]; - assign chan_out_all [5] = router_chan_out [5][0]; -//Connect R5 input ports 1 to R11 output ports 4 - assign router_chan_in [5][1] = router_chan_out [15][4]; -//Connect R5 input ports 2 to R6 output ports 2 - assign router_chan_in [5][2] = router_chan_out [6][2]; -//Connect R5 input ports 3 to R13 output ports 2 - assign router_chan_in [5][3] = router_chan_out [9][2]; -//Connect R6 input ports 0 to T6 output ports 0 - assign router_chan_in [6][0] = chan_in_all [6]; - assign chan_out_all [6] = router_chan_out [6][0]; -//Connect R6 input ports 1 to R9 output ports 3 - assign router_chan_in [6][1] = router_chan_out [13][3]; -//Connect R6 input ports 2 to R5 output ports 2 - assign router_chan_in [6][2] = router_chan_out [5][2]; -//Connect R6 input ports 3 to R4 output ports 3 - assign router_chan_in [6][3] = router_chan_out [4][3]; -//Connect R7 input ports 0 to T7 output ports 0 - assign router_chan_in [7][0] = chan_in_all [7]; - assign chan_out_all [7] = router_chan_out [7][0]; -//Connect R7 input ports 1 to R12 output ports 3 - assign router_chan_in [7][1] = router_chan_out [8][3]; -//Connect R7 input ports 2 to R14 output ports 2 - assign router_chan_in [7][2] = router_chan_out [10][2]; -//Connect R7 input ports 3 to R1 output ports 1 - assign router_chan_in [7][3] = router_chan_out [1][1]; -//Connect R12 input ports 0 to T8 output ports 0 - assign router_chan_in [8][0] = chan_in_all [8]; - assign chan_out_all [8] = router_chan_out [8][0]; -//Connect R12 input ports 1 to R8 output ports 4 - assign router_chan_in [8][1] = router_chan_out [12][4]; -//Connect R12 input ports 2 to R10 output ports 3 - assign router_chan_in [8][2] = router_chan_out [14][3]; -//Connect R12 input ports 3 to R7 output ports 1 - assign router_chan_in [8][3] = router_chan_out [7][1]; -//Connect R13 input ports 0 to T9 output ports 0 - assign router_chan_in [9][0] = chan_in_all [9]; - assign chan_out_all [9] = router_chan_out [9][0]; -//Connect R13 input ports 1 to R8 output ports 2 - assign router_chan_in [9][1] = router_chan_out [12][2]; -//Connect R13 input ports 2 to R5 output ports 3 - assign router_chan_in [9][2] = router_chan_out [5][3]; -//Connect R13 input ports 3 to R0 output ports 2 - assign router_chan_in [9][3] = router_chan_out [0][2]; -//Connect R14 input ports 0 to T10 output ports 0 - assign router_chan_in [10][0] = chan_in_all [10]; - assign chan_out_all [10] = router_chan_out [10][0]; -//Connect R14 input ports 1 to R8 output ports 3 - assign router_chan_in [10][1] = router_chan_out [12][3]; -//Connect R14 input ports 2 to R7 output ports 2 - assign router_chan_in [10][2] = router_chan_out [7][2]; -//Connect R14 input ports 3 to R0 output ports 1 - assign router_chan_in [10][3] = router_chan_out [0][1]; -//Connect R15 input ports 0 to T11 output ports 0 - assign router_chan_in [11][0] = chan_in_all [11]; - assign chan_out_all [11] = router_chan_out [11][0]; -//Connect R15 input ports 1 to R10 output ports 4 - assign router_chan_in [11][1] = router_chan_out [14][4]; -//Connect R15 input ports 2 to R2 output ports 1 - assign router_chan_in [11][2] = router_chan_out [2][1]; -//Connect R15 input ports 3 to R3 output ports 1 - assign router_chan_in [11][3] = router_chan_out [3][1]; -//Connect R8 input ports 0 to T12 output ports 0 - assign router_chan_in [12][0] = chan_in_all [12]; - assign chan_out_all [12] = router_chan_out [12][0]; -//Connect R8 input ports 1 to R11 output ports 1 - assign router_chan_in [12][1] = router_chan_out [15][1]; -//Connect R8 input ports 2 to R13 output ports 1 - assign router_chan_in [12][2] = router_chan_out [9][1]; -//Connect R8 input ports 3 to R14 output ports 1 - assign router_chan_in [12][3] = router_chan_out [10][1]; -//Connect R8 input ports 4 to R12 output ports 1 - assign router_chan_in [12][4] = router_chan_out [8][1]; -//Connect R9 input ports 0 to T13 output ports 0 - assign router_chan_in [13][0] = chan_in_all [13]; - assign chan_out_all [13] = router_chan_out [13][0]; -//Connect R9 input ports 1 to R11 output ports 3 - assign router_chan_in [13][1] = router_chan_out [15][3]; -//Connect R9 input ports 2 to R4 output ports 1 - assign router_chan_in [13][2] = router_chan_out [4][1]; -//Connect R9 input ports 3 to R6 output ports 1 - assign router_chan_in [13][3] = router_chan_out [6][1]; -//Connect R9 input ports 4 to R10 output ports 2 - assign router_chan_in [13][4] = router_chan_out [14][2]; -//Connect R10 input ports 0 to T14 output ports 0 - assign router_chan_in [14][0] = chan_in_all [14]; - assign chan_out_all [14] = router_chan_out [14][0]; -//Connect R10 input ports 1 to R11 output ports 2 - assign router_chan_in [14][1] = router_chan_out [15][2]; -//Connect R10 input ports 2 to R9 output ports 4 - assign router_chan_in [14][2] = router_chan_out [13][4]; -//Connect R10 input ports 3 to R12 output ports 2 - assign router_chan_in [14][3] = router_chan_out [8][2]; -//Connect R10 input ports 4 to R15 output ports 1 - assign router_chan_in [14][4] = router_chan_out [11][1]; -//Connect R11 input ports 0 to T15 output ports 0 - assign router_chan_in [15][0] = chan_in_all [15]; - assign chan_out_all [15] = router_chan_out [15][0]; -//Connect R11 input ports 1 to R8 output ports 1 - assign router_chan_in [15][1] = router_chan_out [12][1]; -//Connect R11 input ports 2 to R10 output ports 1 - assign router_chan_in [15][2] = router_chan_out [14][1]; -//Connect R11 input ports 3 to R9 output ports 1 - assign router_chan_in [15][3] = router_chan_out [13][1]; -//Connect R11 input ports 4 to R5 output ports 1 - assign router_chan_in [15][4] = router_chan_out [5][1]; - + for( i=0; i<4; i=i+1) begin : router_5_port_lp + localparam RID = i+12; + assign current_r_addr [RID] = RID[RAw-1: 0]; + router_top #( + .NOC_ID(NOC_ID), + .ROUTER_ID(RID), + .P(5) + ) router_5_port ( + .clk(clk), + .reset(reset), + .current_r_id(RID), + .current_r_addr(current_r_addr[RID]), + .chan_in (router_chan_in [RID] [4 : 0]), + .chan_out (router_chan_out[RID] [4 : 0]), + .router_event(router_event[RID] [4 : 0]) + ); + end +endgenerate + //Connect R0 input ports 0 to T0 output ports 0 + assign router_chan_in [0][0] = chan_in_all [0]; + assign chan_out_all [0] = router_chan_out [0][0]; + //Connect R0 input ports 1 to R14 output ports 3 + assign router_chan_in [0][1] = router_chan_out [10][3]; + //Connect R0 input ports 2 to R13 output ports 3 + assign router_chan_in [0][2] = router_chan_out [9][3]; + //Connect R1 input ports 0 to T1 output ports 0 + assign router_chan_in [1][0] = chan_in_all [1]; + assign chan_out_all [1] = router_chan_out [1][0]; + //Connect R1 input ports 1 to R7 output ports 3 + assign router_chan_in [1][1] = router_chan_out [7][3]; + //Connect R1 input ports 2 to R2 output ports 2 + assign router_chan_in [1][2] = router_chan_out [2][2]; + //Connect R2 input ports 0 to T2 output ports 0 + assign router_chan_in [2][0] = chan_in_all [2]; + assign chan_out_all [2] = router_chan_out [2][0]; + //Connect R2 input ports 1 to R15 output ports 2 + assign router_chan_in [2][1] = router_chan_out [11][2]; + //Connect R2 input ports 2 to R1 output ports 2 + assign router_chan_in [2][2] = router_chan_out [1][2]; + //Connect R3 input ports 0 to T3 output ports 0 + assign router_chan_in [3][0] = chan_in_all [3]; + assign chan_out_all [3] = router_chan_out [3][0]; + //Connect R3 input ports 1 to R15 output ports 3 + assign router_chan_in [3][1] = router_chan_out [11][3]; + //Connect R3 input ports 2 to R4 output ports 2 + assign router_chan_in [3][2] = router_chan_out [4][2]; + //Connect R4 input ports 0 to T4 output ports 0 + assign router_chan_in [4][0] = chan_in_all [4]; + assign chan_out_all [4] = router_chan_out [4][0]; + //Connect R4 input ports 1 to R9 output ports 2 + assign router_chan_in [4][1] = router_chan_out [13][2]; + //Connect R4 input ports 2 to R3 output ports 2 + assign router_chan_in [4][2] = router_chan_out [3][2]; + //Connect R4 input ports 3 to R6 output ports 3 + assign router_chan_in [4][3] = router_chan_out [6][3]; + //Connect R5 input ports 0 to T5 output ports 0 + assign router_chan_in [5][0] = chan_in_all [5]; + assign chan_out_all [5] = router_chan_out [5][0]; + //Connect R5 input ports 1 to R11 output ports 4 + assign router_chan_in [5][1] = router_chan_out [15][4]; + //Connect R5 input ports 2 to R6 output ports 2 + assign router_chan_in [5][2] = router_chan_out [6][2]; + //Connect R5 input ports 3 to R13 output ports 2 + assign router_chan_in [5][3] = router_chan_out [9][2]; + //Connect R6 input ports 0 to T6 output ports 0 + assign router_chan_in [6][0] = chan_in_all [6]; + assign chan_out_all [6] = router_chan_out [6][0]; + //Connect R6 input ports 1 to R9 output ports 3 + assign router_chan_in [6][1] = router_chan_out [13][3]; + //Connect R6 input ports 2 to R5 output ports 2 + assign router_chan_in [6][2] = router_chan_out [5][2]; + //Connect R6 input ports 3 to R4 output ports 3 + assign router_chan_in [6][3] = router_chan_out [4][3]; + //Connect R7 input ports 0 to T7 output ports 0 + assign router_chan_in [7][0] = chan_in_all [7]; + assign chan_out_all [7] = router_chan_out [7][0]; + //Connect R7 input ports 1 to R12 output ports 3 + assign router_chan_in [7][1] = router_chan_out [8][3]; + //Connect R7 input ports 2 to R14 output ports 2 + assign router_chan_in [7][2] = router_chan_out [10][2]; + //Connect R7 input ports 3 to R1 output ports 1 + assign router_chan_in [7][3] = router_chan_out [1][1]; + //Connect R12 input ports 0 to T8 output ports 0 + assign router_chan_in [8][0] = chan_in_all [8]; + assign chan_out_all [8] = router_chan_out [8][0]; + //Connect R12 input ports 1 to R8 output ports 4 + assign router_chan_in [8][1] = router_chan_out [12][4]; + //Connect R12 input ports 2 to R10 output ports 3 + assign router_chan_in [8][2] = router_chan_out [14][3]; + //Connect R12 input ports 3 to R7 output ports 1 + assign router_chan_in [8][3] = router_chan_out [7][1]; + //Connect R13 input ports 0 to T9 output ports 0 + assign router_chan_in [9][0] = chan_in_all [9]; + assign chan_out_all [9] = router_chan_out [9][0]; + //Connect R13 input ports 1 to R8 output ports 2 + assign router_chan_in [9][1] = router_chan_out [12][2]; + //Connect R13 input ports 2 to R5 output ports 3 + assign router_chan_in [9][2] = router_chan_out [5][3]; + //Connect R13 input ports 3 to R0 output ports 2 + assign router_chan_in [9][3] = router_chan_out [0][2]; + //Connect R14 input ports 0 to T10 output ports 0 + assign router_chan_in [10][0] = chan_in_all [10]; + assign chan_out_all [10] = router_chan_out [10][0]; + //Connect R14 input ports 1 to R8 output ports 3 + assign router_chan_in [10][1] = router_chan_out [12][3]; + //Connect R14 input ports 2 to R7 output ports 2 + assign router_chan_in [10][2] = router_chan_out [7][2]; + //Connect R14 input ports 3 to R0 output ports 1 + assign router_chan_in [10][3] = router_chan_out [0][1]; + //Connect R15 input ports 0 to T11 output ports 0 + assign router_chan_in [11][0] = chan_in_all [11]; + assign chan_out_all [11] = router_chan_out [11][0]; + //Connect R15 input ports 1 to R10 output ports 4 + assign router_chan_in [11][1] = router_chan_out [14][4]; + //Connect R15 input ports 2 to R2 output ports 1 + assign router_chan_in [11][2] = router_chan_out [2][1]; + //Connect R15 input ports 3 to R3 output ports 1 + assign router_chan_in [11][3] = router_chan_out [3][1]; + //Connect R8 input ports 0 to T12 output ports 0 + assign router_chan_in [12][0] = chan_in_all [12]; + assign chan_out_all [12] = router_chan_out [12][0]; + //Connect R8 input ports 1 to R11 output ports 1 + assign router_chan_in [12][1] = router_chan_out [15][1]; + //Connect R8 input ports 2 to R13 output ports 1 + assign router_chan_in [12][2] = router_chan_out [9][1]; + //Connect R8 input ports 3 to R14 output ports 1 + assign router_chan_in [12][3] = router_chan_out [10][1]; + //Connect R8 input ports 4 to R12 output ports 1 + assign router_chan_in [12][4] = router_chan_out [8][1]; + //Connect R9 input ports 0 to T13 output ports 0 + assign router_chan_in [13][0] = chan_in_all [13]; + assign chan_out_all [13] = router_chan_out [13][0]; + //Connect R9 input ports 1 to R11 output ports 3 + assign router_chan_in [13][1] = router_chan_out [15][3]; + //Connect R9 input ports 2 to R4 output ports 1 + assign router_chan_in [13][2] = router_chan_out [4][1]; + //Connect R9 input ports 3 to R6 output ports 1 + assign router_chan_in [13][3] = router_chan_out [6][1]; + //Connect R9 input ports 4 to R10 output ports 2 + assign router_chan_in [13][4] = router_chan_out [14][2]; + //Connect R10 input ports 0 to T14 output ports 0 + assign router_chan_in [14][0] = chan_in_all [14]; + assign chan_out_all [14] = router_chan_out [14][0]; + //Connect R10 input ports 1 to R11 output ports 2 + assign router_chan_in [14][1] = router_chan_out [15][2]; + //Connect R10 input ports 2 to R9 output ports 4 + assign router_chan_in [14][2] = router_chan_out [13][4]; + //Connect R10 input ports 3 to R12 output ports 2 + assign router_chan_in [14][3] = router_chan_out [8][2]; + //Connect R10 input ports 4 to R15 output ports 1 + assign router_chan_in [14][4] = router_chan_out [11][1]; + //Connect R11 input ports 0 to T15 output ports 0 + assign router_chan_in [15][0] = chan_in_all [15]; + assign chan_out_all [15] = router_chan_out [15][0]; + //Connect R11 input ports 1 to R8 output ports 1 + assign router_chan_in [15][1] = router_chan_out [12][1]; + //Connect R11 input ports 2 to R10 output ports 1 + assign router_chan_in [15][2] = router_chan_out [14][1]; + //Connect R11 input ports 3 to R9 output ports 1 + assign router_chan_in [15][3] = router_chan_out [13][1]; + //Connect R11 input ports 4 to R5 output ports 1 + assign router_chan_in [15][4] = router_chan_out [5][1]; - endmodule diff --git a/mpsoc/rtl/src_topology/custom_flist.f b/mpsoc/rtl/src_topology/custom_flist.f index 3a4b667..84acb86 100644 --- a/mpsoc/rtl/src_topology/custom_flist.f +++ b/mpsoc/rtl/src_topology/custom_flist.f @@ -1,10 +1,10 @@ +incdir+./ -./common/custom_lkh_routing.v -./common/custom_ni_routing.v -./common/custom_noc_top.sv -./custom1/custom1_noc.sv -./custom1/Tcustom1Rcustom_look_ahead_routing.v ./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v ./custom1/custom1_noc_genvar.sv -./custom1/Tcustom1Rcustom_conventional_routing.v ./custom1/Tcustom1Rcustom_conventional_routing_genvar.v +./custom1/custom1_noc.sv +./custom1/Tcustom1Rcustom_conventional_routing.v +./custom1/Tcustom1Rcustom_look_ahead_routing.v +./common/custom_ni_routing.v +./common/custom_noc_top.sv +./common/custom_lkh_routing.v diff --git a/mpsoc/rtl/src_topology/param.obj b/mpsoc/rtl/src_topology/param.obj index 0315176..7d47bec 100644 --- a/mpsoc/rtl/src_topology/param.obj +++ b/mpsoc/rtl/src_topology/param.obj @@ -1,21 +1,26 @@ ####################################################################### -## File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/param.obj +## File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/param.obj ## -## Copyright (C) 2014-2022 Alireza Monemi +## Copyright (C) 2014-2022 Alireza Monemi ## -## This file is part of ProNoC 2.2.0 +## This file is part of ProNoC 2.2.0 ## -## WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT -## MAY CAUSE UNEXPECTED BEHAVIOR. +## WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT +## MAY CAUSE UNEXPECTED BEHAVIOR. ################################################################################ - $Topology = { - '"mesh4x4"' => { + '"custom1"' => { 'ROUTER_Ps' => { - '5' => 16 + '5' => 4, + '4' => 8, + '3' => 4 }, - 'T1' => 16, + 'ROUTE_NAME' => '"custom"', 'er_addr' => [ + 0, + 1, + 2, + 3, 4, 5, 6, @@ -24,10 +29,6 @@ $Topology = { 9, 10, 11, - 0, - 1, - 2, - 3, 12, 13, 14, @@ -35,18 +36,10 @@ $Topology = { ], 'T2' => 16, 'T3' => 5, - 'ROUTE_NAME' => '"custom","m4"' + 'T1' => 16 }, - '"custom1"' => { - 'ROUTE_NAME' => '"custom"', - 'T3' => 5, - 'T1' => 16, - 'T2' => 16, + '"mesh4x4"' => { 'er_addr' => [ - 0, - 1, - 2, - 3, 4, 5, 6, @@ -55,15 +48,21 @@ $Topology = { 9, 10, 11, + 0, + 1, + 2, + 3, 12, 13, 14, 15 ], + 'T3' => 5, + 'T2' => 16, + 'ROUTE_NAME' => '"custom","m4"', + 'T1' => 16, 'ROUTER_Ps' => { - '5' => 4, - '3' => 4, - '4' => 8 + '5' => 16 } } }; diff --git a/mpsoc/src_verilator/topology/custom/custom1_noc.h b/mpsoc/src_verilator/topology/custom/custom1_noc.h index 7f9d34b..469dc4d 100644 --- a/mpsoc/src_verilator/topology/custom/custom1_noc.h +++ b/mpsoc/src_verilator/topology/custom/custom1_noc.h @@ -1,139 +1,137 @@ - -//Connect R0 input ports 1 to R14 output ports 3 + //Connect R0 input ports 1 to R14 output ports 3 void single_r2r0(void){conect_r2r(1,0,1,2,6,3);} -//Connect R0 input ports 2 to R13 output ports 3 + //Connect R0 input ports 2 to R13 output ports 3 void single_r2r1(void){conect_r2r(1,0,2,2,5,3);} -//Connect R1 input ports 1 to R7 output ports 3 + //Connect R1 input ports 1 to R7 output ports 3 void single_r2r2(void){conect_r2r(1,1,1,2,3,3);} -//Connect R1 input ports 2 to R2 output ports 2 + //Connect R1 input ports 2 to R2 output ports 2 void single_r2r3(void){conect_r2r(1,1,2,1,2,2);} -//Connect R2 input ports 1 to R15 output ports 2 + //Connect R2 input ports 1 to R15 output ports 2 void single_r2r4(void){conect_r2r(1,2,1,2,7,2);} -//Connect R2 input ports 2 to R1 output ports 2 + //Connect R2 input ports 2 to R1 output ports 2 void single_r2r5(void){conect_r2r(1,2,2,1,1,2);} -//Connect R3 input ports 1 to R15 output ports 3 + //Connect R3 input ports 1 to R15 output ports 3 void single_r2r6(void){conect_r2r(1,3,1,2,7,3);} -//Connect R3 input ports 2 to R4 output ports 2 + //Connect R3 input ports 2 to R4 output ports 2 void single_r2r7(void){conect_r2r(1,3,2,2,0,2);} -//Connect R4 input ports 1 to R9 output ports 2 + //Connect R4 input ports 1 to R9 output ports 2 void single_r2r8(void){conect_r2r(2,0,1,3,1,2);} -//Connect R4 input ports 2 to R3 output ports 2 + //Connect R4 input ports 2 to R3 output ports 2 void single_r2r9(void){conect_r2r(2,0,2,1,3,2);} -//Connect R4 input ports 3 to R6 output ports 3 + //Connect R4 input ports 3 to R6 output ports 3 void single_r2r10(void){conect_r2r(2,0,3,2,2,3);} -//Connect R5 input ports 1 to R11 output ports 4 + //Connect R5 input ports 1 to R11 output ports 4 void single_r2r11(void){conect_r2r(2,1,1,3,3,4);} -//Connect R5 input ports 2 to R6 output ports 2 + //Connect R5 input ports 2 to R6 output ports 2 void single_r2r12(void){conect_r2r(2,1,2,2,2,2);} -//Connect R5 input ports 3 to R13 output ports 2 + //Connect R5 input ports 3 to R13 output ports 2 void single_r2r13(void){conect_r2r(2,1,3,2,5,2);} -//Connect R6 input ports 1 to R9 output ports 3 + //Connect R6 input ports 1 to R9 output ports 3 void single_r2r14(void){conect_r2r(2,2,1,3,1,3);} -//Connect R6 input ports 2 to R5 output ports 2 + //Connect R6 input ports 2 to R5 output ports 2 void single_r2r15(void){conect_r2r(2,2,2,2,1,2);} -//Connect R6 input ports 3 to R4 output ports 3 + //Connect R6 input ports 3 to R4 output ports 3 void single_r2r16(void){conect_r2r(2,2,3,2,0,3);} -//Connect R7 input ports 1 to R12 output ports 3 + //Connect R7 input ports 1 to R12 output ports 3 void single_r2r17(void){conect_r2r(2,3,1,2,4,3);} -//Connect R7 input ports 2 to R14 output ports 2 + //Connect R7 input ports 2 to R14 output ports 2 void single_r2r18(void){conect_r2r(2,3,2,2,6,2);} -//Connect R7 input ports 3 to R1 output ports 1 + //Connect R7 input ports 3 to R1 output ports 1 void single_r2r19(void){conect_r2r(2,3,3,1,1,1);} -//Connect R12 input ports 1 to R8 output ports 4 + //Connect R12 input ports 1 to R8 output ports 4 void single_r2r20(void){conect_r2r(2,4,1,3,0,4);} -//Connect R12 input ports 2 to R10 output ports 3 + //Connect R12 input ports 2 to R10 output ports 3 void single_r2r21(void){conect_r2r(2,4,2,3,2,3);} -//Connect R12 input ports 3 to R7 output ports 1 + //Connect R12 input ports 3 to R7 output ports 1 void single_r2r22(void){conect_r2r(2,4,3,2,3,1);} -//Connect R13 input ports 1 to R8 output ports 2 + //Connect R13 input ports 1 to R8 output ports 2 void single_r2r23(void){conect_r2r(2,5,1,3,0,2);} -//Connect R13 input ports 2 to R5 output ports 3 + //Connect R13 input ports 2 to R5 output ports 3 void single_r2r24(void){conect_r2r(2,5,2,2,1,3);} -//Connect R13 input ports 3 to R0 output ports 2 + //Connect R13 input ports 3 to R0 output ports 2 void single_r2r25(void){conect_r2r(2,5,3,1,0,2);} -//Connect R14 input ports 1 to R8 output ports 3 + //Connect R14 input ports 1 to R8 output ports 3 void single_r2r26(void){conect_r2r(2,6,1,3,0,3);} -//Connect R14 input ports 2 to R7 output ports 2 + //Connect R14 input ports 2 to R7 output ports 2 void single_r2r27(void){conect_r2r(2,6,2,2,3,2);} -//Connect R14 input ports 3 to R0 output ports 1 + //Connect R14 input ports 3 to R0 output ports 1 void single_r2r28(void){conect_r2r(2,6,3,1,0,1);} -//Connect R15 input ports 1 to R10 output ports 4 + //Connect R15 input ports 1 to R10 output ports 4 void single_r2r29(void){conect_r2r(2,7,1,3,2,4);} -//Connect R15 input ports 2 to R2 output ports 1 + //Connect R15 input ports 2 to R2 output ports 1 void single_r2r30(void){conect_r2r(2,7,2,1,2,1);} -//Connect R15 input ports 3 to R3 output ports 1 + //Connect R15 input ports 3 to R3 output ports 1 void single_r2r31(void){conect_r2r(2,7,3,1,3,1);} -//Connect R8 input ports 1 to R11 output ports 1 + //Connect R8 input ports 1 to R11 output ports 1 void single_r2r32(void){conect_r2r(3,0,1,3,3,1);} -//Connect R8 input ports 2 to R13 output ports 1 + //Connect R8 input ports 2 to R13 output ports 1 void single_r2r33(void){conect_r2r(3,0,2,2,5,1);} -//Connect R8 input ports 3 to R14 output ports 1 + //Connect R8 input ports 3 to R14 output ports 1 void single_r2r34(void){conect_r2r(3,0,3,2,6,1);} -//Connect R8 input ports 4 to R12 output ports 1 + //Connect R8 input ports 4 to R12 output ports 1 void single_r2r35(void){conect_r2r(3,0,4,2,4,1);} -//Connect R9 input ports 1 to R11 output ports 3 + //Connect R9 input ports 1 to R11 output ports 3 void single_r2r36(void){conect_r2r(3,1,1,3,3,3);} -//Connect R9 input ports 2 to R4 output ports 1 + //Connect R9 input ports 2 to R4 output ports 1 void single_r2r37(void){conect_r2r(3,1,2,2,0,1);} -//Connect R9 input ports 3 to R6 output ports 1 + //Connect R9 input ports 3 to R6 output ports 1 void single_r2r38(void){conect_r2r(3,1,3,2,2,1);} -//Connect R9 input ports 4 to R10 output ports 2 + //Connect R9 input ports 4 to R10 output ports 2 void single_r2r39(void){conect_r2r(3,1,4,3,2,2);} -//Connect R10 input ports 1 to R11 output ports 2 + //Connect R10 input ports 1 to R11 output ports 2 void single_r2r40(void){conect_r2r(3,2,1,3,3,2);} -//Connect R10 input ports 2 to R9 output ports 4 + //Connect R10 input ports 2 to R9 output ports 4 void single_r2r41(void){conect_r2r(3,2,2,3,1,4);} -//Connect R10 input ports 3 to R12 output ports 2 + //Connect R10 input ports 3 to R12 output ports 2 void single_r2r42(void){conect_r2r(3,2,3,2,4,2);} -//Connect R10 input ports 4 to R15 output ports 1 + //Connect R10 input ports 4 to R15 output ports 1 void single_r2r43(void){conect_r2r(3,2,4,2,7,1);} -//Connect R11 input ports 1 to R8 output ports 1 + //Connect R11 input ports 1 to R8 output ports 1 void single_r2r44(void){conect_r2r(3,3,1,3,0,1);} -//Connect R11 input ports 2 to R10 output ports 1 + //Connect R11 input ports 2 to R10 output ports 1 void single_r2r45(void){conect_r2r(3,3,2,3,2,1);} -//Connect R11 input ports 3 to R9 output ports 1 + //Connect R11 input ports 3 to R9 output ports 1 void single_r2r46(void){conect_r2r(3,3,3,3,1,1);} -//Connect R11 input ports 4 to R5 output ports 1 + //Connect R11 input ports 4 to R5 output ports 1 void single_r2r47(void){conect_r2r(3,3,4,2,1,1);} -//Connect R0 input ports 0 to T0 output ports 0 + //Connect R0 input ports 0 to T0 output ports 0 void single_r2e0(void) {connect_r2e(1,0,0,0);} -//Connect R1 input ports 0 to T1 output ports 0 + //Connect R1 input ports 0 to T1 output ports 0 void single_r2e1(void) {connect_r2e(1,1,0,1);} -//Connect R2 input ports 0 to T2 output ports 0 + //Connect R2 input ports 0 to T2 output ports 0 void single_r2e2(void) {connect_r2e(1,2,0,2);} -//Connect R3 input ports 0 to T3 output ports 0 + //Connect R3 input ports 0 to T3 output ports 0 void single_r2e3(void) {connect_r2e(1,3,0,3);} -//Connect R4 input ports 0 to T4 output ports 0 + //Connect R4 input ports 0 to T4 output ports 0 void single_r2e4(void) {connect_r2e(2,0,0,4);} -//Connect R5 input ports 0 to T5 output ports 0 + //Connect R5 input ports 0 to T5 output ports 0 void single_r2e5(void) {connect_r2e(2,1,0,5);} -//Connect R6 input ports 0 to T6 output ports 0 + //Connect R6 input ports 0 to T6 output ports 0 void single_r2e6(void) {connect_r2e(2,2,0,6);} -//Connect R7 input ports 0 to T7 output ports 0 + //Connect R7 input ports 0 to T7 output ports 0 void single_r2e7(void) {connect_r2e(2,3,0,7);} -//Connect R12 input ports 0 to T8 output ports 0 + //Connect R12 input ports 0 to T8 output ports 0 void single_r2e8(void) {connect_r2e(2,4,0,8);} -//Connect R13 input ports 0 to T9 output ports 0 + //Connect R13 input ports 0 to T9 output ports 0 void single_r2e9(void) {connect_r2e(2,5,0,9);} -//Connect R14 input ports 0 to T10 output ports 0 + //Connect R14 input ports 0 to T10 output ports 0 void single_r2e10(void) {connect_r2e(2,6,0,10);} -//Connect R15 input ports 0 to T11 output ports 0 + //Connect R15 input ports 0 to T11 output ports 0 void single_r2e11(void) {connect_r2e(2,7,0,11);} -//Connect R8 input ports 0 to T12 output ports 0 + //Connect R8 input ports 0 to T12 output ports 0 void single_r2e12(void) {connect_r2e(3,0,0,12);} -//Connect R9 input ports 0 to T13 output ports 0 + //Connect R9 input ports 0 to T13 output ports 0 void single_r2e13(void) {connect_r2e(3,1,0,13);} -//Connect R10 input ports 0 to T14 output ports 0 + //Connect R10 input ports 0 to T14 output ports 0 void single_r2e14(void) {connect_r2e(3,2,0,14);} -//Connect R11 input ports 0 to T15 output ports 0 + //Connect R11 input ports 0 to T15 output ports 0 void single_r2e15(void) {connect_r2e(3,3,0,15);} - void (*r2r_func_ptr[48])() = { single_r2r0,single_r2r1,single_r2r2,single_r2r3,single_r2r4,single_r2r5,single_r2r6,single_r2r7,single_r2r8,single_r2r9 ,single_r2r10,single_r2r11,single_r2r12,single_r2r13,single_r2r14,single_r2r15,single_r2r16,single_r2r17,single_r2r18,single_r2r19 @@ -145,15 +143,13 @@ single_r2e0,single_r2e1,single_r2e2,single_r2e3,single_r2e4,single_r2e5,single_r ,single_r2e10,single_r2e11,single_r2e12,single_r2e13,single_r2e14,single_r2e15}; void topology_connect_r2r (int n){ - (*r2r_func_ptr[n])(); + (*r2r_func_ptr[n])(); } void topology_connect_r2e (int n){ - (*r2e_func_ptr[n])(); + (*r2e_func_ptr[n])(); } - - void topology_init(void){ router1[0]->current_r_addr=0; router1[0]->current_r_id=0; @@ -187,54 +183,54 @@ router3[2]->current_r_addr=14; router3[2]->current_r_id=14; router3[3]->current_r_addr=15; router3[3]->current_r_id=15; - r2r_cnt_all[0] =(r2r_cnt_table_t){.id1=0, .t1=1, .r1=0, .p1=1,.id2=10, .t2=2, .r2=6, .p2=3 }; - r2r_cnt_all[1] =(r2r_cnt_table_t){.id1=0, .t1=1, .r1=0, .p1=2,.id2=9, .t2=2, .r2=5, .p2=3 }; - r2r_cnt_all[2] =(r2r_cnt_table_t){.id1=1, .t1=1, .r1=1, .p1=1,.id2=7, .t2=2, .r2=3, .p2=3 }; - r2r_cnt_all[3] =(r2r_cnt_table_t){.id1=1, .t1=1, .r1=1, .p1=2,.id2=2, .t2=1, .r2=2, .p2=2 }; - r2r_cnt_all[4] =(r2r_cnt_table_t){.id1=2, .t1=1, .r1=2, .p1=1,.id2=11, .t2=2, .r2=7, .p2=2 }; - r2r_cnt_all[5] =(r2r_cnt_table_t){.id1=2, .t1=1, .r1=2, .p1=2,.id2=1, .t2=1, .r2=1, .p2=2 }; - r2r_cnt_all[6] =(r2r_cnt_table_t){.id1=3, .t1=1, .r1=3, .p1=1,.id2=11, .t2=2, .r2=7, .p2=3 }; - r2r_cnt_all[7] =(r2r_cnt_table_t){.id1=3, .t1=1, .r1=3, .p1=2,.id2=4, .t2=2, .r2=0, .p2=2 }; - r2r_cnt_all[8] =(r2r_cnt_table_t){.id1=4, .t1=2, .r1=0, .p1=1,.id2=13, .t2=3, .r2=1, .p2=2 }; - r2r_cnt_all[9] =(r2r_cnt_table_t){.id1=4, .t1=2, .r1=0, .p1=2,.id2=3, .t2=1, .r2=3, .p2=2 }; - r2r_cnt_all[10] =(r2r_cnt_table_t){.id1=4, .t1=2, .r1=0, .p1=3,.id2=6, .t2=2, .r2=2, .p2=3 }; - r2r_cnt_all[11] =(r2r_cnt_table_t){.id1=5, .t1=2, .r1=1, .p1=1,.id2=15, .t2=3, .r2=3, .p2=4 }; - r2r_cnt_all[12] =(r2r_cnt_table_t){.id1=5, .t1=2, .r1=1, .p1=2,.id2=6, .t2=2, .r2=2, .p2=2 }; - r2r_cnt_all[13] =(r2r_cnt_table_t){.id1=5, .t1=2, .r1=1, .p1=3,.id2=9, .t2=2, .r2=5, .p2=2 }; - r2r_cnt_all[14] =(r2r_cnt_table_t){.id1=6, .t1=2, .r1=2, .p1=1,.id2=13, .t2=3, .r2=1, .p2=3 }; - r2r_cnt_all[15] =(r2r_cnt_table_t){.id1=6, .t1=2, .r1=2, .p1=2,.id2=5, .t2=2, .r2=1, .p2=2 }; - r2r_cnt_all[16] =(r2r_cnt_table_t){.id1=6, .t1=2, .r1=2, .p1=3,.id2=4, .t2=2, .r2=0, .p2=3 }; - r2r_cnt_all[17] =(r2r_cnt_table_t){.id1=7, .t1=2, .r1=3, .p1=1,.id2=8, .t2=2, .r2=4, .p2=3 }; - r2r_cnt_all[18] =(r2r_cnt_table_t){.id1=7, .t1=2, .r1=3, .p1=2,.id2=10, .t2=2, .r2=6, .p2=2 }; - r2r_cnt_all[19] =(r2r_cnt_table_t){.id1=7, .t1=2, .r1=3, .p1=3,.id2=1, .t2=1, .r2=1, .p2=1 }; - r2r_cnt_all[20] =(r2r_cnt_table_t){.id1=8, .t1=2, .r1=4, .p1=1,.id2=12, .t2=3, .r2=0, .p2=4 }; - r2r_cnt_all[21] =(r2r_cnt_table_t){.id1=8, .t1=2, .r1=4, .p1=2,.id2=14, .t2=3, .r2=2, .p2=3 }; - r2r_cnt_all[22] =(r2r_cnt_table_t){.id1=8, .t1=2, .r1=4, .p1=3,.id2=7, .t2=2, .r2=3, .p2=1 }; - r2r_cnt_all[23] =(r2r_cnt_table_t){.id1=9, .t1=2, .r1=5, .p1=1,.id2=12, .t2=3, .r2=0, .p2=2 }; - r2r_cnt_all[24] =(r2r_cnt_table_t){.id1=9, .t1=2, .r1=5, .p1=2,.id2=5, .t2=2, .r2=1, .p2=3 }; - r2r_cnt_all[25] =(r2r_cnt_table_t){.id1=9, .t1=2, .r1=5, .p1=3,.id2=0, .t2=1, .r2=0, .p2=2 }; - r2r_cnt_all[26] =(r2r_cnt_table_t){.id1=10, .t1=2, .r1=6, .p1=1,.id2=12, .t2=3, .r2=0, .p2=3 }; - r2r_cnt_all[27] =(r2r_cnt_table_t){.id1=10, .t1=2, .r1=6, .p1=2,.id2=7, .t2=2, .r2=3, .p2=2 }; - r2r_cnt_all[28] =(r2r_cnt_table_t){.id1=10, .t1=2, .r1=6, .p1=3,.id2=0, .t2=1, .r2=0, .p2=1 }; - r2r_cnt_all[29] =(r2r_cnt_table_t){.id1=11, .t1=2, .r1=7, .p1=1,.id2=14, .t2=3, .r2=2, .p2=4 }; - r2r_cnt_all[30] =(r2r_cnt_table_t){.id1=11, .t1=2, .r1=7, .p1=2,.id2=2, .t2=1, .r2=2, .p2=1 }; - r2r_cnt_all[31] =(r2r_cnt_table_t){.id1=11, .t1=2, .r1=7, .p1=3,.id2=3, .t2=1, .r2=3, .p2=1 }; - r2r_cnt_all[32] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=1,.id2=15, .t2=3, .r2=3, .p2=1 }; - r2r_cnt_all[33] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=2,.id2=9, .t2=2, .r2=5, .p2=1 }; - r2r_cnt_all[34] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=3,.id2=10, .t2=2, .r2=6, .p2=1 }; - r2r_cnt_all[35] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=4,.id2=8, .t2=2, .r2=4, .p2=1 }; - r2r_cnt_all[36] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=1,.id2=15, .t2=3, .r2=3, .p2=3 }; - r2r_cnt_all[37] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=2,.id2=4, .t2=2, .r2=0, .p2=1 }; - r2r_cnt_all[38] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=3,.id2=6, .t2=2, .r2=2, .p2=1 }; - r2r_cnt_all[39] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=4,.id2=14, .t2=3, .r2=2, .p2=2 }; - r2r_cnt_all[40] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=1,.id2=15, .t2=3, .r2=3, .p2=2 }; - r2r_cnt_all[41] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=2,.id2=13, .t2=3, .r2=1, .p2=4 }; - r2r_cnt_all[42] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=3,.id2=8, .t2=2, .r2=4, .p2=2 }; - r2r_cnt_all[43] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=4,.id2=11, .t2=2, .r2=7, .p2=1 }; - r2r_cnt_all[44] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=1,.id2=12, .t2=3, .r2=0, .p2=1 }; - r2r_cnt_all[45] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=2,.id2=14, .t2=3, .r2=2, .p2=1 }; - r2r_cnt_all[46] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=3,.id2=13, .t2=3, .r2=1, .p2=1 }; - r2r_cnt_all[47] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=4,.id2=5, .t2=2, .r2=1, .p2=1 }; + r2r_cnt_all[0] =(r2r_cnt_table_t){.id1=0, .t1=1, .r1=0, .p1=1,.id2=10, .t2=2, .r2=6, .p2=3 }; + r2r_cnt_all[1] =(r2r_cnt_table_t){.id1=0, .t1=1, .r1=0, .p1=2,.id2=9, .t2=2, .r2=5, .p2=3 }; + r2r_cnt_all[2] =(r2r_cnt_table_t){.id1=1, .t1=1, .r1=1, .p1=1,.id2=7, .t2=2, .r2=3, .p2=3 }; + r2r_cnt_all[3] =(r2r_cnt_table_t){.id1=1, .t1=1, .r1=1, .p1=2,.id2=2, .t2=1, .r2=2, .p2=2 }; + r2r_cnt_all[4] =(r2r_cnt_table_t){.id1=2, .t1=1, .r1=2, .p1=1,.id2=11, .t2=2, .r2=7, .p2=2 }; + r2r_cnt_all[5] =(r2r_cnt_table_t){.id1=2, .t1=1, .r1=2, .p1=2,.id2=1, .t2=1, .r2=1, .p2=2 }; + r2r_cnt_all[6] =(r2r_cnt_table_t){.id1=3, .t1=1, .r1=3, .p1=1,.id2=11, .t2=2, .r2=7, .p2=3 }; + r2r_cnt_all[7] =(r2r_cnt_table_t){.id1=3, .t1=1, .r1=3, .p1=2,.id2=4, .t2=2, .r2=0, .p2=2 }; + r2r_cnt_all[8] =(r2r_cnt_table_t){.id1=4, .t1=2, .r1=0, .p1=1,.id2=13, .t2=3, .r2=1, .p2=2 }; + r2r_cnt_all[9] =(r2r_cnt_table_t){.id1=4, .t1=2, .r1=0, .p1=2,.id2=3, .t2=1, .r2=3, .p2=2 }; + r2r_cnt_all[10] =(r2r_cnt_table_t){.id1=4, .t1=2, .r1=0, .p1=3,.id2=6, .t2=2, .r2=2, .p2=3 }; + r2r_cnt_all[11] =(r2r_cnt_table_t){.id1=5, .t1=2, .r1=1, .p1=1,.id2=15, .t2=3, .r2=3, .p2=4 }; + r2r_cnt_all[12] =(r2r_cnt_table_t){.id1=5, .t1=2, .r1=1, .p1=2,.id2=6, .t2=2, .r2=2, .p2=2 }; + r2r_cnt_all[13] =(r2r_cnt_table_t){.id1=5, .t1=2, .r1=1, .p1=3,.id2=9, .t2=2, .r2=5, .p2=2 }; + r2r_cnt_all[14] =(r2r_cnt_table_t){.id1=6, .t1=2, .r1=2, .p1=1,.id2=13, .t2=3, .r2=1, .p2=3 }; + r2r_cnt_all[15] =(r2r_cnt_table_t){.id1=6, .t1=2, .r1=2, .p1=2,.id2=5, .t2=2, .r2=1, .p2=2 }; + r2r_cnt_all[16] =(r2r_cnt_table_t){.id1=6, .t1=2, .r1=2, .p1=3,.id2=4, .t2=2, .r2=0, .p2=3 }; + r2r_cnt_all[17] =(r2r_cnt_table_t){.id1=7, .t1=2, .r1=3, .p1=1,.id2=8, .t2=2, .r2=4, .p2=3 }; + r2r_cnt_all[18] =(r2r_cnt_table_t){.id1=7, .t1=2, .r1=3, .p1=2,.id2=10, .t2=2, .r2=6, .p2=2 }; + r2r_cnt_all[19] =(r2r_cnt_table_t){.id1=7, .t1=2, .r1=3, .p1=3,.id2=1, .t2=1, .r2=1, .p2=1 }; + r2r_cnt_all[20] =(r2r_cnt_table_t){.id1=8, .t1=2, .r1=4, .p1=1,.id2=12, .t2=3, .r2=0, .p2=4 }; + r2r_cnt_all[21] =(r2r_cnt_table_t){.id1=8, .t1=2, .r1=4, .p1=2,.id2=14, .t2=3, .r2=2, .p2=3 }; + r2r_cnt_all[22] =(r2r_cnt_table_t){.id1=8, .t1=2, .r1=4, .p1=3,.id2=7, .t2=2, .r2=3, .p2=1 }; + r2r_cnt_all[23] =(r2r_cnt_table_t){.id1=9, .t1=2, .r1=5, .p1=1,.id2=12, .t2=3, .r2=0, .p2=2 }; + r2r_cnt_all[24] =(r2r_cnt_table_t){.id1=9, .t1=2, .r1=5, .p1=2,.id2=5, .t2=2, .r2=1, .p2=3 }; + r2r_cnt_all[25] =(r2r_cnt_table_t){.id1=9, .t1=2, .r1=5, .p1=3,.id2=0, .t2=1, .r2=0, .p2=2 }; + r2r_cnt_all[26] =(r2r_cnt_table_t){.id1=10, .t1=2, .r1=6, .p1=1,.id2=12, .t2=3, .r2=0, .p2=3 }; + r2r_cnt_all[27] =(r2r_cnt_table_t){.id1=10, .t1=2, .r1=6, .p1=2,.id2=7, .t2=2, .r2=3, .p2=2 }; + r2r_cnt_all[28] =(r2r_cnt_table_t){.id1=10, .t1=2, .r1=6, .p1=3,.id2=0, .t2=1, .r2=0, .p2=1 }; + r2r_cnt_all[29] =(r2r_cnt_table_t){.id1=11, .t1=2, .r1=7, .p1=1,.id2=14, .t2=3, .r2=2, .p2=4 }; + r2r_cnt_all[30] =(r2r_cnt_table_t){.id1=11, .t1=2, .r1=7, .p1=2,.id2=2, .t2=1, .r2=2, .p2=1 }; + r2r_cnt_all[31] =(r2r_cnt_table_t){.id1=11, .t1=2, .r1=7, .p1=3,.id2=3, .t2=1, .r2=3, .p2=1 }; + r2r_cnt_all[32] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=1,.id2=15, .t2=3, .r2=3, .p2=1 }; + r2r_cnt_all[33] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=2,.id2=9, .t2=2, .r2=5, .p2=1 }; + r2r_cnt_all[34] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=3,.id2=10, .t2=2, .r2=6, .p2=1 }; + r2r_cnt_all[35] =(r2r_cnt_table_t){.id1=12, .t1=3, .r1=0, .p1=4,.id2=8, .t2=2, .r2=4, .p2=1 }; + r2r_cnt_all[36] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=1,.id2=15, .t2=3, .r2=3, .p2=3 }; + r2r_cnt_all[37] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=2,.id2=4, .t2=2, .r2=0, .p2=1 }; + r2r_cnt_all[38] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=3,.id2=6, .t2=2, .r2=2, .p2=1 }; + r2r_cnt_all[39] =(r2r_cnt_table_t){.id1=13, .t1=3, .r1=1, .p1=4,.id2=14, .t2=3, .r2=2, .p2=2 }; + r2r_cnt_all[40] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=1,.id2=15, .t2=3, .r2=3, .p2=2 }; + r2r_cnt_all[41] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=2,.id2=13, .t2=3, .r2=1, .p2=4 }; + r2r_cnt_all[42] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=3,.id2=8, .t2=2, .r2=4, .p2=2 }; + r2r_cnt_all[43] =(r2r_cnt_table_t){.id1=14, .t1=3, .r1=2, .p1=4,.id2=11, .t2=2, .r2=7, .p2=1 }; + r2r_cnt_all[44] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=1,.id2=12, .t2=3, .r2=0, .p2=1 }; + r2r_cnt_all[45] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=2,.id2=14, .t2=3, .r2=2, .p2=1 }; + r2r_cnt_all[46] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=3,.id2=13, .t2=3, .r2=1, .p2=1 }; + r2r_cnt_all[47] =(r2r_cnt_table_t){.id1=15, .t1=3, .r1=3, .p1=4,.id2=5, .t2=2, .r2=1, .p2=1 }; R2R_TABLE_SIZ=48; From 8746bf35d715f6eb237df7e50d88feffc908b5ab Mon Sep 17 00:00:00 2001 From: amonemi Date: Fri, 14 Mar 2025 17:13:38 +0100 Subject: [PATCH 018/107] add router_config port --- .../perl_gui/lib/perl/topology_verilog_gen.pl | 21 +- mpsoc/rtl/arbiter.v | 6 +- mpsoc/rtl/src_emulate/rtl/noc_emulator.sv | 776 ++++++---------- mpsoc/rtl/src_modelsim/multicast_injector.sv | 842 ++++++++---------- mpsoc/rtl/src_noc/fattree_noc_top.sv | 32 +- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 55 +- mpsoc/rtl/src_noc/packet_injector.sv | 5 +- mpsoc/rtl/src_noc/pronoc_pkg.sv | 33 +- mpsoc/rtl/src_noc/router_top.sv | 33 +- mpsoc/rtl/src_noc/router_two_stage.sv | 6 +- mpsoc/rtl/src_noc/star_noc.sv | 7 +- mpsoc/rtl/src_noc/topology_localparam.v | 30 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 2 +- mpsoc/rtl/src_noc/tree_noc_top.sv | 13 +- mpsoc/rtl/src_openpiton/wrapper.sv | 2 +- mpsoc/rtl/src_topology/custom1/custom1.png | Bin 103874 -> 83516 bytes mpsoc/rtl/src_topology/custom1/custom1_noc.sv | 128 +-- .../custom1/custom1_noc_genvar.sv | 20 +- mpsoc/rtl/src_topology/param.obj | 48 +- .../jtag_ram_test/src_verilog/lib/arbiter.v | 6 +- 20 files changed, 899 insertions(+), 1166 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index 17fe5d2..b855a7c 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -136,7 +136,6 @@ sub get_router_instance_v { *******************/ wire ${instance}_clk; wire ${instance}_reset; - wire [RAw-1 : 0] ${instance}_current_r_addr; smartflit_chanel_t ${instance}_chan_in [$Pnum-1 : 0]; smartflit_chanel_t ${instance}_chan_out [$Pnum-1 : 0]; router_event_t ${instance}_router_event [$Pnum-1 : 0]; @@ -145,6 +144,7 @@ sub get_router_instance_v { /******************* * $instance *******************/ + router_config_t ${instance}_router_config_in; router_top #( .NOC_ID(NOC_ID), .ROUTER_ID($current_r), @@ -152,8 +152,7 @@ sub get_router_instance_v { ) $instance ( .clk(${instance}_clk), .reset(${instance}_reset), - .current_r_id($current_r), - .current_r_addr (${instance}_current_r_addr), + .router_config_in(${instance}_router_config_in), .chan_in (${instance}_chan_in), .chan_out (${instance}_chan_out), .router_event (${instance}_router_event) @@ -162,7 +161,8 @@ sub get_router_instance_v { $router_v= $router_v." assign ${instance}_clk = clk; assign ${instance}_reset = reset; - assign ${instance}_current_r_addr = $current_r; + assign ${instance}_router_config_in.router_addr = $current_r; + assign ${instance}_router_config_in.router_id = $current_r; "; for (my $i=0;$i<$Pnum; $i++){ @@ -272,7 +272,7 @@ sub generate_topology_top_genvar_v{ //all routers port smartflit_chanel_t router_chan_in [NR-1 :0][MAX_P-1 : 0]; smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; - wire [RAw-1 : 0] current_r_addr [NR-1 : 0]; + router_config_t router_config [NR-1 : 0]; "; my $router_wires=""; @@ -350,7 +350,8 @@ sub generate_topology_top_genvar_v{ $routers=$routers." for( i=0; i<$n; i=i+1) begin : router_${i}_port_lp localparam RID = $router_pos; - assign current_r_addr [RID] = RID[RAw-1: 0]; + assign router_config [RID].router_id = RID[RAw-1: 0]; + assign router_config [RID].router_addr = RID[RAw-1: 0]; router_top #( .NOC_ID(NOC_ID), .ROUTER_ID(RID), @@ -358,8 +359,7 @@ sub generate_topology_top_genvar_v{ ) router_${i}_port ( .clk(clk), .reset(reset), - .current_r_id(RID), - .current_r_addr(current_r_addr\[RID\]), + .router_config_in(router_config\[RID\]), .chan_in (router_chan_in \[RID\] \[$p : 0\]), .chan_out (router_chan_out\[RID\] \[$p : 0\]), .router_event(router_event\[RID\] \[$p : 0\]) @@ -454,6 +454,8 @@ sub get_router_genvar_instance_v{ my @parameters=@{$self->object_get_attribute ('Verilog','Router_param')}; my @ports= @{$self->object_get_attribute('Verilog','Router_ports')}; my $router_v=" + assign router_config[$router_pos].router_id = $router_pos; + assign router_config[$router_pos].router_addr = $router_pos; router_top #( .NOC_ID(NOC_ID), .ROUTER_ID($router_pos), @@ -461,8 +463,7 @@ sub get_router_genvar_instance_v{ ) router_${Pnum}_port ( .clk(clk), .reset(reset), - .current_r_addr($router_pos), - .current_r_id($router_pos), + .router_config_in(router_config\[$router_pos\]), .chan_in (router_chan_in\[$router_pos\]), .chan_out(router_chan_out\[$router_pos\]), .router_event(router_event\[$router_pos\]) diff --git a/mpsoc/rtl/arbiter.v b/mpsoc/rtl/arbiter.v index 5c5af0b..0cdb1aa 100755 --- a/mpsoc/rtl/arbiter.v +++ b/mpsoc/rtl/arbiter.v @@ -356,7 +356,7 @@ module thermo_arbiter #( reg [ARBITER_WIDTH-1 : 0] termo1,termo2; integer i; always @(*) begin - for(int i=0;i 4'd0 && counter<=4'b1111) counter <=counter+1'b1; + wire start_traffic; + reg [3:0] counter; + always @(posedge clk or posedge reset) begin + if(reset) counter <=4'd0; + else begin + if(start) counter <=4'd1; + else if(counter> 4'd0 && counter<=4'b1111) counter <=counter+1'b1; + end end - end - - assign start_traffic = counter == 4'b1100; // delaied for 12 clock cycles + assign start_traffic = counter == 4'b1100; // delaied for 12 clock cycles - - traffic_gen_top #( + traffic_gen_top #( .NOC_ID(NOC_ID), .MAX_RATIO(MAX_RATIO) - ) - the_traffic_gen - ( - + ) the_traffic_gen ( .reset(reset), .clk(clk), - //input + //input .ratio (ratio), .start(start_traffic), .stop(stop), - .pck_size_in(pck_size_in), + .pck_size_in(pck_size_in), .current_e_addr(current_e_addr), - .dest_e_addr(dest_e_addr), - .pck_class_in(pck_class), + .dest_e_addr(dest_e_addr), + .pck_class_in(pck_class), .init_weight({WEIGHTw{1'b0}}), .report ( ), - //output .update(update), // update the noc_analayzer - .src_e_addr( ), + .src_e_addr( ), .pck_number( ), .sent_done(sent_done), // tail flit has been sent .hdr_flit_sent( ), .distance( ), - .pck_class_out( ), + .pck_class_out( ), .time_stamp_h2h( ), .time_stamp_h2t(time_stamp_h2t), .flit_out_class(), - //noc - .chan_in(chan_in), - .chan_out(chan_out), - .mcast_dst_num_o() - - + //noc + .chan_in(chan_in), + .chan_out(chan_out), + .mcast_dst_num_o() ); - - always @ (*)begin + + always @ (*)begin case (statistic_jtag_addr_b) SENT_PCK_ADDR: statistic_jtag_q_b= total_pck_sent; RSVD_PCK_ADDR: statistic_jtag_q_b= total_pck_recieved; TOTAL_LATENCY_ADDR: statistic_jtag_q_b= total_latency_cnt; WORST_LATENCY_ADDR: statistic_jtag_q_b= worst_latency; - default: statistic_jtag_q_b= worst_latency; - endcase + default: statistic_jtag_q_b= worst_latency; + endcase end - - - - - always @ (*)begin - ns=ps; - addr_a_next = addr_a; - pck_number_sent_next = pck_number_sent; - done_next =done; - total_latency_cnt_next = total_latency_cnt; - worst_latency_next = worst_latency; - total_pck_recieved_next = total_pck_recieved; - total_pck_sent_next = total_pck_sent; - ram_counter_next = ram_counter; - data_a = total_pck_sent; - we_a = 0; - stop=1'b0; - - if(update)begin - total_latency_cnt_next = total_latency_cnt + time_stamp_h2t; - if(time_stamp_h2t >worst_latency ) worst_latency_next=time_stamp_h2t; - total_pck_recieved_next =total_pck_recieved+1'b1; - end - - if(sent_done)begin - pck_number_sent_next =pck_number_sent+1'b1; - total_pck_sent_next =total_pck_sent+1'b1; - end - - - case(ps) - IDEAL : begin - done_next =1'b0; - addr_a_next =RAM_CNT_ADDR; - ram_counter_next = q_a[31:0]; // first ram data shows how many times the RAM is needed to ne read - if( start) begin - addr_a_next=PATTERN_START_ADDR; - ns= WAIT1; - end - - end//IDEAL - WAIT1 : begin - ns= WAIT2; - - end - WAIT2 : begin - ns= SEND_PCK; - - end - SEND_PCK: begin - if (reset_pck_number_sent) begin - pck_number_sent_next={PCK_CNTw{1'b0}}; - if(last_adr_in)begin - if(ram_counter==0)begin - ns = ASSET_DONE;// SAVE_SENT_PCK_NUM; - //addr_a_next = SENT_PCK_ADDR; - end else addr_a_next = 1; - ram_counter_next=ram_counter-1'b1; - end else begin + + always @ (*)begin + ns=ps; + addr_a_next = addr_a; + pck_number_sent_next = pck_number_sent; + done_next =done; + total_latency_cnt_next = total_latency_cnt; + worst_latency_next = worst_latency; + total_pck_recieved_next = total_pck_recieved; + total_pck_sent_next = total_pck_sent; + ram_counter_next = ram_counter; + data_a = total_pck_sent; + we_a = 0; + stop=1'b0; + if(update)begin + total_latency_cnt_next = total_latency_cnt + time_stamp_h2t; + if(time_stamp_h2t >worst_latency ) worst_latency_next=time_stamp_h2t; + total_pck_recieved_next =total_pck_recieved+1'b1; + end + if(sent_done)begin + pck_number_sent_next =pck_number_sent+1'b1; + total_pck_sent_next =total_pck_sent+1'b1; + end + case(ps) + IDEAL : begin + done_next =1'b0; + addr_a_next =RAM_CNT_ADDR; + ram_counter_next = q_a[31:0]; // first ram data shows how many times the RAM is needed to ne read + if( start) begin + addr_a_next=PATTERN_START_ADDR; + ns= WAIT1; + end + end//IDEAL + WAIT1 : begin + ns= WAIT2; + end + WAIT2 : begin + ns= SEND_PCK; + end + SEND_PCK: begin + if (reset_pck_number_sent) begin + pck_number_sent_next={PCK_CNTw{1'b0}}; + if(last_adr_in)begin + if(ram_counter==0)begin + ns = ASSET_DONE;// SAVE_SENT_PCK_NUM; + //addr_a_next = SENT_PCK_ADDR; + end else addr_a_next = 1; + ram_counter_next=ram_counter-1'b1; + end else begin addr_a_next=addr_a+1'b1; - - end - + end end - - - - - - end//SEND_PCk - /* - SAVE_SENT_PCK_NUM: begin + end//SEND_PCk + /* + SAVE_SENT_PCK_NUM: begin data_a = total_pck_sent; we_a = 1; addr_a_next =RSVD_PCK_ADDR ; - ns= SAVE_RSVD_PCK_NUM; - - end - SAVE_RSVD_PCK_NUM: begin + ns= SAVE_RSVD_PCK_NUM; + end + SAVE_RSVD_PCK_NUM: begin data_a = total_pck_recieved; addr_a_next =TOTAL_LATENCY_ADDR; we_a = 1; - ns= SAVE_TOTAL_LATENCY_NUM; - - - end - SAVE_TOTAL_LATENCY_NUM: begin + ns= SAVE_TOTAL_LATENCY_NUM; + end + SAVE_TOTAL_LATENCY_NUM: begin data_a = total_latency_cnt; addr_a_next =WORST_LATENCY_ADDR; - we_a = 1; + we_a = 1; ns=SAVE_WORST_LATENCY_NUM; - - - end - SAVE_WORST_LATENCY_NUM:begin + end + SAVE_WORST_LATENCY_NUM:begin data_a = worst_latency; - we_a = 1; - ns= ASSET_DONE; - end - */ - ASSET_DONE: begin - done_next =1'b1; - stop=1'b1; - end - endcase - end//always - - - + we_a = 1; + ns= ASSET_DONE; + end + */ + ASSET_DONE: begin + done_next =1'b1; + stop=1'b1; + end + endcase + end//always + always @(posedge clk) begin if(reset)begin ps <= IDEAL; @@ -661,7 +519,7 @@ module traffic_gen_ram nvalid_dest<=1'b0; reset_pck_number_sent_old<=1'b0; worst_latency<={CLK_CNTw{1'b0}}; - end else begin + end else begin ps <= ns; addr_a<= addr_a_next; pck_number_sent<= pck_number_sent_next; @@ -673,87 +531,60 @@ module traffic_gen_ram nvalid_dest<=nvalid_dest_next; reset_pck_number_sent_old<=reset_pck_number_sent; worst_latency<=worst_latency_next; - end - end - - - + end + end endmodule - - - /*********************** * * jtag_emulator_controller * ***********************/ - - - module jtag_emulator_controller #( parameter VJTAG_INDEX=125, parameter Dw=32, - parameter Aw=32 - + parameter Aw=32 )( clk, - reset, + reset, //wishbone master interface signals - dat_o, addr_o, we_o, - q_i + q_i ); - //IO declaration input reset,clk; - - //wishbone master interface signals - output [Dw-1 : 0] dat_o; output [Aw-1 : 0] addr_o; - output we_o; + output we_o; input [Dw-1 : 0] q_i; - - - - localparam STATE_NUM=3, - IDEAL =1, - WB_WR_DATA=2, - WB_RD_DATA=4; + localparam + STATE_NUM=3, + IDEAL =1, + WB_WR_DATA=2, + WB_RD_DATA=4; + reg [STATE_NUM-1 : 0] ps,ns; - wire [Dw-1 :0] data_out, data_in; wire wb_wr_addr_en, wb_wr_data_en, wb_rd_data_en; reg wr_mem_en, wb_cap_rd; - reg [Aw-1 : 0] wb_addr,wb_addr_next; reg [Dw-1 : 0] wb_wr_data,wb_rd_data; reg wb_addr_inc; - - - assign we_o = wr_mem_en; assign dat_o = wb_wr_data; assign addr_o = wb_addr; assign data_in = wb_rd_data; -//vjtag vjtag signals declaration - - -localparam VJ_DW= (Dw > Aw)? Dw : Aw; - - + //vjtag vjtag signals declaration + localparam VJ_DW= (Dw > Aw)? Dw : Aw; vjtag_ctrl #( .DW(VJ_DW), .VJTAG_INDEX(VJTAG_INDEX) - ) - vjtag_ctrl_inst - ( + ) vjtag_ctrl_inst ( .clk(clk), .reset(reset), .data_out(data_out), @@ -764,61 +595,46 @@ localparam VJ_DW= (Dw > Aw)? Dw : Aw; .status_i( ) ); - - - always @(posedge clk or posedge reset) begin - if(reset) begin + always @(posedge clk or posedge reset) begin + if(reset) begin wb_addr <= {Aw{1'b0}}; - wb_wr_data <= {Dw{1'b0}}; + wb_wr_data <= {Dw{1'b0}}; ps <= IDEAL; end else begin wb_addr <= wb_addr_next; ps <= ns; - if(wb_wr_data_en) wb_wr_data <= data_out; + if(wb_wr_data_en) wb_wr_data <= data_out; if(wb_cap_rd) wb_rd_data <= q_i; end end - - always @(*)begin + always @(*)begin wb_addr_next= wb_addr; if(wb_wr_addr_en) wb_addr_next = data_out [Aw-1 : 0]; - else if (wb_addr_inc) wb_addr_next = wb_addr + 1'b1; + else if (wb_addr_inc) wb_addr_next = wb_addr + 1'b1; end - - - always @(*)begin + always @(*)begin ns=ps; wr_mem_en =1'b0; - wb_addr_inc=1'b0; wb_cap_rd=1'b0; case(ps) - IDEAL : begin - if(wb_wr_data_en) ns= WB_WR_DATA; - if(wb_rd_data_en) ns= WB_RD_DATA; - end - WB_WR_DATA: begin + IDEAL : begin + if(wb_wr_data_en) ns= WB_WR_DATA; + if(wb_rd_data_en) ns= WB_RD_DATA; + end + WB_WR_DATA: begin wr_mem_en =1'b1; ns=IDEAL; - wb_addr_inc=1'b1; - - end - WB_RD_DATA: begin - + wb_addr_inc=1'b1; + end + WB_RD_DATA: begin wb_cap_rd=1'b1; ns=IDEAL; - //wb_addr_inc=1'b1; - - end - endcase - end - + //wb_addr_inc=1'b1; + end + endcase + end //assign led={wb_addr[7:0], wb_wr_data[7:0]}; - -endmodule - - - - +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_modelsim/multicast_injector.sv b/mpsoc/rtl/src_modelsim/multicast_injector.sv index bce9d4f..142ffb8 100644 --- a/mpsoc/rtl/src_modelsim/multicast_injector.sv +++ b/mpsoc/rtl/src_modelsim/multicast_injector.sv @@ -1,497 +1,376 @@ `include "pronoc_def.v" - /**************************** * This module can inject and eject packets from the NoC. - * It can be used in simulation for injecting real application traces to the NoC + * It can be used in simulation for injecting real application traces to the NoC * *************************/ - - module multicast_injector #( - parameter NOC_ID=0 + parameter NOC_ID=0 )( - //general - current_e_addr, - reset, - clk, - //noc port - chan_in, - chan_out, - //control interafce - pck_injct_in, - pck_injct_out + //general + current_e_addr, + reset, + clk, + //noc port + chan_in, + chan_out, + //control interafce + pck_injct_in, + pck_injct_out ); - - `NOC_CONF - - //general - input reset,clk; - input [EAw-1 :0 ] current_e_addr; - - // the destination endpoint address - //NoC interface - input smartflit_chanel_t chan_in; - output smartflit_chanel_t chan_out; - //control interafce - - input pck_injct_t pck_injct_in; - output pck_injct_t pck_injct_out; - - - wire [RAw-1 :0 ] current_r_addr; - - wire [DSTPw-1 : 0 ] destport; - reg flit_wr; - - assign current_r_addr = chan_in.ctrl_chanel.neighbors_r_addr; - - /* - conventional_routing #( - .NOC_ID(NOC_ID), - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .T1(T1), - .T2(T2), - .T3(T3), - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw), - .LOCATED_IN_NI(1) - ) - routing_module - ( - .reset(reset), - .clk(clk), - .current_r_addr(current_r_addr), - .dest_e_addr(pck_injct_in.endp_addr), - .src_e_addr(current_e_addr), - .destport(destport) - ); - -*/ - - assign destport = 7; - - localparam - HDR_BYTE_NUM = HDR_MAX_DATw / 8, // = HDR_MAX_DATw / (8 - HDR_MAX_DATw %8) - HDR_DATA_w_tmp = HDR_BYTE_NUM * 8, - HDR_DATA_w = (PCK_INJ_Dw < HDR_DATA_w_tmp)? PCK_INJ_Dw : HDR_DATA_w_tmp; - - wire [HDR_DATA_w-1 : 0] hdr_data_in = pck_injct_in.data [HDR_DATA_w-1 : 0]; - wire [Fw-1 : 0] hdr_flit_out; - - header_flit_generator #( - .NOC_ID(NOC_ID), - .DATA_w(HDR_DATA_w) - ) the_header_flit_generator ( - .flit_out (hdr_flit_out), - .vc_num_in (pck_injct_in.vc), - .class_in (pck_injct_in.class_num), - .dest_e_addr_in (pck_injct_in.endp_addr), - .src_e_addr_in (current_e_addr), - .weight_in (pck_injct_in.init_weight), - .destport_in (destport), - .data_in (hdr_data_in), - .be_in({BEw{1'b1}} )// Be is not used in simulation as we dont sent real data - ); - - - localparam - REMAIN_DATw = PCK_INJ_Dw - HDR_DATA_w, - REMAIN_DAT_FLIT_I = (REMAIN_DATw / Fpay), - REMAIN_DAT_FLIT_F = (REMAIN_DATw % Fpay == 0)? 0 : 1, - REMAIN_DAT_FLIT = REMAIN_DAT_FLIT_I + REMAIN_DAT_FLIT_F, - CNTw = log2(REMAIN_DAT_FLIT), - MIN_PCK_SIZ = REMAIN_DAT_FLIT +1; - - - reg [PCK_SIZw-1 : 0] counter, counter_next; - reg [CNTw-1 : 0] counter2,counter2_next; - reg tail,head; - - wire [Fpay -1 : 0] remain_dat [REMAIN_DAT_FLIT -1 : 0]; - wire [Fpay-1 : 0] dataIn = remain_dat[counter2]; - enum {HEADER, BODY,TAIL} flit_type,flit_type_next; - - - - wire [V-1 : 0] wr_vc_send = (flit_wr)? pck_injct_in.vc : {V{1'b0}}; - wire [V-1 : 0] vc_fifo_full; - - - wire noc_ready; - - localparam - LAST_TMP =PCK_INJ_Dw - (Fpay*REMAIN_DAT_FLIT_I)-HDR_DATA_w, - LASTw=(LAST_TMP==0)? Fpay : LAST_TMP; - genvar i; - generate - for(i=0; i 0) ? router_chan_out[x-1][FORWARD] : - (IS_LINE) ? {SMARTFLIT_CHANEL_w{1'b0}} : router_chan_out[NX-1][FORWARD]; + (IS_LINE) ? is_grounded : router_chan_out[NX-1][FORWARD]; // connect other local ports for (l=0; l 0 ) ? router_chan_out[fmesh_router_id(x, y-1)][SOUTH] : //not_first_y - (IS_MESH) ? {SMARTFLIT_CHANEL_w{1'b0}} : //first_y_mesh + (IS_MESH) ? is_grounded : //first_y_mesh (IS_TORUS)? router_chan_out[fmesh_router_id(x, NY-1)][SOUTH] : //first_y_torus chan_in_all[NORTH_ID]; //first_y_fmesh assign router_chan_in[fmesh_router_id(x, y)][WEST] = (x > 0) ? router_chan_out[fmesh_router_id(x-1, y)][EAST] : //not_first_x - (IS_MESH) ? {SMARTFLIT_CHANEL_w{1'b0}} : //first_x_mesh + (IS_MESH) ? is_grounded : //first_x_mesh (IS_TORUS)? router_chan_out[fmesh_router_id(NX-1, y)][EAST] : //first_x_torus chan_in_all[WEST_ID]; //first_x_fmesh assign router_chan_in[fmesh_router_id(x, y)][SOUTH] = (y < NY-1)? router_chan_out[fmesh_router_id(x, y+1)][NORTH] : //not_last_y - (IS_MESH)? {SMARTFLIT_CHANEL_w{1'b0}} : //last_y_mesh + (IS_MESH)? is_grounded : //last_y_mesh (IS_TORUS)? router_chan_out[fmesh_router_id(x, 0)][NORTH] : //last_y_torus chan_in_all[SOUTH_ID]; //last_y_fmesh if(IS_FMESH) begin :IS_FMESH //connect to endpoints diff --git a/mpsoc/rtl/src_noc/packet_injector.sv b/mpsoc/rtl/src_noc/packet_injector.sv index 6f48817..a385792 100644 --- a/mpsoc/rtl/src_noc/packet_injector.sv +++ b/mpsoc/rtl/src_noc/packet_injector.sv @@ -66,7 +66,7 @@ module packet_injector #( wire [DSTPw-1 : 0 ] destport; reg flit_wr; - assign current_r_addr = chan_in.ctrl_chanel.neighbors_r_addr; + assign current_r_addr = chan_in.ctrl_chanel.router_addr; generate if(CAST_TYPE == "UNICAST") begin : uni @@ -350,7 +350,7 @@ module packet_injector #( end end `endif - + end//for i endgenerate @@ -448,7 +448,6 @@ endmodule /****************** * ovc_status *******************/ - module injector_ovc_status #( parameter V = 4, parameter B = 16, diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index 00712f5..3e546a2 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -19,6 +19,7 @@ package pronoc_pkg; localparam Vw= log2(V), Cw= (C==0)? 1 : log2(C), + NRw = log2(NR), NEw = log2(NE), Bw = log2(B), WRRA_CONFIG_INDEX=0, @@ -111,7 +112,7 @@ package pronoc_pkg; typedef struct packed { bit smart_en; bit hdr_flit_req; - logic [V-1 : 0] ivc_smart_en; + logic [V-1 : 0] ivc_smart_en; logic [DSTPw-1 : 0] lk_destport; logic [DSTPw-1 : 0] destport; logic [V-1 : 0] credit_out; @@ -195,6 +196,14 @@ package pronoc_pkg; logic [MAX_P*RAw-1: 0] neighbors_r_addr; } router_info_t; localparam ROUTER_INFO_w = $bits(router_info_t); + + typedef struct packed { + logic [NRw-1 : 0] router_id; + logic [RAw-1 : 0] router_addr; + logic [NE_PER_R*EAw-1 : 0] endp_addrs; + logic [NE_PER_R*NEw-1 : 0] endp_ids; + } router_config_t; + localparam ROUTER_CONFIG_w = $bits(router_config_t); /********************* * router_chanels @@ -247,12 +256,22 @@ package pronoc_pkg; localparam CRDTw = (B>LB) ? log2(B+1) : log2(LB+1); typedef struct packed { - bit endp_port; // if it is one, it means the corresponding port is connected o an endpoint - logic [RAw-1: 0] neighbors_r_addr; - logic [V-1 :0] [CRDTw-1: 0] credit_init_val; // the connected port initial credit value. It is taken at reset time - logic [V-1 :0] credit_release_en; - logic [V-1 :0] hetero_ovc_presence; // Indicates the presence of active output VCs for neighboring routers when heterogeneous VC support is enabled. - } ctrl_chanel_t; + bit endp_port; + // If set to 1, the corresponding port is connected to an endpoint. + logic [EAw-1 : 0] endp_addr; + // If endp_port is 1, this field represents the address of the connected endpoint. + // This address must be set in the header flit for packets to be received by this port. + logic [RAw-1 : 0] router_addr; + // The router address sent to the neighboring router. + logic [V-1 : 0] [CRDTw-1: 0] credit_init_val; + // Initial credit value for the connected port, captured at reset. + logic [V-1 : 0] credit_release_en; + // If credit_init_val is zero, a rising edge on this signal triggers credit release to the other side. + logic [V-1 : 0] hetero_ovc_presence; + // Indicates the presence of active output virtual channels (VCs) in neighboring routers + // when heterogeneous VC support is enabled. + } ctrl_chanel_t; + localparam CTRL_CHANEL_w = $bits(ctrl_chanel_t); typedef struct packed { diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index db9e9cc..44e6c38 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -31,8 +31,7 @@ module router_top #( parameter ROUTER_ID=0, parameter P=5 )( - current_r_id, - current_r_addr, + router_config_in, chan_in, chan_out, @@ -42,16 +41,13 @@ module router_top #( clk, reset ); - `NOC_CONF localparam DISABLED =P; + input router_config_t router_config_in; - input [RAw-1 : 0] current_r_addr; - input [31 : 0] current_r_id; - - input smartflit_chanel_t chan_in [P-1 : 0]; - output smartflit_chanel_t chan_out [P-1 : 0]; + input smartflit_chanel_t chan_in [P-1 : 0]; + output smartflit_chanel_t chan_out [P-1 : 0]; output router_event_t router_event [P-1 : 0]; input clk,reset; @@ -73,6 +69,15 @@ module router_top #( ctrl_chanel_t ctrl_in [P-1 : 0]; ctrl_chanel_t ctrl_out [P-1 : 0]; + logic [RAw-1 : 0] current_r_addr; + logic [31 : 0] current_r_id; + + always_comb begin + current_r_addr = router_config_in.router_addr; + current_r_id = 0; + current_r_id [NRw-1 : 0] = router_config_in.router_id; + end + generate for(i=0; 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

p*2B9Oa_e2N82`Gnz@el9MT#%POscdYIBi;6Dw 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 vMnP0E zXkGZb22ev-Ke0Wqc=ZNkuw7l*`K-v9N5hQ%FD8HYF9xv>uNICm*L^c|a5R6n-G$Xj8ApZDa6W%k|jL&hd;yRt1I6vWMc9EBAcr8B24_lf9fki<0W z;1km6S^|(|oZBE;XkXg;F>|trs3^2}D#(aJonCro@0$24qRqVpom0Q=`c2yP80zWK z@DwZUPy4X^I6M6A-H8(?u(h>O=%5X%oI3v4A{**9G-b(AQLTXLf@kSFV~ihTA~qXX z10gEDl?lh?*ApOVyawO45mpW;D*E4i$~FSTg(ukGJ&7W)okn?FtGCs;a&iCJ}~|C^?W{ z-7Ao?Ou}M7Z?BC?2riYFjQfDtDt7!F&1nntNT3w$U8m+eQd;5-rv5~GGLkWa!K(Pv zVFrvnY&SW!c@u8spYyn_5YCF3g83e}iK!pV{wLX4@pR5Pa`Iv~XTfnrJJn0KGtJ3x zt#tCnY(CeYQK`b_^YYYxi5Wtfyu`Nna{+SK#9u&~LwK=k~vVaKzz`>g{)=HTtWUw zH5wmhqA}A&X8Bbfp*u|BJ-GnmKzsp_u~#YwH!C%jYW@H-EL6>B{ry4PMe&6n6Hf}S z0EBI|ty|aX;1kGaFqhg=H2!qop#(DOuy~WVc=1k>{;Jv>a%S+X_+Fugmth>;pLA>EQu` zlMBHschXyq7omZUZC?D;Q09$>1?V}bnKB8+h}QLqJh&sv(hZGIR7V<7!L+s##C!al zR@FVST1$l32V^NIt}v@`1hKvSH0$F#e@xt!h5S zWod1FJ0U?(SeSnWdSe(|0kM&0wqK>Yg1ZOH9vC-3UluQnnm}Pkv=#)vy~pW;-qH;I zB#ys%(}Mgl(|2=@w9cFU2-nrU?_IfW(U$#M@Kra z(dC~HR^TO1aJGMcKf!f*eiI?|+I~HXDYIm@qF2mr zr9}R1UEm$V%Ma%s{A?v-Hzc+}Lk~D8J9}efBO5ELimEDB7m7dyp_x3kT!4*euT<34 zuSZ2?7w^g(-$hXn^K9*3*W$D#!8l`7w!*C$vxMH>IaFF`Hpd+73iX-vGP^-xyRCdw z5-lw5gz|NUuC9|nkWiW;b%Qw4OJPcZFI82`p-VYJIf+@AB_y`x9hw{B!})XvJ|4LB zE-uaWgZ_i~l6o+u-1@WE@wMW~fHDO&?E^f240Pbk*kypd?uc{$nT!s8s_9| zn!4ku;FOm4k(3q^A8FexXCU(h9!(PI8a0EaOuIm3sv$R#8o0I}SYIf`OIk(iHj2zk zBZdWgEP*tm2qCCv@$oR&u&@C74CW)$wAhmHj>Io8Ry`1RaM3%*I0Jx|Hlz_yWkb=2 z@ydMVsmJ5+aDfZ>AECU`)4+Lz&;di0OI&JAT~7t&N&NgbL4<{h2q5@0yc!(0tR#Ls z>*WReS4|Y3mX-pW%Ln1Hf;&S$t#G}ZrS2@JCV7&fE%}Fmg*0~sR|}cFlVg(7vr*74 z#jB{Kw)Ea+9w+0Mp#BBZm<|&SX8$#gTy1LfmMZjD>!&MD?5v4uxXiHyz zw9@uaA9|6oHRku{6XQZ_=xeU6*E9iPhNK<-Z(&VS1>u6saPrO-|kdP3gbl%erZFamA8hzYj!AlEj$L>0V z{O9TU1^3*PR#wi#$^)EYtgvNthMD6j7jej-mlNOSy{_mIeQN5^fdd3r z9C172(dA04)XOCP3a*;wUc+EH>Sdaeqj0C>9)L>Sq1kf_9!Y39zx>OSCDX^pg+xW~ z;C90Ojqwaz4&K8CxwaM6J&gKXfDM5Z1d}T0@dgJ6FTPyhKRVJSEBox_OFQ*dl*8n0 zyll249;yaSFLkr%(bcqKH}i01mDRTFpP5~0N2w&%oHth_se-e+FAL{(#gTOTm}}Q;6|7I6&IiEW{d|BEuMt#746rasAl4w- z+`DilLS5LCOf4@f!)b|B^I1q{(E|g(-!a&oqm*R2R=)K1g=5Txq&*Z$j_Pq)IzyPc zWtuf*I7dRBr;}xvdJ@3i>RB!ok|y_OvM-5&ZbsjxQo3{ExMc!M7D?Aj_-}@>X#WlF zKRw+((O2!Nf)~r2pJZ9f2^=p1YJ`t9fon8q{s(cvqU!?<3k4+9jJ?_qO_dTeA3sL^ zmLY-=lhxbt>K%4pRIaM(?BC6y%xbY=VL|$C`d^~AescQD(uGbSS6*I$;9Xd!xdlaA zKQt$!D#hJKL>^}gQU3xoT18H`6*^=4|<2* z3*p)4$?}=ZKAmAM%E_GEj=JCa{DpSzaQ!K;w(!`%Vn7Wi3;RB#+y8~z+=1OUT0a3e z$BzDuiscmys6YmA*3pfkI;M_qZxo&ExxzTjPv_?4mZNg$iKMdpBA1a{X=iATba`Hu ze_SmjAG%0qi{$Ffvqz=HlgP872Wh;tUku_0Be*zXqZfbB8!m&0>OLGa6Zv1Ci}@OW zu|S--7{K6dj8>JIDKVhkk9U4*%&yZ9)O8Ng1u7aMOh(cyJ@4`1=T{^CoL^4=n}zNbHmR7 zFHGi6d{)e?V1)G#oq(?vwg8cO38BFu7&vS&u`ZPp3!G8ey!liD3==VR0ICMTnJ>-- zTow1Wx?Bg*smgS@)yW$^{+BQBg3cG49B<+YxkLB#+&SZHhGp9MpFT^W%W4;w^z%0K zG8y#+yNkt0ii%dc^}^)1UUo}!o>7Jc+$m+(t$W_wTo2(8LbbHD&j$rTpE}grn_#eJ zXH(=8iC41U&vdl44PlOs&J_|H6bj#4y_+6CR$1y~c;<3#&pIM*(#vbs#dgs|_9n)$ zJQAAbc6M&Z(xTKk?CwTeXPA>Qmw`a=O-qX_EQu#9&cF3JHWt(}DSzn&X~34ax!hv*eFRPhWJ~_o0#|m@fE+~>Zp_jSG2rM`FX3PrGn+5>0;n%V5cc6hX`9-pPG zBBS_8p%q0?km`D})l@{f;00uGK%sG1Umrn4#;x)ZI-_WhF;M^c(nJAsFb@D%A8Kd_ zZF2ZmQC4y%TNLK9+e^0bJG4xw9L);Em*lID&wn{L(HpvjDrN|A8dh~I^hhPc#Q-h3 zien1+hm=jNMZa3{rfW@Kz}c19)b$~b0MnAtaF()zr>9|-5t6eJ5&7IRJJ+#OjZ+fa zIf8-^b)XJt4MhzpWtd%A5u}5vj?)W63E~d*e0&~1Omu1`@sp*=jKaht1Wh}wEnD;M zgly8HA7S+3vLjq3wyRy0bLF}_IWh6%qGs16?YvIhi=dBiSAgPdfl4q4A=s{#Iq2S? z9K2Uo_YXG+=uJGexg}Oq(!Pxl_~Oo?XsSW-o{0kh2Fw6%w!0}Q__6q(?GR$(yc!7} zPrq&uzyDyp8E%kJbG9Uc0pUlNOQG-4RMsuNe%cn=nsQbPVP zwZmA-3i#pLHMI0|SqeGh0+=exJ5vLLVSy z$ppSFTV9R(VC~s@X>>_nUu43Pj`&?{Z&$<)MsRYgD=W$)3^;$xvDwIPmM`|;UqE44 zn5%x`MCZmocE|A%@dxv2j3qj^==9}{qBQBsLuxrVdGp_BeKVf0YUpB3ykbAYbjAGE z(A{QPP>47dY!aI~Oa<0Mtid|}CCw21rm6~$44_l#Bv0&XRLqc%w3eSLk=SU)=@ z(*vbc_Y=<0nGJ=hK3tTA_ZI7#vjax{3^}-DnnB$%+2w) zOMQ<6cLYzvQ3l1^zT21;c`h}$5{~|}?=U=Ik5O+JjW!ZiwrxI#rUwEFY5Sus-*vRL z>jASPoq&R%*xSpawZQ>>^pbnA%O`Y(!WuV@la#96oi}m?%flw z8i^@KapTzlJAp+LWQ)`L`{=~G_$xlOJ>ZH2N(`M1?xIg09z4#;`HHuXs|9n16#~6c zP6-l@Y))A-`+v#cN(8iLnGjqr?OFaV%y^AaSVphjtmB3$oxmJd^~}ol!S^4owA|SN zD5EbY{u|0XNL2uTV{>z$8l7+?qZ8Y+cdv3KOYyg{FJEv&qVpaqGh>o2zSFMrA67_B z$2{?=xF5|1#OsJsx{IZ5>FHoeHn6n=d#+urP589hQelMn=N^+k)X>*=3FaoCS=Vpg z+(2Ta@5PI&OFx8oc%096-SWPN&yCes;GHbcG~>wN^J9}{AvZKUKy`uw41ZiQSQ64a zM$yhfm;k-%X~3K4AGSI$*gQajpt;c{)&_U2?kBt45*UrNO$;R0TTl31zLH;3z9UKO zqqcW2Pj#4m36~H-ngxXdhnyhN4N$%DJS_hC^Uz2F*SGe{U%#_wzn)tUU?snKlaH1F zBQ1p$z1Myqi-U)sA0`@Kz-su0zWCHQlrQ5P#b?Dk$4l>Fh#uA5Ua^`T35=3v`{Ev% z6nynzkI>nEcY5hu;g4v7#8#6Couj!^w_6sgV+&04UzC7kSE&p>+p1%0`x18%uu_l+ zYsiG4EV@9Y0RfwwlG3f3hvy&Lq6&dMQ1ZLL_egIzJ*3hjpBNF7BTVGZjqN4{jBFOB zks=vodQd-O=4C#Ji5MF66KD~f{;ZF_f^-~=9Cn{}bjV3cer(H?E>Pf?jmug-zjcUo zgT6LRhO<>TzSj29ofbRAOx+MhHhqyh4To932A9rBnB}wSJ|v{j>{E08VZ(1K$#uFZ zlx?6{A~-b3n*2EGfb8e+`syvtkv|fPTwPrCL_bhA>Vnb0!vqM0W3w#)4FGL;&cGeD z31l7|`SBwd0-SGgIx%!V19zEH?cQC4aRf7y5Moi$uwiP(ifCA-p~zMS;QgdA_edLW zx=z-kM~{MV4!5NSCnoH;^3PZA@1Los!dNY&kW%|VXMQcvAZTq+^?ds0z9}3;97kGL zW9LQQ{e`XtVX(-k=n_141n$!)9{q%jj9}n)xPt*~QzS>wAlf)S|Mu-0_NjEjiALG^ zg1V2#;bBb8WZ>reRLmiDTKvAdO?Q-W?jbf349Pp}ww7^CZ0ah#6Qw7LmIq@PUQ3c) zfJ`u>Lc|5RpZ}a)?7QvNzMFR}W!~wzBQtn;OK=_OC6k2MfPT|>UUJ_SmDjg+d;i?T z#TuC;U??`?Bf5U{^_a3(p*@?WP4s8CfD~4L{;wB|rO1zEM~zz9L~(=dT`pkD5%EyH zC~g0ZHOW$rsj$a7E4LmU0btg~*RK(?=iXn{_VHKn$xbZ(GdzC$=Jo5V?z@+VMWNI} zmxMrLD|1t6nv86n9c2|2Q2yS-UM_Ua@Z5=R-;U=Kz;?5pQRuzNsnaJSS@P&`<#f*LYw6fmA(J#cHC6a}k2NoDb&9?Z zw>Y|UoV%~TFTnYN9@Th>!;CBDKvxb4MkKZy%Ej&=)%W_Qw|n+shYy zX`*T9Sp045as~9}lrFFw4(~gh9;V!x^->=cVP@H=ZDDzL>A*bxTWhn-k*FT!y#c zLYC_6kW*Al#Yco|0x`&2A+-mjW#15v2s#{?!S{xC?a#=#b;}DE0!xhH+D5O8`3wVh zp|_|T6m@9+!EvA+0`Cn+t(xzY5?sen;Q8)*j+;q7<)}yW*FzYC;BLSRFfS%VJThfT zNj;FZLtr`e_&0=eKu)>vtHG85e&*_5>(3c}B$l}~-$uoe@Sc2?)I*4Hb#V9y3mndq zKbY%R5ez`t!G~^juD7E3!-w)IM~*4Kriq#P^_~_n=3hio)kDH9o8>=rfv4^VhYQYT z*)AF>K4OX+s*nB7bGr2HJ`Z!}E!mLloj3uV;q8QkN_bvy1lIbhqVQ0LF6@`cExFBB zOb3J&q7I6&rH1;$1NNXf#>#s@?y75Q+HlT*g~9`PH!trTS^|(W{b-+`K28Q1Eyl4a zLT7)5>{f)SXMx9HjNs(tgo78+lVTj+oLG4BpTTx&H*|L(S^;XbV)pvRQ85D{{{6Hx zU`&A;Lx54S&=eFWCG?~f=1V*pZB7)X7F@0AiR(>YaFc^o0@;giJwz+BsAw8mnz1oO z0Cy0ZAd`q7Cn`1h%6n(f za-GNdheioavFm8-zhlJP4Ptc*4!Y0cVKs?}H~?q+IuS2jKT7RT;lieG zEJey1+Aw%`>~ntngGUcu9Qr8PC7zR??@YnXqoXnBSwN8Xe4QU^b!1He>cLFlnaH5b zYim0UQ~_j3@!oq}&YZ5wTN!h4%%J79eS8*Z{pO7Jo3XLb9;sso-h~TpP*CZKVkaUl zulQY*R5Y7;omeV^7lbb{O&>cu73JjMod;`UOdG8y30;wd#GAG@Y=eMH`Qc$P1!d*M zpFb!2DvOGXr4tOW9}(X~M`icaNnthw)H17d;ZeYcp{ zSv>1F;(lD|L(}4P>eK*bIk>Cq>SS1#7c}1i&<&vs7C(>U3i`%qCdL7WCN2X0d)CPb zCDq*2bYf}>wGj?f-2N-8tN5P?i#mnorn)-0c?`}LZ1t;t{v0WYuTck(5^Qdsq$i3S zUZ;VPCKQDbZwFKtcs-72#3P|3R8}s6HpVTF3i8?AZ?J;$>_}`)gyxTvlRXPW4#fuq z)tTt+Hv*Jf58+8JUH!A+PL zKqKW&=FlV}XG1cfu^l!+oJwFEQ&7wPR(V*BH_K}sR~W$6hG4c@lfJT;e|s6x6ak8 z>uB~-laAz==9;+t=e7ZlhINte-o3*G!wWNS4kJ`ecz`sHW2+^;mzq;0CI#1SAXf)F zdci9KoPO{i6p_!AWk?p5mb=)ng+0WiAjhNthAxcb5NCjG5~5(!6X&rI23ku~$v_Po zn8a{ET)G5cum>VF)WF!-W5CovsG!;C8uB(fhMmc#l9licJQxe!k0^DJN&vQyF@RLb zf4E>MrWd@uH?gqzdV2>JO_|!-2BSqpL87c81(R)Mddzk2JpV1a0OC!O#K`Woz$@rPj%P_N z+{qro6K#38B|<0q@8pQtgEY?H6L#`)l{>Gme7?vYGJDG`RK37r-?sOQX=O#lx@JOf zvI1?zJOd`%8s8|KMAFhUcpz=CM+D-1&3X2ZR6rV_<3a~WA`xbJ1f<2xrqeDH|x{T2eKh-*m_JaTYhs;D?Aq@Z)u z8z=ndSzTOx1~)CpYMdUZCb;APU7$_{tAI1CsLsb5#TkluD9F-6>JO=3uk51EHLF8{-}2d)^I){Xk`_xlWj)I>2HKuBI*{u6jFJ_Em{h9nyU zf_;JPW(vgoazUW;6$2i0INg1V;rA9bl&{*PaYI>(M2 zfh0(qvMFl&AspE2<@>M5?(mhg|~gz?IW4 zJaLvnM-Q?AM9X@Imx6S+26Q_(+mJUGQ(5VIq4_~>ipx*me9_yO`mND4BAaX$>x|Lq z;<4yX5O@?>Z^x#Rh_elfISMU_egNbS(hza%7&8|RDXOre^5RztA-EO1H|V%I^i;k@yNh9Uz;)R1(UZNu1_fz}-zH_ilSnS?uZPsEqtEkJfuu zh@U}G#8Zf0idsJi?16r~An{Y2p6Ch$I=GTxdMg5cI)GhLn>+mZE(Ke_;nb1PiH87#ZnU_{5T0v7_e)AQ$w=kfI<( z17#%e@@0J2kn*s!7c21Gfb1Qu2pVoYjwKf55A0umK#Pwy7r|#%`oAZ$J~%gOm=SP? z<5tJ&7)i+~)I147)FQ z2f(?}li^rBgUUViqV$x^Fc1=CB;kuFPRR4sJAS+r$OV4HEO#G&sOjNqxk(y@V}EP@ zF}w5@tx;50Q2qj`N;PNaP$r-x9XWdR>%s~eM>JsYL4#ts;N{gZpVErs)T%b%C%k6- z9X6E22%L?!&;5>F{@KljN{7G#N9auRI#GZ@*y6FpR0z$>#@q=#E51K-v`K&Uw?ngA zQe-;dW(?n5pqi!#4iE6taen2%#F0U`>oG9^Re1Z`pN zdSg=)Fg7Xd8o(|g#D>8Fh^`+Z|AX1E0^-KHeCZP8?QE>R$5v;}3&`IWuww-A#I`Sj zQqt3*Igm+s3#IkoKp*}h)M;fFEJ`haci*(Pw*xqN^9DT$ausk^#=6f?VvYyZqFz@|oe`R-+*9!0*QMc?QYZ@ke&W2M;spn;I?JO|cfOmoXFjD+9;6 ze{FKEkEy`Pt_ZFT7}w9~RMq8$<8Q{>__y+A5}ioA9V}Yf+6%82v~_f|OxLrGaLi+? z7goJ_;(&g3`6bdtfGgUnS05jg5aAB(^SW>X;xLM13*;Ws=cWc~DzdZ3V9nT6G>D@Y zB?g?A4xT;ar}p*&ma(+9-tyiJ{T0iew4>rhSe}N}Thh|_CIPGgYC^VP<5nff1kA(^ zZf?_ab1DJz!VPh$^>$r#!Wg%)N}2LP*A9g0+&QQ^V)R6@)y=`70d~(PE{gc;|8vp6 z1)lwZ&+@`A5H)C##CPr#f|Ubzq3?daO@(ytPyXw2_G2+od|*<5W&?^=KMF4PZ*>-0 z|AB#8VqFz70&uZ#5~3CU@V3*+SUW!IPQcgu2R_)|+Nvu;rDake@s-b3Tqm#a?5&@- zf;Z6y>l_j~I8-)8Uoj{5hqi!rH?MSMhsj0>J{x`vPQCMsGEY9=@VbDIOyn^y!D0Z2 zUR6r!QQYNyFfrkCU(V?Y)1k3Zxc)=<`?f|}xjE({qhw$DPQLtMmOFZ)xIW-3F9V&S zaB}|sfO;D3Y&J*1Bq+%h12uV4D|B(dn2w{8_|)L^lT5g76mSt&BM&<^|C=Wv5HOWQ z)&l-SZfVEsqgdeqoxhPpzG)%UBD*)16Wf?Kt@eHG?3egY-+-#t2arl|Nwh@FoC$nV!F2Oq08{ z;b{Dj?i_9W;2}rBc#h1?OFvu-B&BsnmA4KN+89=4%4V1r?08nR@v3YmQ&Cg$&7j19yv|TU^Hf!r-Iz*w%=}2QdNZx zgJshuVx~z!qeHoogqZje#}p*_kjgu_-ouoibrP|y@=l=!xln3$6oH8G-4K6!_A%%h z+=D>yFhQbRAh&XVMyaVJcC}($#vBRK8{HLpiEH&P$NFgS6EWXlw<2XH3%(PiQXvYm z+~U!yK!g)j>x*MsG84u1a!q!Ki>L4L{(`mz?~^iIoN>CxKog2`hiIh@v`~F+WBqS- z8{LjvD|)jbOCxJ+Ns!=6Hd{R>ODncRV%LF|(-RZA?Sl7*$|h*H%TBnS=qV22DljsW z>_+#F!#Jnl+lq#rh#eK1W12Zh%x+glWy;v99OPaIYQcO4$AXM&CLBNV@{|Q^d_(jP zZ|4ik5Pt0aC7V4WDQTnontnY^(}*a!mu50QAa;Ps&PsP!fNLLllD5k2^e-AEJ`aeE zA({m1G+6DOT~gvH&5vXL^y$IAr%2m?dxGax>-U8~4K#gQ{xeP#m}0`lQ zgJJc6NzN)*{-?~rQ3-qqlRxSRrf}*G;3z68Rg}E5UsHq6pW!MFs^$g}}uH&<-n)Yj3N@;|oMx2a#4{{j`L0uci_Q z=h+|zo6(K_=L^*j=Pm}1WQd8~3TOLs<&ahr3->_Mv!2{4wfDz8ewdx>GqhGut1|RZ zFYdfll-75$-}T3DL+j$xk3M_vejw^;!Rh@}(vcAmJSQ z5#PYuLLU!oQ_uwk2+w?~M&RRO>Oda(GUjXa)d%`HNCCpshs(ZS;ssU{v|kg)qDs}G zAsHndO_lwtNMBvMeKcpnOPC97jUNjoOy;*zpK-P><%(Gqb&fH<%9El{%^KRihvt2_ z#^(1n(zV%`jfb!`=jFfI^T0TR$6{4ao$C8Q!$fklth739VG)4F0253?d^}bTVO&dU zbyVQ($&*cLt+BrcoDYvjVPPT8*_}HN6`x!P(0~M)D+cR>4069LtU!8rYSSoanvM=5 zAO=O7**y35V)_Gc2rGG{Jtj~DTK>k~JY$Cs{LV`EP&_?{UkH%V!~y>t_%&;3jj_XP z`T&B(6Ne7iwaJ-k`?BOl8ToEj?y)PNe|FVVoKV44X_?=q^WL0|zQIi_^c#6M@uM7r z+N!zu;Jcp+rgb(HHti*ndHiafOBr}*<+Nyxn77d!r0$&AyN`Bce0)bzD;n2M*GQ|= zr_7wecQGxg*oZ0o8(yC)``!6fg`IIqNq zOJ!3E#XG7Ax*8lvl)Bo&*-Qr5P%8F%kiV0L-;?kIj0wk4SqAa)Vc>A^+PCF)A6 zD?p}z!-K=bCe0v_+X6pm9W4J~bP3-0I}8odQnTiIxw-5#`JSDrb|6k{r>@bh<^)XL~Dl3JYhR&Mmkk z5X05y5HF%^78~pW$Eau~Q+13;8cdsr;jSn}?(4Q>k9+d;Ou^Nbje^z=5z- ze?XZyGT>l1pVj*jsVU>*v%@bnAutdZcY^u?d7qEq={i{iU=~3fM`2|Ee0A(tEJY=$ zhY=XJEQ$?8Ae$H&T_4%`3gPEsW?5cd7S|*eoh(8l4^I68CIE~jh~0{5`hu?&L*0K= z#w-x>FJDBrGOAzYZj615UvkXAK<&ae3VRK_thDqz5Ecj~Y%fjb{(U`pCq2s1GS`GM z!XP&X#{~$0O2Bn#3e~+1<=Y?t!H5<-RgiZT---WP_~u7{xIC{!-l6W`B+fd^T$!|{ zxh&GhN~pRY{{GqqAAJpvzocE5=jvj;303uWsc{OFrX9%wSZ8}&^6O+Q_hI+c^Km-t$q_RO#a zjU8se;FVU}A&4L#wS;IwBY-c`9@3lrs}tEMIIMh1&PcvsjBtQd0(K70jCTM3@VD4& z*LV{*8sy=nQk^M+j!ZwY;L5gW3mY;=A*V|j(Tt!(~*(}QlwFy`}P7kyeI1&J6 zY~9+(BI!K#*n|1i0AOf1)iACgI@C zk+!m|UQ~sIyRl=g#yA-v?r5FWmudy`{&w7lFXR$yj9@pnaq_jt*&Sc4G_|{3{l7DI zWqR#o^bg$`{v&|q{lSr=Zyd;5G=9B-L}(mUZiBM29vZ9<&S+h*@&eii%3cbaIxA2M zLjS$+{J}YfB80FQY&`c^5&(*DN5Y;3FDy}K0)lM$s2Q3#1h4O|9Y{60uKpels(^n+gh5XrHZGS)#H4fw$V zItb{^&MHi|GHd1|b|QFVDHu{#N_jL<45D_E;jR$+6(~3oM_5Yq6W*7;-7z2XS!n5T zpfAmrO}{-xBJLsN5JgDr)wF~FR)#VU3u(+MSV16NI%k2UXGpyOqTc^6Bhy;$V7!2i zH;1I5mO0~V28}1@-B#%t79vaeZ#aqBhMc%P z7d7c^o`nSqMCs8)Gtem-6#iWH(okW(;}q3CC_rte*W_)QGuopn5~D&Z^G<^4`NiU+ z#V6tIyaF-{*A~MBpmKCZz}|zf7mHiUVq|LS?e~S*LYINIHV^!*Q_p2vA2Yx5aQ* z+L$(GO9VdM!(p&AbQxlG@Y%7Sf;>kUHf;T6sp8lqy&o|z0zpwr^L!h>t7>zOnKxMz zQBOn*EkZTn&;9~RY8XP@q-{O$3EI9dAfZrC=no;Yl$>jB98B+grK3BPJz3zU-SMtT z?_!4A`vbmjdec~a@|p(i4W~7$Ybjx6+XW7`?xS~&P2SJ85LvHJU<&(jd@SPph-`CC zVv>QKC7CLQcIv41u|)cfpFhvo-dA5LNBR}sx*OyTc<@n4H3VgM?P@{r?fOP08pfj6 zj9OwGHP4=X0TM1V+IS7I?!Ggm%k3&hU zi4hswJUupc+F9V^FlRkmpcV?@?D0ETs|=(BUcY2s)@X zXC*os8mu$=S{nSXC?g{yHI?6Yc*zP40K{BKrihJ=y@C~N7`LrzkJ#5+J+hEIk=OYT z!+|E8b(-rxZ{jKQo7CaRIWiy6b#+P$AMBXEKB8)cpjs}bo=ibsR$}`S860a|e}HEt zRa7hhi+nCE`Mjq%NiDJ|#eG}t^~D%@iN<@1^DAq(%9JHO3FbDG{dYh#W`gQzvp>MX z0WJll1RgLT(*zuZlqF0!194c!C;ai@ipkB)w8M-JG04rEH*M=K`5w9ZyT(keP{HUD z+hPPmGI2N>={Db05@gLJwqo2ty9oB~3P4u1h31L9k6wzo{$8$RbCm3wzMU8m_)6Hb zde8Xo+ovNf^@^5&FD(-d`Iv^aC=h6cs_s2ea1Kbl3hPAV9DkZ~eWBA(_Mz8*Zntjr*6c% z5#-L;J*PV{IGB+7XK0!Ixg!(D7IpQ3I4t0P>dATUsIiUB767XIG-{a`?|n^Jhs{S- zwe5u6WWZ6O&)<^H|4OkkHU`d&W3lG^g$v%l&R!0_R>H+7MQvmpa-Gq-*+({_;S>9B z2j*8$9f0PTLHmd&8Dc=_PQFi#sSGmF?dYZH6fc1&W?c0v_@;VpzefLT% zZ*m9@VAdYVp1-VTyfe^$HcCVA$17G%3_UZ?GU6`oe%9v2w)s|;O|@5uV=v@HPoC|p zn|@RQC=a4NaY zJ%p}u4}JlF%8j2lgTdhrR?xdemeUnZOXweL^3GSRx2mfuqwV9EFfhKvp!2jrbS0cT zzcYR1b8mn9IydbT<<;?9hE6|t3!5BzfjBeC)^;TFHvbNBi@-DpUh4ekvQhhKigN>=kMp~9(X$+d-tFE0SsKQghBR337Mqx{mj6WOgy10 zDExS%Xv?H4U6_cX;sw-qAe3@GoKptPj?BesiWhtCC~NcCF5E z-BZfoGA8nabz_ntaNDmvd-VCZ-M26K#JAfWimrHCvD8lb`t>Zf6nKBpv!?&3h;oeR zT4;#bS$E$d%e{l%l_JAO0IO$Q8~dI&j&aRy%-!xPt!EVqOjjY;?>!OeO81BAFX^xr zgMz@*|I-2xz7n16c4!?*S~O8hoBQ7)ugat104IAv%cfqOsOU&|AVu4xpTB2wMO7z9 zr&Bqz)Fo5fgKeAxYYcbTmX9C$tP>C$dG|??P5ednMBn&Um5{V^`S3^LXRKf$v)UQP zV97GhdHO~YT|Ob5%E>qL*19TLP*@-tS!$O?RJ9mt>6z&Wa$4eEY@ZpK>8?Ionol8* ziVw#TU(i1i{BBAe#1K!luC+;yCxFiD{9+j(D`e6jg_fJO-yY}*$VKTHt!-L&V-#M= z1?`7MbscOvj3N~-7E9i=Lo{>$b#&5y0CbINE&RoBt- z5AH(>g9WA2i*`Rn>f=O3;!Z7Ace-@qd+O0o>0W!u^p8U{iD!sh`9wk5b;dQC0751C z*oZ&*#kb9@gc7RQ?1KA*qM|+B#8T=6vY!@n7u5xRm8y$|u?H7$TE4%hJgu2QT#}TL z!8Z3G$VL&YSsWYtnK<|0o!eR*H$VU7zkfXV5B?_X95E&kn7XKwFagQu=GD=^k^=>4 zaP(*`cw^koFuhx&6Gl2;%w{ugeM=-FZJ^K8afEZRyB@ybK-3 zx%f|7Uv3cV1E%x-vRW!|WypG1S3jbC&9`+{`{&hb1Eb1RAr5!mZYAe=~RmL2Plw>;U7oYnOg$kN?z5t-L)9+lZ2+7V=qZdfjJX2*8Ku z60o?VLN8j%LpON5kM}0_rB*-Y=uYbEPtcU%>ZB8W%T0J}AnemHeY4&+&f2ls3jJV0 z#m}h7(KECLwHu1-9VJHuxS8F;vp90;jT5gwJJlFGkbdH~)X;YMNj4t!-DLw(@|A(= zbn0zJmWjuXALnL_07^YKb0IY(BZQxvM>-$XevJnHHC;vBCnT(JCJkhgrL#xij zFB0K8S-tKccCqOO@C&I$e}a?>n0|`kBy3r*$qoCFC6~f!S&1aP!yoiSvWxndc#vcJda!LB~aI zX>oZ>3m?AekjGnSQ+gb+cNp*ck_C5BkR8d)?u3cAA*Dou5H(SNnS&rq7$C}O5p$@$ z$#1HZi;G=0<9;+AGap#Lb)EIh>Mh=)d_Yf-Zs0;rNV_F2bsB>4~N&jEnf! zFMV`Yf;y@7?Jt@k7w_iXTB34X0bALqtVu+zgEVTr8f(`Y(DjJP| zKr?Cs;i;k6lQ&m|2#th1QVoGsj`}-^CNqMLn3tD+39CiFwH_&#dXDE0Z30&7O@xGg z&e@c;`@sfHcHbxOC)Xo>(9F{i@J-w}xcz4H!tdXY%CbY3yUBE9`edp-#HS(q$f6{J z`9BgUr^sQ2(31I;2EYf(_s8ES{LD`(_QQ?#6Y^)+MAe6Wx@~03ZSt1*lN=1v1w{HK zXxKbbGGEEPLo)={8B(swrf%;z>UN@uF!!<`!He2rI7IFUiIL2(mB>iuPNu14S!0=} ze@Lv?;>@JGs3qXVKToAWB=nG$NasRcXi1mxdlA#iRql9=u#8+8IbZZzs{Nw0TT!7e&MtkJ>r2>I*(GMz6TiG8>e|4(>4j9hD2dWowIIm*!KjJUbkO_N9c zE-J5pcZ6xP-$Ha9_XFw$5_sIK9*6g>KRRJ+yMe{NJH*6p@To(NEKVZMHcpQHjLW+bDG5#sUGd zv68Vds`<#^d)?-3d)TRy*+9rNy89j!+4RCLkL*b z{Z0(`Y`z zdY0ONOgqsz#rJ0R)Wr&V2cB<`tKePML41LA9Uxi%qW@Z~lhH6(W0*{v5!F>rZ9}01 z6u#tmUwS438JC!?O%CM5QC4#RWrx&OJa{8fa_z3*EBGp_suG*WpvahBjF6stE^wHN z3%w?BUW9GaBTtFxej8CO+FHUIdoq18>FCI5JGuEyWZ%eb)bFVdg>1{LZYfV9-6Tb8 zX=>5W&|MGd7LahcPydKIh~xrm^l4_LBFdq6o=C+#j%%t`%K^gJ;ht}IfT5Bb`rt5xw94o z%JKaxXORyC>C$6gshm{g*FoS2v=oZaikh6JE6v0)LdkC)YG;xeS?E!lkuHH+m}-@9 zhCmn#p&H2`$7nGV$ov6ZM*BMY_=vSEzul_Ovd}k#*ne`$w}LQ~V9`JSvVdlYMwG8X zm;kC1;0aW}@kqMh;i2q30Z8QQ|D0689V!?W^-or~A#BOnx>*aI0XOdy20@Uu^P?W8 zjVb#!5EJN8aM)43ndGL$>qQ6{{#37YytF5Hp-mN|6YR8Q_zbYDE`$GsJQF=?WKG|f z7spz^xQ4jf85Grx&Kfgy5z>!I+OS-GlWs#Ye|3hdn)x^Jk)XC11v z4b=fFJRx&FEnv}nl-h~VKND#G6Sq0W4EKTR@-uFAZ1k_bFCfBQ?*0;bgN zRN-VNa_O1UQu;qsDH_r3CvxeNTno8hZ1GcM7*Cgxt#LS5@Y00j=8D?Dxv-7BUew;wg?f$_`G@qt`bH`y z_3e!QBg&b40epKl(^OUkiAog@&MCY2lUc2XalIVlF%bJ+oEB`pQ z6I;-=Z}p=7Mx`(!Jwi8s8Od<``809VNg-+@CxjW3sSd+u-l@e^mObjuT=u5#a5%Yw zKzbTN)Z#Uw4(jhC(Dg(xC7tj6^%Kkx1mTsk9)}>7y$ALiTRq{IMxY|3IF)s|BsQIA z_oNlOKyYK&g}T0KS^`{Y#}{J(agMzwboEQY*_l~eTbr5D(o|KCag5ZPMHCAr?BTga zTfO0*7wP(tNY*AZ%oBHw(1ugB@@-~UnNiugXHhFJJfC`p@i^H)i$0mSf8=ALS}E|W z;hKdFlohBj-Dju!V8h!3AOTvLD?vfP*q5-i6@a$M^Iam1L!YH61r}!zD>F0DrQqkA z;}455znWOQ^jAjKmN|&Fi*S=@OJz@PFifL4c5Sh?t`1DHWJ0lHzKqt+^`w0>?svp3 zO9{?ZF2e;awSV6?oS*n|ev2S0RfrwNJOm6SBb?z?n{3zgB1kN-I8e6n;#tM&Rc@?U z6;3mzJSR@P;DiUDU_>ihZnw!MAJr`DCe`ztNAo4WwDNZS_12nZe_Xa5wk zhr{z&0R%0x$lAmNc;eyFa$h}{BT-vNNQa;FtXTsvdf_0;r^fAEMJqm$wbM+hJc^&%+JO-+Ng2e`~pZ!8or>_-pSjeM;`T;|;-M166 z-6$-v2TvFq+nZCmYp@poGisu>h7T!VJi#1l6n6n`k#LI^I$l@gk0E#gZHe0=FI=G+ z>%a3L=D>ZUdb04#PxALyEq{)%?V%H7jqhKwg5m>Vz1z2kwfC4r_St|A0ey|3=H&1h zf0>HjQy9#!<{l*6Z$}O#vaoIs}Y2g0id-! zc<5Rmqgw};4F<*__g8td;NO{w_Mj^Tb_^mpQ4>?l2}Gv(b;XWiEY-o^f*fmRgv|tD z$k;Sj41GJgPRNO0=!r&Orz#%SKg^FejTLDXDGH`;%m_0>{wDLQ&pD0zS|8&c#nL-6)9d;ct-3EnER|K{VZ$*x2(ad9Zg(1|@8 zlLbLvgKrKt1L(ogTgAOy-ty583Q-Ng(vp&opF)((Sl1Y&XwGWI6^FU#BgUi20Y!WE zTTgLG2{5Bm2$BRii0=(;;ZwlcAaRW@88A!+s+F@OXkTHEKW9|S%DL0tBt)J_(vI%m z&>4El7HFk$@Owt9&H5VOx$o}_0z}yuklMM|wJRTcv$_yQ)pVT`Olxk`+na_dD=YGKJqpV;%^dtU>K<}3?8c>v-A=Di)D_QHRACk*Yk-{oJ+iJ~Lrib%dab zw65FGNKbxDvf~j)RzG4A@W`V_3B(3DSm$IBT_=8@?IXWMYSukhbb}w8A?zCD6#W0&eiqDkMo}uLO5vpjcg1(<` zvPmRI)um_0&5$g{DSinESa<5x_J;ZGfM>j>U=pNq-+eGJ`1>fe=u z5+M_w66hFcPq_=2Ex_B=-(C6pH!31xakgJoOiYhr-gMyRR{wWVENACODpi8! z$Oef|n18;!pBXWM?=jb1rA z;fNNNNd2DLhWA8(QFiDmn&{=|S-qimJ9+g#` zA21~>OYpu-AfLFN#_P3ZEcnFe&X+rNyC;4&8P5k&BoxD+6uJ(cDs(l?4iGZ98rf{O ze9?#f(0|gC43Ky#p0LegSVz>6CQ1z|sxn_}ulqMHC00g8q^4m>3#7X2(R!zB3+fh= zIdq=AN6|%3^Eq+fG4W3LGEjhhL81a-ki{k`JdyGETZdckoz3@{YZ2Odz3oV9@Kohq z0{O8;1)+P<;^oG=z*(8)X?MK8%jI=heyXs#{FfT5TsV2~e@i;i2+Yj5d+v2lbfl#U zIVujyoAN?ULxdm$!~DWR_Wgugg3D6@+?xFNLTnavtws`fe()6hmoN@7 z1|~Wf9q`|w|6Vw!O!Y}@^nmSQ$i^7xwxVEVD1%&34R}P#D$6ikuPEut~<(W!SHdMiX1;7|N z97h4bK|L@^SK2RUsKelW>X?FQRLv`Yk`^r$(VT_!m$K1mvf|Xbs~k^tDIP(5@`Se- zR}p-9vIuC=;-$J?cdlqXM7804JCrB81tqkcMaQU+a#S+GXA;hm+!9@fG|dfOidv1K znO%T|fCm#wQTS0dn>YVPBn4cB(02g3fCTVnTwG%7_x?9O zo_}>0)dW<1G7;j3-+)ISO-H=g~%u~Ts|KS^^ty=J<0 zHS7ED+7~&FH0zS-2?<=9j>36VVXwUQ3KjW}w#ZNLGZ4g?;!ZWExCa=Fijl1~?SpLJ zZR_IIG+@O$L5{GVsEhA$nP7aZQ(Ue4VCa%eC`56^8_w(WJ`O201x}SBAR5@V4|$t- z?2n2g1OheyOlZBm2r2ir-HR)#V(LQMW7X=?70(Tel8U)YiKb-mb1*LOYC+ zZ_^g>wWZ(kLp#i)T82_G}5Y@>(459FEUm~+v1nvb;_o7-?w|`arYJ#6~P_EVHu|->>NaP z2|8MQET_Lrs(-n}bDQw{x>xvfI0MEe@a|su9>XHQxpa6Zcgx9PlTZ)r*7z+z8Q{ai z!Nb7H`gHLo>h3;X<>*CGst^)?UEdIOO}mdwwz3i=RReph>TF88UCkspRsWFqwcS)w zkBQ%Hau^k~mg0)Ezb9UB>Tzps%_-{Qm>8y>pw@jO_X28|EhM(WXNpPj`$7%R@cWqOrAg3gtFuT`b} zOS?a7lIx~1*}$QR6B^G8|8sU|-7BVBpv1-2<{&hG@#&O{>!x<%df$`73!tEkB%XN2 zHXoE~^_g_<+}6`U^WT+pQR4H2Ue)7hM2a}nc&(2I%p>iqOJip%V~eZcPj6`{@a_mL zBQ8Bc!jV72Qvk3&VM5i-vCTd$7tds$AM4?I;qh$zMJ((7m~WphIs3(Q7r$rje7EW~ zLw$r-)zjXxYH}=UU;lDtue7ss%~#L!eEhQfsd8;j7tUBe{NVi6)BU2_=`&;dme3Z< z^DyI}JgYz)@jSx!(uWoE8>pA+H4}JNn!dnvT;gIYdfUquB?T`E(fU__N-ni+W9_>p z!c3fiTP*4`h=f16y}c^SM11yEfQF!|N@mRac1Mk47cyTr=1-2jetlYIX=LQ<2LHktY+SNai4^bUe|o%vwVFCLJ>+ki*Q8IUP(EOFRW~;5$d_vmpJM8C(O;Uwlub)ysm80 z^O*MGCSd}BHb`Gj+qARUZ}evXETHuRac(@GflMwG2^c_$VvBN7DXDj#%Gq=dmyTTX z$PfR`c52mmTH^3-S2wr+znt0^;TKA;ZUVVD)S1XhU-RqZP8yM%=ZHi2H_95Ei~tbi znjMY^M|J5}a?xG9(LCZ?6_e8zpm7-V3I1wDN|({;unrc_@)7^;fbps`mMZAa!&vw8 zVEVt%zVA>I3IA68=V$tdzj5>V+h@r}{gQgSS=XEI8OQtquUM@SspVsl8kElM3hbiNVi0L$jL*WUEZ`PeMFVx}C5E>P`OjHiGY|&Gukp8RzZm8w zv>bP6ev4O3L`-{K_MK;pujC*vfT|7}Et?u2M@pmd3D7lL!V+b*H3Vs7ykbL}?PxTK?e=W+q+v7ZdvG5iXdUD$=G)USF+(=OUB@O8ek;*9 z60?}Yw@Y2)SzmbG-ppDR{mn_R(myKHI5sR0Hn*3Vc(Wl`;rR4alcuuy9P zxEeg5r?G<^R+7B?DQr5|d?j>ugkPkkJILvJ9*T|YiurFz2k4(@%3onqr6V_Sr@tCe z<j>zS(<)G3;p8}N#~0Oo)x;ahu#5EjdQVAzCdjK?uQ{FY%OIY)cZF+MkQ zjls2~a_HtTyT*PRnRx@!54~^=;?ox+F@1Lmeca}4;2}l6Fg!_E4w<4Ee3iauaYs1Y z$LRmw5nTn{^}7=4p zGPRYsue0gQu;6X56_s~zJy@eLV9k`G{dOr+arLKqC_lCE=7SyX%lkq}ylii4&cRBG zj%sPPzxnYDkQ9VMB68US-%$9isBC5szMM_^0~Rq;F>*a&%G4fjk1cGqC})vh_wv=w zrQ4~%&V8fWj!=E)ChewVWt!ppdY-gvgU08yin-b~LgnRWZ^X8qSP|WGxp1GLX7M)f zuU(~3B4O|Z>tquUut!?u2vEkjllp)~a(^*z-C3X9=Xk$RD0j;Kt3Fa09cw2lBFXPE4XAhSe{0IH6k-+Qqufv{l4P-Q{kC?= z?d?Jl=W7@9gz+8BQoaL=TqeHlY0Jq9gg{1j!=|AaBeyJNyY6iPAH*)}FiblB_jmFZ z6iq8P^Rs^Gp$hsfwo3b8h$QV2FsUB2YRe3 z3OCT}5C?W7cW^&#_0G+t-kCcS&!)4Djq=U$ckmf!MYi0ycS*wahv)Ca(T&*G2|+V8 zBx}dRFA;7bFHYA<=l3;N;sEZJX5G5AaJK1-5(~Qv4tjH*d{0HXvF%+neFl9wgREim zj7as#@ZatXY4gqcJX=`UPv_&UBxNyaiZn_JxZS()=g^a2#r_oyy%mwSrMf$V3Ch_V zI@iLo{@>#2fH@&!f}*k=~d$$TIu1E=hc z>;nb##%al0e68H30EK2P+6i>o>JP0Cx@8pp3v)0wu5AVdt)0!Z(w>DWEdsw6={7wx zdsDBo%7Lk}p5y7ZzGh%SX$>+)5vczScP}swKt_LSH3|VzEdojLpdbeeJ^jyYaP&aa T`NLQLG5~?6tDnm{r-UW|NmVo* literal 103874 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

G>~aao;(>v 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

&;{z8Vdxv1{?s|>rf*TzTCT{P6@$m{g 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 { + '"mesh4x4"' => { 'ROUTER_Ps' => { - '5' => 4, - '4' => 8, - '3' => 4 + '5' => 16 }, - 'ROUTE_NAME' => '"custom"', + 'T1' => 16, + 'T3' => 5, + 'ROUTE_NAME' => '"custom","m4"', 'er_addr' => [ - 0, - 1, - 2, - 3, 4, 5, 6, @@ -29,17 +25,31 @@ $Topology = { 9, 10, 11, + 0, + 1, + 2, + 3, 12, 13, 14, 15 ], - 'T2' => 16, - 'T3' => 5, - 'T1' => 16 + 'T2' => 16 }, - '"mesh4x4"' => { + '"custom1"' => { + 'T3' => 5, + 'T1' => 16, + 'ROUTER_Ps' => { + '4' => 8, + '5' => 4, + '3' => 4 + }, + 'T2' => 16, 'er_addr' => [ + 0, + 1, + 2, + 3, 4, 5, 6, @@ -48,21 +58,11 @@ $Topology = { 9, 10, 11, - 0, - 1, - 2, - 3, 12, 13, 14, 15 ], - 'T3' => 5, - 'T2' => 16, - 'ROUTE_NAME' => '"custom","m4"', - 'T1' => 16, - 'ROUTER_Ps' => { - '5' => 16 - } + 'ROUTE_NAME' => '"custom"' } }; diff --git a/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v b/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v index 5c5af0b..0cdb1aa 100644 --- a/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v +++ b/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v @@ -356,7 +356,7 @@ module thermo_arbiter #( reg [ARBITER_WIDTH-1 : 0] termo1,termo2; integer i; always @(*) begin - for(int i=0;i Date: Fri, 23 May 2025 12:31:19 +0200 Subject: [PATCH 019/107] fix bug in ni --- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mpsoc/rtl/src_peripheral/ni/ni_master.sv b/mpsoc/rtl/src_peripheral/ni/ni_master.sv index 3579309..dee4672 100644 --- a/mpsoc/rtl/src_peripheral/ni/ni_master.sv +++ b/mpsoc/rtl/src_peripheral/ni/ni_master.sv @@ -800,12 +800,7 @@ Shared registers for all VCs localparam LBw = log2(LB); flit_buffer #( .V(V), - .B(LB), - .SSA_EN("NO"), - .Fw(Fw), - .PCK_TYPE(PCK_TYPE), - .CAST_TYPE(CAST_TYPE), - .DEBUG_EN(DEBUG_EN) + .B(LB) ) the_ififo ( .din(flit_in), // Data in .vc_num_wr(flit_in_vc_num),//write virtual chanel @@ -818,7 +813,7 @@ Shared registers for all VCs .clk(clk), .ssa_rd({V{1'b0}}), .multiple_dest(), - .sub_rd_ptr_ld() + .sub_rd_ptr_ld() ); extract_header_flit_info #( From 181f5d4625faf9a558c7414222ec48b94bbd6cc9 Mon Sep 17 00:00:00 2001 From: amonemi Date: Sun, 25 May 2025 15:55:38 +0200 Subject: [PATCH 020/107] merg ft/ci to hetrovc --- .github/workflows/main.yml | 48 +++++++ .gitignore | 1 + .../{default => general}/Fattree_k3_L3_st | 0 .../{default => general}/bintree_k3_L3_st | 0 .../{default => general}/custom1_topology | 0 .../{default => general}/fmesh_1x1_openpiton | 0 .../{default => general}/fmesh_2x2_openpiton | 0 .../{default => general}/fmesh_8x8_2cycle_xy | 0 .../{default => general}/fmesh_8x8_openpiton | 0 .../{default => general}/mesh_2x2_openpiton | 0 .../mesh_4x4_2cycle_mcast_f | 0 .../{default => general}/mesh_4x4_smart3 | 0 .../{default => general}/mesh_4x4_v1_B15 | 0 .../{default => general}/mesh_4x4x3_2cycle_xy | 0 .../mesh_8x8_2cycle_adaptive | 0 .../mesh_8x8_2cycle_west_first | 0 .../{default => general}/mesh_8x8_2cycle_xy | 0 .../{default => general}/mesh_8x8_4vc_4c | 0 .../{default => general}/mesh_8x8_b2 | 0 .../{default => general}/mesh_8x8_sbp6_xy | 0 .../{default => general}/mesh_8x8_single_flit | 0 .../{default => general}/mesh_8x8_ssa_xy | 0 .../{default => general}/star_6 | 0 .../{default => general}/torus_8x8_2cycle_xy | 0 .../failed-model} | 0 .../default_report => golden_ref/general} | 0 .../line-ring_report => golden_ref/line-ring} | 2 +- .../multicast_report => golden_ref/multicast} | 0 .../vc_alloc} | 0 .../synthetic_sim/reports/default_report_old | 133 ------------------ .../synthetic_sim/reports/failed-model_report | 39 ----- .../reports/line-ring_report_old | 71 ---------- .../reports/multicast_report_old | 43 ------ .../synthetic_sim/reports/vc_alloc_report | 37 ----- mpsoc/Integration_test/synthetic_sim/run.sh | 17 ++- .../synthetic_sim/src/check.pl | 131 +++++++++++++++++ .../Integration_test/synthetic_sim/src/src.pl | 38 ++--- .../synthetic_sim/src/verify.perl | 24 +++- mpsoc/rtl/src_noc/mesh_torus.sv | 9 +- 39 files changed, 233 insertions(+), 360 deletions(-) create mode 100644 .github/workflows/main.yml rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/Fattree_k3_L3_st (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/bintree_k3_L3_st (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/custom1_topology (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/fmesh_1x1_openpiton (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/fmesh_2x2_openpiton (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/fmesh_8x8_2cycle_xy (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/fmesh_8x8_openpiton (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_2x2_openpiton (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_4x4_2cycle_mcast_f (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_4x4_smart3 (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_4x4_v1_B15 (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_4x4x3_2cycle_xy (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_2cycle_adaptive (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_2cycle_west_first (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_2cycle_xy (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_4vc_4c (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_b2 (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_sbp6_xy (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_single_flit (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/mesh_8x8_ssa_xy (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/star_6 (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/{default => general}/torus_8x8_2cycle_xy (100%) rename mpsoc/Integration_test/synthetic_sim/{reports/failed-model_report_old => golden_ref/failed-model} (100%) rename mpsoc/Integration_test/synthetic_sim/{reports/default_report => golden_ref/general} (100%) rename mpsoc/Integration_test/synthetic_sim/{reports/line-ring_report => golden_ref/line-ring} (98%) rename mpsoc/Integration_test/synthetic_sim/{reports/multicast_report => golden_ref/multicast} (100%) rename mpsoc/Integration_test/synthetic_sim/{reports/vc_alloc_report_old => golden_ref/vc_alloc} (100%) delete mode 100644 mpsoc/Integration_test/synthetic_sim/reports/default_report_old delete mode 100644 mpsoc/Integration_test/synthetic_sim/reports/failed-model_report delete mode 100644 mpsoc/Integration_test/synthetic_sim/reports/line-ring_report_old delete mode 100644 mpsoc/Integration_test/synthetic_sim/reports/multicast_report_old delete mode 100644 mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report create mode 100644 mpsoc/Integration_test/synthetic_sim/src/check.pl diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..027a0d3 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,48 @@ +name: Verilator Test Suite + +on: + push: + branches: [ "**" ] + +jobs: + synthetic-sim: + runs-on: ubuntu-latest + container: + image: verilator/verilator:4.104 + #options: --volume ${{ github.workspace }}/mpsoc_work:/mpsoc_work --volume ${{ github.workspace }}/mpsoc:/mpsoc + strategy: + matrix: + conf_name: [general, line-ring, multicast, vc_alloc] + env: + ROOT: ${{ github.workspace }}/mpsoc + PRONOC_WORK: ${{ github.workspace }}/mpsoc_work + GOLDEN_REF: ${{ github.workspace }}/mpsoc/Integration_test/synthetic_sim/golden_ref + LOG_DIR: ${{ github.workspace }}/mpsoc/Integration_test/synthetic_sim/result_logs + steps: + - uses: actions/checkout@v4 + - name: Run NoC simulation - ${{ matrix.conf_name }} + run: | + set -ex # Enable exit on error and command tracing + verilator --version + echo "Running simulation for config: ${{ matrix.conf_name }}" + echo "Workspace structure:" + ls -lR $ROOT/Integration_test/synthetic_sim/src + cd $ROOT/Integration_test/synthetic_sim/src + perl ./verify.perl -p 15 -u 80 -l 2 -s 4 -d ${{ matrix.conf_name }} + perl ./check.pl -o $GOLDEN_REF/${{ matrix.conf_name }} -n $LOG_DIR/${{ matrix.conf_name }} || { + echo "❌ Verification check failed. Please inspect the simulation logs." + exit 1 + } + - name: Upload failures artifact - ${{ matrix.conf_name }} + if: failure() # Only upload if previous step failed + uses: actions/upload-artifact@v4 + with: + name: simulation-failures-${{ matrix.conf_name }} + path: | + ${{ env.PRONOC_WORK }}/failures.txt + - name: Upload simulation reports - ${{ matrix.conf_name }} + uses: actions/upload-artifact@v4 + with: + name: simulation-reports-${{ matrix.conf_name }}-${{ github.run_id }} + path: ${{ env.LOG_DIR }} + retention-days: 7 diff --git a/.gitignore b/.gitignore index c77757b..dd70c5f 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ mpsoc/remove_cycle/__pycache__ mpsoc_work/ mpsoc/rtl/src_openpiton/nocs +mpsoc/Integration_test/synthetic_sim/result_logs/* diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/Fattree_k3_L3_st b/mpsoc/Integration_test/synthetic_sim/configurations/general/Fattree_k3_L3_st similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/Fattree_k3_L3_st rename to mpsoc/Integration_test/synthetic_sim/configurations/general/Fattree_k3_L3_st diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/bintree_k3_L3_st b/mpsoc/Integration_test/synthetic_sim/configurations/general/bintree_k3_L3_st similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/bintree_k3_L3_st rename to mpsoc/Integration_test/synthetic_sim/configurations/general/bintree_k3_L3_st diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/custom1_topology b/mpsoc/Integration_test/synthetic_sim/configurations/general/custom1_topology similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/custom1_topology rename to mpsoc/Integration_test/synthetic_sim/configurations/general/custom1_topology diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_1x1_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_1x1_openpiton rename to mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_2x2_openpiton rename to mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_2cycle_xy similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_8x8_2cycle_xy rename to mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_2cycle_xy diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_8x8_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/fmesh_8x8_openpiton rename to mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_2x2_openpiton rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_2cycle_mcast_f similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4_2cycle_mcast_f rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_2cycle_mcast_f diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4_smart3 rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4_v1_B15 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4_v1_B15 rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4x3_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4x3_2cycle_xy similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_4x4x3_2cycle_xy rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4x3_2cycle_xy diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_2cycle_adaptive b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_adaptive similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_2cycle_adaptive rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_adaptive diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_2cycle_west_first b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_west_first similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_2cycle_west_first rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_west_first diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_xy similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_2cycle_xy rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_xy diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_4vc_4c b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_4vc_4c similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_4vc_4c rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_4vc_4c diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_b2 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_b2 similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_b2 rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_b2 diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_sbp6_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_sbp6_xy similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_sbp6_xy rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_sbp6_xy diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_single_flit b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_single_flit similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_single_flit rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_single_flit diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_ssa_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_ssa_xy similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/mesh_8x8_ssa_xy rename to mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_ssa_xy diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/star_6 b/mpsoc/Integration_test/synthetic_sim/configurations/general/star_6 similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/star_6 rename to mpsoc/Integration_test/synthetic_sim/configurations/general/star_6 diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/default/torus_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/torus_8x8_2cycle_xy similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/default/torus_8x8_2cycle_xy rename to mpsoc/Integration_test/synthetic_sim/configurations/general/torus_8x8_2cycle_xy diff --git a/mpsoc/Integration_test/synthetic_sim/reports/failed-model_report_old b/mpsoc/Integration_test/synthetic_sim/golden_ref/failed-model similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/reports/failed-model_report_old rename to mpsoc/Integration_test/synthetic_sim/golden_ref/failed-model diff --git a/mpsoc/Integration_test/synthetic_sim/reports/default_report b/mpsoc/Integration_test/synthetic_sim/golden_ref/general similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/reports/default_report rename to mpsoc/Integration_test/synthetic_sim/golden_ref/general diff --git a/mpsoc/Integration_test/synthetic_sim/reports/line-ring_report b/mpsoc/Integration_test/synthetic_sim/golden_ref/line-ring similarity index 98% rename from mpsoc/Integration_test/synthetic_sim/reports/line-ring_report rename to mpsoc/Integration_test/synthetic_sim/golden_ref/line-ring index ff14dcb..63eced9 100644 --- a/mpsoc/Integration_test/synthetic_sim/reports/line-ring_report +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/line-ring @@ -24,7 +24,7 @@ Verification Results: ****************************line2_openpiton : random traffic *******************************: Passed: zero load (2,8.28125) saturation (74,89.3628) ****************************line4_smart3 : random traffic *******************************: - Passed: zero load (2,8.66406) saturation (62,115.304) + Passed: zero load (2,8.66406) saturation (58,53.1986) ****************************Line_3x2_v2 : random traffic *******************************: Passed: zero load (2,9.40682) saturation (30,138.275) ****************************line_4_v1_B15 : random traffic *******************************: diff --git a/mpsoc/Integration_test/synthetic_sim/reports/multicast_report b/mpsoc/Integration_test/synthetic_sim/golden_ref/multicast similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/reports/multicast_report rename to mpsoc/Integration_test/synthetic_sim/golden_ref/multicast diff --git a/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report_old b/mpsoc/Integration_test/synthetic_sim/golden_ref/vc_alloc similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report_old rename to mpsoc/Integration_test/synthetic_sim/golden_ref/vc_alloc diff --git a/mpsoc/Integration_test/synthetic_sim/reports/default_report_old b/mpsoc/Integration_test/synthetic_sim/reports/default_report_old deleted file mode 100644 index 606a952..0000000 --- a/mpsoc/Integration_test/synthetic_sim/reports/default_report_old +++ /dev/null @@ -1,133 +0,0 @@ -Verification Results: -****************************bintree_k3_L3_st : Compile *******************************: - model is generated successfully. -****************************custom1_topology : Compile *******************************: - model is generated successfully. -****************************Fattree_k3_L3_st : Compile *******************************: - model is generated successfully. -****************************fmesh_1x1_openpiton : Compile *******************************: - model is generated successfully. -****************************fmesh_2x2_openpiton : Compile *******************************: - model is generated successfully. -****************************fmesh_8x8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************fmesh_8x8_openpiton : Compile *******************************: - model is generated successfully. -****************************mesh_2x2_openpiton : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_smart3 : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_v1_B15 : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x3_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_2cycle_adaptive : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_2cycle_west_first : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_4vc_4c : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_b2 : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_sbp6_xy : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_single_flit : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_ssa_xy : Compile *******************************: - model is generated successfully. -****************************star_6 : Compile *******************************: - model is generated successfully. -****************************torus_8x8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************bintree_k3_L3_st : random traffic *******************************: - Passed: zero load (2,14.5705) saturation (14,400.884) -****************************custom1_topology : random traffic *******************************: - Passed: zero load (2,13.0626) saturation (42,65.4283) -****************************Fattree_k3_L3_st : random traffic *******************************: - Passed: zero load (2,13.5991) saturation (62,98.8008) -****************************fmesh_1x1_openpiton : random traffic *******************************: - Passed: zero load (2,7.06202) saturation (66,51.0968) -****************************fmesh_2x2_openpiton : random traffic *******************************: - Passed: zero load (2,8.27536) saturation (54,67.4686) -****************************fmesh_8x8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,19.5638) saturation (18,137.798) -****************************fmesh_8x8_openpiton : random traffic *******************************: - Passed: zero load (2,14.4245) saturation (30,98.3569) -****************************mesh_2x2_openpiton : random traffic *******************************: - Passed: zero load (2,9.10156) saturation (66,72.3384) -****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: - Passed: zero load (2,14.4623) saturation (22,261.684) -****************************mesh_4x4_smart3 : random traffic *******************************: - Passed: zero load (2,10.1271) saturation (42,72.4117) -****************************mesh_4x4_v1_B15 : random traffic *******************************: - Passed: zero load (6,12.719) saturation (58,93.2747) -****************************mesh_4x4x3_2cycle_xy : random traffic *******************************: - Passed: zero load (2,12.7475) saturation (26,188.161) -****************************mesh_8x8_2cycle_adaptive : random traffic *******************************: - Passed: zero load (2,18.2154) saturation (34,186.128) -****************************mesh_8x8_2cycle_west_first : random traffic *******************************: - Passed: zero load (2,18.2239) saturation (34,154.392) -****************************mesh_8x8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,18.2211) saturation (34,132.962) -****************************mesh_8x8_4vc_4c : random traffic *******************************: - Passed: zero load (2,18.0557) saturation (26,162.893) -****************************mesh_8x8_b2 : random traffic *******************************: - Passed: zero load (2,22.1073) saturation (30,198.439) -****************************mesh_8x8_sbp6_xy : random traffic *******************************: - Passed: zero load (2,11.1597) saturation (34,119.674) -****************************mesh_8x8_single_flit : random traffic *******************************: - Passed: zero load (2,12.7369) saturation (58,65.8427) -****************************mesh_8x8_ssa_xy : random traffic *******************************: - Passed: zero load (2,14.769) saturation (34,111.6) -****************************star_6 : random traffic *******************************: - Passed: zero load (2,7.27692) saturation (62,57.3078) -****************************torus_8x8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,16.8517) saturation (38,120.208) -****************************bintree_k3_L3_st : transposed 1 traffic *******************************: - Passed: zero load (2,14.5436) saturation (14,430.149) -****************************custom1_topology : transposed 1 traffic *******************************: - Passed: zero load (2,12.6827) saturation (34,68.3986) -****************************Fattree_k3_L3_st : transposed 1 traffic *******************************: - Passed: zero load (26,13.4638) saturation (100,-) -****************************fmesh_1x1_openpiton : transposed 1 traffic *******************************: - Passed: zero load (46,6.99433) saturation (100,-) -****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,8.99642) saturation (54,71.4902) -****************************fmesh_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,21.6193) saturation (14,142.818) -****************************fmesh_8x8_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,15.916) saturation (26,118.048) -****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,8.7482) saturation (100,-) -****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: - Passed: zero load (2,14.8953) saturation (26,146.747) -****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: - Passed: zero load (2,10.5055) saturation (34,60.2796) -****************************mesh_4x4_v1_B15 : transposed 1 traffic *******************************: - Passed: zero load (2,13.6902) saturation (38,106.686) -****************************mesh_4x4x3_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,13.0755) saturation (14,126.234) -****************************mesh_8x8_2cycle_adaptive : transposed 1 traffic *******************************: - Passed: zero load (2,19.3604) saturation (26,108.443) -****************************mesh_8x8_2cycle_west_first : transposed 1 traffic *******************************: - Passed: zero load (2,19.3588) saturation (22,102.056) -****************************mesh_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,19.3582) saturation (18,124.569) -****************************mesh_8x8_4vc_4c : transposed 1 traffic *******************************: - Passed: zero load (2,19.2371) saturation (18,114.964) -****************************mesh_8x8_b2 : transposed 1 traffic *******************************: - Passed: zero load (2,23.5649) saturation (18,118.423) -****************************mesh_8x8_sbp6_xy : transposed 1 traffic *******************************: - Passed: zero load (2,11.3748) saturation (18,119.786) -****************************mesh_8x8_single_flit : transposed 1 traffic *******************************: - Passed: zero load (2,14.0386) saturation (26,70.9042) -****************************mesh_8x8_ssa_xy : transposed 1 traffic *******************************: - Passed: zero load (2,15.3919) saturation (18,123.223) -****************************star_6 : transposed 1 traffic *******************************: - Passed: zero load (2,6.83981) saturation (100,-) -****************************torus_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,18.0133) saturation (18,134.597) diff --git a/mpsoc/Integration_test/synthetic_sim/reports/failed-model_report b/mpsoc/Integration_test/synthetic_sim/reports/failed-model_report deleted file mode 100644 index 774f7dd..0000000 --- a/mpsoc/Integration_test/synthetic_sim/reports/failed-model_report +++ /dev/null @@ -1,39 +0,0 @@ -Verification Results: -****************************line2_2cycle_mcast_f : Compile *******************************: - model is generated successfully. - %Error: Exiting due to 1 warning(s) - - %Error: Exiting due to 1 warning(s) - - %Error: Exiting due to 1 warning(s) - - %Warning-WIDTH: /gpfs/home//pronoc_verify/mpsoc_work/verify/rtl/src_noc/multicast.sv:447:48: Operator ASSIGNW expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'dest_e_addr' generates 4 bits. - - %Warning-WIDTH: /gpfs/home//pronoc_verify/mpsoc_work/verify/rtl/src_noc/multicast.sv:447:48: Operator ASSIGNW expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'dest_e_addr' generates 4 bits. - - %Warning-WIDTH: /gpfs/home//pronoc_verify/mpsoc_work/verify/rtl/src_noc/multicast.sv:447:48: Operator ASSIGNW expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'dest_e_addr' generates 4 bits. - -****************************line_8_sbp6_xy : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_openpiton_mcast_f : Compile *******************************: - model is generated successfully. -****************************line2_2cycle_mcast_f : random traffic *******************************: - Error in running simulation: ERROR: Multicast/Broadcast is not yet supported for LINE Topology - ERROR: Multicast/Broadcast is not yet supported for LINE Topology - -****************************line_8_sbp6_xy : random traffic *******************************: - Error in running simulation: 8000: ERROR: The destination port is not set for an active IVC request: d[R - -****************************mesh_4x4_openpiton_mcast_f : random traffic *******************************: - Error in running simulation: ERROR: SMART or SAA do not support muticast/braodcast packets - ERROR: SMART or SAA do not support muticast/braodcast packets - -****************************line2_2cycle_mcast_f : transposed 1 traffic *******************************: - Error in running simulation: ERROR: Multicast/Broadcast is not yet supported for LINE Topology - ERROR: Multicast/Broadcast is not yet supported for LINE Topology - -****************************line_8_sbp6_xy : transposed 1 traffic *******************************: -****************************mesh_4x4_openpiton_mcast_f : transposed 1 traffic *******************************: - Error in running simulation: ERROR: SMART or SAA do not support muticast/braodcast packets - ERROR: SMART or SAA do not support muticast/braodcast packets - diff --git a/mpsoc/Integration_test/synthetic_sim/reports/line-ring_report_old b/mpsoc/Integration_test/synthetic_sim/reports/line-ring_report_old deleted file mode 100644 index 2196a90..0000000 --- a/mpsoc/Integration_test/synthetic_sim/reports/line-ring_report_old +++ /dev/null @@ -1,71 +0,0 @@ -Verification Results: -****************************line2_openpiton : Compile *******************************: - model is generated successfully. -****************************line4_smart3 : Compile *******************************: - model is generated successfully. -****************************Line_3x2_v2 : Compile *******************************: - model is generated successfully. -****************************line_4_v1_B15 : Compile *******************************: - model is generated successfully. -****************************line_4x3_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************line_8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************line_8_b2 : Compile *******************************: - model is generated successfully. -****************************line_8_sbp6_xy : Compile *******************************: - model is generated successfully. -****************************line_8_single_flit : Compile *******************************: - model is generated successfully. -****************************line_8x8_ssa_xy : Compile *******************************: - model is generated successfully. -****************************linex8_4vc_4c : Compile *******************************: - model is generated successfully. -****************************ring_8x8_2cycle_xy : Compile *******************************: - model is generated successfully. -****************************line2_openpiton : random traffic *******************************: - Passed: zero load (2,8.28125) saturation (74,89.3628) -****************************line4_smart3 : random traffic *******************************: - Passed: zero load (2,8.66406) saturation (62,115.304) -****************************Line_3x2_v2 : random traffic *******************************: - Passed: zero load (2,9.40682) saturation (30,138.275) -****************************line_4_v1_B15 : random traffic *******************************: - Passed: zero load (2,10.5781) saturation (62,84.8723) -****************************line_4x3_2cycle_xy : random traffic *******************************: - Passed: zero load (2,10.3202) saturation (26,59.0116) -****************************line_8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,13.2248) saturation (38,122.456) -****************************line_8_b2 : random traffic *******************************: - Passed: zero load (6,17.8996) saturation (34,105.723) -****************************line_8_sbp6_xy : random traffic *******************************: -****************************line_8_single_flit : random traffic *******************************: - Passed: zero load (6,7.98062) saturation (38,41.7814) -****************************line_8x8_ssa_xy : random traffic *******************************: - Passed: zero load (2,11.3721) saturation (38,104.132) -****************************linex8_4vc_4c : random traffic *******************************: - Passed: zero load (2,13.1512) saturation (34,126.007) -****************************ring_8x8_2cycle_xy : random traffic *******************************: - Passed: zero load (2,16.8517) saturation (38,120.208) -****************************line2_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,8.28947) saturation (100,-) -****************************line4_smart3 : transposed 1 traffic *******************************: - Passed: zero load (2,8.89928) saturation (54,147.034) -****************************Line_3x2_v2 : transposed 1 traffic *******************************: - Passed: zero load (2,9.68116) saturation (26,117.311) -****************************line_4_v1_B15 : transposed 1 traffic *******************************: - Passed: zero load (2,10.7986) saturation (54,150.53) -****************************line_4x3_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,11.7295) saturation (18,217.171) -****************************line_8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,15.1871) saturation (26,126.551) -****************************line_8_b2 : transposed 1 traffic *******************************: - Passed: zero load (2,19.2832) saturation (26,144.49) -****************************line_8_sbp6_xy : transposed 1 traffic *******************************: -****************************line_8_single_flit : transposed 1 traffic *******************************: - Passed: zero load (2,9.99617) saturation (26,65.1642) -****************************line_8x8_ssa_xy : transposed 1 traffic *******************************: - Passed: zero load (2,12.0755) saturation (26,125.579) -****************************linex8_4vc_4c : transposed 1 traffic *******************************: - Passed: zero load (2,15.1403) saturation (26,129.933) -****************************ring_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,18.0133) saturation (18,134.597) diff --git a/mpsoc/Integration_test/synthetic_sim/reports/multicast_report_old b/mpsoc/Integration_test/synthetic_sim/reports/multicast_report_old deleted file mode 100644 index adccc74..0000000 --- a/mpsoc/Integration_test/synthetic_sim/reports/multicast_report_old +++ /dev/null @@ -1,43 +0,0 @@ -Verification Results: -****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_LB5_B4 : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_selflp_mcast_f : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x2_bcast_f : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x2_bcast_p : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x2_mcast_p : Compile *******************************: - model is generated successfully. -****************************star6_2cycle_mcast_par : Compile *******************************: - model is generated successfully. -****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: - Passed: zero load (2,14.4623) saturation (22,261.684) -****************************mesh_4x4_LB5_B4 : random traffic *******************************: - Passed: zero load (2,13.234) saturation (26,78.9049) -****************************mesh_4x4_selflp_mcast_f : random traffic *******************************: - Passed: zero load (2,14.366) saturation (22,257.065) -****************************mesh_4x4x2_bcast_f : random traffic *******************************: - Passed: zero load (2,20.5192) saturation (6,1071.58) -****************************mesh_4x4x2_bcast_p : random traffic *******************************: - Passed: zero load (2,16.3674) saturation (6,317.19) -****************************mesh_4x4x2_mcast_p : random traffic *******************************: - Passed: zero load (2,13.544) saturation (14,177.748) -****************************star6_2cycle_mcast_par : random traffic *******************************: - Passed: zero load (2,6.531) saturation (42,82.0855) -****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: - Passed: zero load (2,14.8953) saturation (26,146.747) -****************************mesh_4x4_LB5_B4 : transposed 1 traffic *******************************: - Passed: zero load (2,13.3738) saturation (22,78.0417) -****************************mesh_4x4_selflp_mcast_f : transposed 1 traffic *******************************: - Passed: zero load (2,14.6488) saturation (22,166.723) -****************************mesh_4x4x2_bcast_f : transposed 1 traffic *******************************: - Passed: zero load (2,21.0549) saturation (6,863.495) -****************************mesh_4x4x2_bcast_p : transposed 1 traffic *******************************: - Passed: zero load (2,16.3766) saturation (6,371.293) -****************************mesh_4x4x2_mcast_p : transposed 1 traffic *******************************: - Passed: zero load (2,13.6081) saturation (10,78.461) -****************************star6_2cycle_mcast_par : transposed 1 traffic *******************************: - Passed: zero load (2,6.53488) saturation (42,35.6578) diff --git a/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report b/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report deleted file mode 100644 index 0de61d5..0000000 --- a/mpsoc/Integration_test/synthetic_sim/reports/vc_alloc_report +++ /dev/null @@ -1,37 +0,0 @@ -Verification Results: -****************************mesh_4x4x3_vc_nonspec : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x3_vc_spec1 : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x3_vc_spec2 : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_4vc : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_4vc_hetero1 : Compile *******************************: - model is generated successfully. -****************************mesh_8x8_4vc_hetero2 : Compile *******************************: - model is generated successfully. -****************************mesh_4x4x3_vc_nonspec : random traffic *******************************: - Passed: zero load (2,12.7475) saturation (26,188.161) -****************************mesh_4x4x3_vc_spec1 : random traffic *******************************: - Passed: zero load (2,12.53) saturation (22,78.2991) -****************************mesh_4x4x3_vc_spec2 : random traffic *******************************: - Passed: zero load (2,12.53) saturation (22,80.5533) -****************************mesh_8x8_4vc : random traffic *******************************: - Passed: zero load (2,18.2409) saturation (38,114.247) -****************************mesh_8x8_4vc_hetero1 : random traffic *******************************: - Passed: zero load (2,18.273) saturation (30,162.17) -****************************mesh_8x8_4vc_hetero2 : random traffic *******************************: - Passed: zero load (2,18.257) saturation (30,175.259) -****************************mesh_4x4x3_vc_nonspec : transposed 1 traffic *******************************: - Passed: zero load (2,13.0755) saturation (14,126.234) -****************************mesh_4x4x3_vc_spec1 : transposed 1 traffic *******************************: - Passed: zero load (2,12.8699) saturation (14,134.914) -****************************mesh_4x4x3_vc_spec2 : transposed 1 traffic *******************************: - Passed: zero load (2,12.8699) saturation (14,137.797) -****************************mesh_8x8_4vc : transposed 1 traffic *******************************: - Passed: zero load (2,19.3785) saturation (18,146.718) -****************************mesh_8x8_4vc_hetero1 : transposed 1 traffic *******************************: - Passed: zero load (2,19.449) saturation (18,150.624) -****************************mesh_8x8_4vc_hetero2 : transposed 1 traffic *******************************: - Passed: zero load (2,19.3972) saturation (18,141.983) diff --git a/mpsoc/Integration_test/synthetic_sim/run.sh b/mpsoc/Integration_test/synthetic_sim/run.sh index 67eb0a6..d9b773b 100755 --- a/mpsoc/Integration_test/synthetic_sim/run.sh +++ b/mpsoc/Integration_test/synthetic_sim/run.sh @@ -50,7 +50,7 @@ PRUN=20 MIN=2 MAX=80 STEP=4 -CONFS="default" +CONFS="general" CONFS_path=$(realpath $SCRPT_DIR_PATH/configurations) @@ -158,11 +158,14 @@ echo "---------------------------------------------" args="-p $PRUN -u $MAX -l $MIN -s $STEP -d $CONFS $model" -report="${SCRPT_DIR_PATH}/reports/${CONFS}_report" +log_dir="${SCRPT_DIR_PATH}/result_logs" +log_file="${log_dir}/${CONFS}" +golden_ref="${SCRPT_DIR_PATH}/golden_ref/${CONFS}" +mkdir -p $log_dir -if [ -f "$report" ]; then - rm "$report" +if [ -f "$log_file" ]; then + rm "$log_file" fi @@ -232,15 +235,15 @@ if [ "${servers[0]}" != "local" ]; then copy_sources echo "source \"/etc/profile\"; bash server_run.sh $args" $my_ssh $my_server "cd ${SERVER_ROOT_DIR}/mpsoc/Integration_test/synthetic_sim/src; source \"/etc/profile\"; bash server_run.sh $args;" - $my_scp -r "$my_server:${SERVER_ROOT_DIR}/mpsoc/Integration_test/synthetic_sim/report" "$report" + $my_scp -r "$my_server:${SERVER_ROOT_DIR}/mpsoc/Integration_test/synthetic_sim/result_logs/${CONFS}" "$log_file" else cd $SCRPT_DIR_PATH/src; bash server_run.sh $args - mv $SCRPT_DIR_PATH/report $report + fi wait -meld "$report" "${report}_old" & +meld "$golden_ref" "$log_file" & diff --git a/mpsoc/Integration_test/synthetic_sim/src/check.pl b/mpsoc/Integration_test/synthetic_sim/src/check.pl new file mode 100644 index 0000000..981f2ee --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/src/check.pl @@ -0,0 +1,131 @@ +#!/usr/bin/perl +use strict; +use warnings; + +my $tolerance=5; + +use Getopt::Std; + +# declare the perl command line flags/options we want to allow +my %options=(); +getopts("hn:o:", \%options); + +# test for the existence of the options on the command line. +# in a normal program you'd do more than just print these. + + + +# other things found on the command line +print "Other things found on the command line:\n" if $ARGV[0]; +foreach (@ARGV) +{ + print "$_\n"; +} + + +if (defined $options{h} ) { +print " Usage: perl verify.pl [options] + -h show this help + -o : Enter the golden refrence results file + -n : Enter the newly obtained results file +"; +exit; +} + +my $new_file= $options{n} // "result_new.txt"; +my $old_file= $options{o} // "result_old.txt"; +my $fail_report="$ENV{PRONOC_WORK}/failures.txt"; +# Track whether any failures or degradations were found +my $has_failures = 0; + +my (%old_results, %new_results); +my @failures=(); + +# Parse result files +parse_file($old_file, \%old_results); +parse_file($new_file, \%new_results); + + + +foreach my $key (sort keys %new_results) { + my $new = $new_results{$key}; + + if ($new->{status} eq "FAIL") { + print_error("[FAILURE] $key: Simulation failed"); + next; + } + + unless (exists $old_results{$key}) { + print "[NEW ENTRY] $key: No reference in old file.\n"; + next; + } + + my $old = $old_results{$key}; + + my $zero_delay_change = percent_increase($old->{zero_delay}, $new->{zero_delay}); + my $sat_inj_change = percent_decrease($old->{sat_inj}, $new->{sat_inj}); + + if ($zero_delay_change > $tolerance || $sat_inj_change > $tolerance) { + my $err=sprintf("[DEGRADED] %-60s Zero delay ↑ %.2f%%, Sat inj ↓ %.2f%%\n", $key, $zero_delay_change, $sat_inj_change); + print_error($err); + } else { + print "[OK] $key\n"; + } +} + + +sub print_error { + my ($msg) = @_; # Capture the argument + print "$msg.\n"; + push @failures, $msg; + $has_failures = 1; +} + +sub parse_file { + my ($file, $result_hash) = @_; + open my $fh, '<', $file or die "Cannot open $file: $!"; + my $key = ""; + while (<$fh>) { + if (/^\*+(.+?): (.*?) \*+:/) { + $key = "$1 : $2"; + } elsif (/Error in running simulation|%Error:/) { + $$result_hash{$key}{status} = "FAIL"; + } elsif (/Passed:\s+zero load \(\d+,([\d.]+)\)\s+saturation \((\d+),([\d.]+)\)/) { + $$result_hash{$key}{status} = "OK"; + $$result_hash{$key}{zero_delay} = $1; # Delay cycles + $$result_hash{$key}{sat_inj} = $2; # Injection ratio + } + } + close $fh; +} + +sub percent_increase { + my ($old, $new) = @_; + return 0 unless defined $old && $old != 0; + return (($new - $old) / $old) * 100; +} + +sub percent_decrease { + my ($old, $new) = @_; + return 0 unless defined $old && $old != 0; + return (($old - $new) / $old) * 100; +} + + + +open my $out, ">>$fail_report" or die "could not open $fail_report: $!"; +open my $in, '<', $new_file or die "Cannot open $new_file: $!"; + +foreach my $fail (@failures) { + print "$fail\n"; + print $out "$fail\n"; +} + +while (my $line = <$in>) { + print $out $line; +} + +close $in; +close $out; + +exit($has_failures); diff --git a/mpsoc/Integration_test/synthetic_sim/src/src.pl b/mpsoc/Integration_test/synthetic_sim/src/src.pl index f1b8ea1..7add35f 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/src.pl +++ b/mpsoc/Integration_test/synthetic_sim/src/src.pl @@ -28,7 +28,7 @@ my $src_verilator = "$root/src_verilator"; my $src_c = "$root/src_c"; my $src = "$script_path"; -my $report = "$dirname/report"; + #require "$root/perl_gui/lib/perl/common.pl"; require "$root/perl_gui/lib/perl/topology.pl"; @@ -456,7 +456,7 @@ sub compile_models{ } sub check_compilation_log { - my ($name,$ref,$inref) = @_; + my ($name,$ref,$inref,$log_file) = @_; my @log_report_match =@{$ref}; my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; my $logfile = "$work/$name/out.log"; @@ -469,7 +469,7 @@ sub check_compilation_log { } foreach my $line (@found) { - append_text_to_file($report,"\t $line\n"); + append_text_to_file($log_file,"\t $line\n"); } } @@ -478,21 +478,21 @@ sub check_compilation_log { sub check_compilation { - my ($self,$ref1,$inref,$mref)=@_; + my ($self,$ref1,$inref,$mref,$log_file)=@_; my @models = get_model_names($mref,$inref); foreach my $m (@models){ my ($name,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); - append_text_to_file($report,"****************************$name : Compile *******************************:\n"); + append_text_to_file($log_file,"****************************$name : Compile *******************************:\n"); #check if testbench is generated successfully if(-f "$work/$name/obj_dir/testbench"){ - append_text_to_file($report,"\t model is generated successfully.\n"); - check_compilation_log($name,$ref1,$inref); + append_text_to_file($log_file,"\t model is generated successfully.\n"); + check_compilation_log($name,$ref1,$inref,$log_file); }else{ - append_text_to_file($report,"\t model generation is FAILED.\n"); - check_compilation_log($name,$ref1,$inref); + append_text_to_file($log_file,"\t model generation is FAILED.\n"); + check_compilation_log($name,$ref1,$inref,$log_file); } } @@ -500,30 +500,30 @@ sub check_compilation { sub run_all_models { - my ($self,$inref,$mref) =@_; + my ($self,$inref,$mref,$log_file) =@_; my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; my @models = get_model_names($mref,$inref); foreach my $m (@models){ - run_traffic ($self,$m,'random',$inref); + run_traffic ($self,$m,'random',$inref,$log_file); } foreach my $m (@models){ - run_traffic ($self,$m,'transposed 1',$inref); + run_traffic ($self,$m,'transposed 1',$inref,$log_file); } } sub run_traffic { - my ($self,$model,$traffic,$inref)=@_; + my ($self,$model,$traffic,$inref,$log_file)=@_; my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; my ($name,$fpath,$fsuffix) = fileparse("$model",qr"\..[^.]*$"); my %param = get_model_parameter($model); my $min_pck = $param{'MIN_PCK_SIZE'}; - append_text_to_file($report,"****************************$name : $traffic traffic *******************************:\n"); + append_text_to_file($log_file,"****************************$name : $traffic traffic *******************************:\n"); unless (-f "$work/$name/obj_dir/testbench"){ - append_text_to_file($report,"\t Failed. Simulation model is not avaialable\n"); + append_text_to_file($log_file,"\t Failed. Simulation model is not avaialable\n"); return; } @@ -551,7 +551,7 @@ sub run_traffic { $proc1->wait; $proc1->die; - check_sim_results($self,$name,$traffic,$inref); + check_sim_results($self,$name,$traffic,$inref,$log_file); } @@ -607,7 +607,7 @@ sub get_zero_load_and_saturation{ sub check_sim_results{ - my ($self,$name,$traffic,$inref)=@_; + my ($self,$name,$traffic,$inref,$log_file)=@_; my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; my $file_name="${traffic}_results"; $file_name =~ s/\s+//g; @@ -621,7 +621,7 @@ sub check_sim_results{ my @errors = unix_grep("$file","ERROR:"); if (scalar @errors ){ - append_text_to_file($report,"\t Error in running simulation:\n @errors \n"); + append_text_to_file($log_file,"\t Error in running simulation:\n @errors \n"); $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="Failed"; $self->{'name'}{"$name"}{'traffic'}{$traffic}{'message'}="@errors"; return; @@ -647,7 +647,7 @@ sub check_sim_results{ - append_text_to_file($report,"\t Passed: zero load ($z,$zl) saturation ($s,$sl)\n"); + append_text_to_file($log_file,"\t Passed: zero load ($z,$zl) saturation ($s,$sl)\n"); $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="passed"; } diff --git a/mpsoc/Integration_test/synthetic_sim/src/verify.perl b/mpsoc/Integration_test/synthetic_sim/src/verify.perl index 8dcaac3..936ccf0 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/verify.perl +++ b/mpsoc/Integration_test/synthetic_sim/src/verify.perl @@ -19,7 +19,7 @@ package ProNOC; use lib $FindBin::Bin; use constant::boolean; - +use File::Path qw(make_path); use strict; @@ -99,8 +99,8 @@ package ProNOC; -my $dirname = dirname(__FILE__); -require "$dirname/src.pl"; +my $script_path = dirname(__FILE__); +require "$script_path/src.pl"; my @inputs =($paralel_run,$MIN,$MAX,$STEP,$model_dir); @@ -114,12 +114,24 @@ package ProNOC; } } + +my $dirname = realpath("$script_path/.."); +my $log_dir ="${dirname}/result_logs"; +my $log_file="${log_dir}/$model_dir"; + +unless (-d "$log_dir") { + print "Creating working directory inside $log_dir\n"; + mkdir("$log_dir", 0700) or die "Failed to create directory $log_dir: $!"; +} + + + check_models_are_exsited(\@models,\@inputs); my @log_report_match =("Error","Warning" ); -save_file ("$dirname/../report","Verification Results:\n"); +save_file ("$log_file","Verification Results:\n"); recompile_synful(); @@ -129,9 +141,9 @@ package ProNOC; compile_models($app,\@inputs,\@models); -check_compilation($app,\@log_report_match,\@inputs,\@models); +check_compilation($app,\@log_report_match,\@inputs,\@models,$log_file); -run_all_models($app,\@inputs,\@models); +run_all_models($app,\@inputs,\@models,$log_file); diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index c85e333..b1f99dd 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -326,14 +326,15 @@ module mesh_torus_mask_non_assignable_destport_no_self_loop #( input odd_column; generate - if(P>5)begin :p5 - assign dest_port_out[P_1-1:4] = dest_port_in[P_1-1:4]; //other local ports - end + /* verilator lint_off WIDTH */ if (TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin : oneD // A port can send packets to all other ports in these topologies /* verilator lint_on WIDTH */ assign dest_port_out = dest_port_in; end else begin : towD + if(P>5)begin :p5 + assign dest_port_out[P_1-1:4] = dest_port_in[P_1-1:4]; //other local ports + end /* verilator lint_off WIDTH */ if ( ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY") begin :xy /* verilator lint_on WIDTH */ @@ -1478,4 +1479,4 @@ module mesh_torus_dynamic_portsel_control #( end// ROUTE_TYPE end//for endgenerate -endmodule \ No newline at end of file +endmodule From 7d519af0d9dd4b0ff72e64ec66daed175de47067 Mon Sep 17 00:00:00 2001 From: amonemi Date: Sun, 25 May 2025 18:20:28 +0200 Subject: [PATCH 021/107] support hetrovc in phy_noc gen --- mpsoc/perl_gui/lib/perl/common.pl | 7 +- mpsoc/perl_gui/test.conf | 107 ----------------------- mpsoc/rtl/src_modelsim/testbench_noc.sv | 37 ++++---- mpsoc/rtl/src_noc/debug.v | 26 ++++-- mpsoc/rtl/src_noc/inout_ports.sv | 1 + mpsoc/rtl/src_noc/input_ports.sv | 86 +++++++++++++----- mpsoc/rtl/src_noc/mesh_torus.sv | 3 +- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 3 + mpsoc/rtl/src_noc/noc_top.sv | 12 ++- mpsoc/rtl/src_noc/ovc_list.sv | 34 +------ mpsoc/rtl/src_noc/pronoc_pkg.sv | 65 +++++++------- mpsoc/rtl/src_noc/router_top.sv | 14 +-- mpsoc/rtl/src_noc/router_two_stage.sv | 25 ++++-- mpsoc/rtl/src_noc/routing.v | 14 +++ mpsoc/rtl/src_noc/topology_localparam.v | 107 +++++++++++++++-------- mpsoc/rtl/src_openpiton/noc_localparam.v | 68 +++++++------- mpsoc/script/phy_noc_gen/phy_noc.pl | 4 +- 17 files changed, 303 insertions(+), 310 deletions(-) delete mode 100644 mpsoc/perl_gui/test.conf diff --git a/mpsoc/perl_gui/lib/perl/common.pl b/mpsoc/perl_gui/lib/perl/common.pl index 1814c3e..100e665 100644 --- a/mpsoc/perl_gui/lib/perl/common.pl +++ b/mpsoc/perl_gui/lib/perl/common.pl @@ -1104,8 +1104,9 @@ sub add_param_widget { $widget =get_dir_in_object ($self,$attribut1,$param,$value,'ref',10,$default); set_gui_status($self,$new_status,$ref_delay) if(defined $ref_delay); } - elsif ( $type eq "FILE_path"){ # use $content as extention - $widget =get_file_name_object ($self,$attribut1,$param,$content,undef,$new_status,$ref_delay); + elsif ( $type eq "FILE_path"){ # use $content for file extention:open_in + my ($ext, $open_in) = split(/:/, $content, 2); + $widget =get_file_name_object ($self,$attribut1,$param,$ext,$open_in,$new_status,$ref_delay); } elsif ( $type eq 'Fixed'){ $self->object_add_attribute($attribut1,$param,$default); @@ -1197,4 +1198,4 @@ sub max_win_size { return ($x,$y); } -1; \ No newline at end of file +1; diff --git a/mpsoc/perl_gui/test.conf b/mpsoc/perl_gui/test.conf deleted file mode 100644 index d1c6189..0000000 --- a/mpsoc/perl_gui/test.conf +++ /dev/null @@ -1,107 +0,0 @@ -$config = \{ - 'CLASS_6' => '1.81818181818182', - 'CLASS_0' => '1.81818181818182', - 'CLASS_17' => '1.81818181818182', - 'CLASS_7' => '1.81818181818182', - 'ratios' => '55', - 'CLASS_46' => '1.81818181818182', - 'CLASS_41' => '1.81818181818182', - 'CLASS_4' => '1.81818181818182', - 'CLASS_5' => '1.81818181818182', - 'CLASS_51' => '1.81818181818182', - 'CLASS_22' => '1.81818181818182', - 'sof_path' => '/home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc_work/simulate', - 'CLASS_19' => '1.81818181818182', - 'CLASS_3' => '1.81818181818182', - 'CLASS_36' => '1.81818181818182', - 'CLASS_31' => '1.81818181818182', - 'CLASS_24' => '1.81818181818182', - 'MCAST_PCK_SIZ_MIN' => '2', - 'PCK_NUM_LIMIT' => '20000', - 'color' => 2, - 'CLASS_18' => '1.81818181818182', - 'CLASS_34' => '1.81818181818182', - 'TRAFFIC_TYPE' => 'Synthetic', - 'CLASS_26' => '1.81818181818182', - 'CLASS_21' => '1.81818181818182', - 'CLASS_2' => '1.81818181818182', - 'CLASS_10' => '1.81818181818182', - 'CLASS_32' => '1.81818181818182', - 'CLASS_13' => '1.81818181818182', - 'CLASS_54' => '1.81818181818182', - 'sof_file' => 'simulate1', - 'SIM_CLOCK_LIMIT' => '10000', - 'CLASS_52' => '1.81818181818182', - 'CLASS_44' => '1.81818181818182', - 'CLASS_15' => '1.81818181818182', - 'PCK_SIZ_SEL' => 'random-range', - 'CLASS_42' => '1.81818181818182', - 'CLASS_25' => '1.81818181818182', - 'CLASS_49' => '1.81818181818182', - 'CLASS_37' => '1.81818181818182', - 'CLASS_23' => '1.81818181818182', - 'line_name' => 'sample0', - 'CLASS_11' => '1.81818181818182', - 'CLASS_16' => '1.81818181818182', - 'MCAST_TRAFFIC_TYPE' => 'Uniform-Random', - 'CLASS_1' => '1.81818181818182', - 'MCAST_TRAFFIC_RATIO' => '50', - 'CLASS_8' => '1.81818181818182', - 'CLASS_47' => '1.81818181818182', - 'MCAST_PCK_SIZ_MAX' => '4', - 'CLASS_39' => '1.81818181818182', - 'CLASS_20' => '1.81818181818182', - 'MIN_PCK_SIZE' => '2', - 'noc_info' => { - 'MIN_PCK_SIZE' => '2', - 'CAST_TYPE' => '"MULTICAST_PARTIAL"', - 'BYTE_EN' => 0, - 'PCK_TYPE' => '"MULTI_FLIT"', - 'B' => '4', - 'Fpay' => '32', - 'TOPOLOGY' => '"STAR"', - 'MUX_TYPE' => '"BINARY"', - 'LB' => 'B', - 'SWA_ARBITER_TYPE' => '"RRA"', - 'T1' => '6', - 'T3' => '1', - 'AVC_ATOMIC_EN' => 0, - 'WEIGHTw' => '4', - 'SSA_EN' => '"NO"', - 'SELF_LOOP_EN' => '"YES"', - 'ADD_PIPREG_AFTER_CROSSBAR' => '1\'b0', - 'ESCAP_VC_MASK' => '2\'b01', - 'VC_REALLOCATION_TYPE' => '"NONATOMIC"', - 'CONGESTION_INDEX' => 3, - 'ROUTE_NAME' => '"UNKNOWN"', - 'FIRST_ARBITER_EXT_P_EN' => 1, - 'DEBUG_EN' => '1', - 'V' => '2', - 'SMART_MAX' => '0', - 'C' => 0, - 'MCAST_ENDP_LIST' => '\'h0b', - 'T2' => 1, - 'COMBINATION_TYPE' => '"COMB_NONSPEC"' - }, - 'PCK_SIZE' => '6', - 'status' => 'failed', - 'CLASS_28' => '1.81818181818182', - 'CLASS_9' => '1.81818181818182', - 'CLASS_38' => '1.81818181818182', - 'CLASS_43' => '1.81818181818182', - 'CLASS_12' => '1.81818181818182', - 'CLASS_30' => '1.81818181818182', - 'CLASS_29' => '1.81818181818182', - 'CLASS_14' => '1.81818181818182', - 'CLASS_45' => '1.81818181818182', - 'CLASS_53' => '1.81818181818182', - 'CLASS_50' => '1.81818181818182', - 'CLASS_48' => '1.81818181818182', - 'MAX_PCK_SIZE' => '10', - 'CLASS_33' => '1.81818181818182', - 'MESSAGE_CLASS' => '0', - 'CLASS_27' => '1.81818181818182', - 'traffic' => 'random', - 'CLASS_40' => '1.81818181818182', - 'CLASS_35' => '1.81818181818182' - }; diff --git a/mpsoc/rtl/src_modelsim/testbench_noc.sv b/mpsoc/rtl/src_modelsim/testbench_noc.sv index 34eb6f7..b3b01bb 100755 --- a/mpsoc/rtl/src_modelsim/testbench_noc.sv +++ b/mpsoc/rtl/src_modelsim/testbench_noc.sv @@ -147,15 +147,15 @@ module testbench_noc; sent_stat.min_latency = latency; end end - endtask + endtask initial begin reset_st (rsvd_stat_total); reset_st (sent_stat_total); for(m=0;m= MIN_PACKET_SIZE && pck_size_o[core_num] <=MAX_PACKET_SIZE) rsv_size_array[pck_size_o[core_num]-MIN_PACKET_SIZE] = rsv_size_array[pck_size_o[core_num]-MIN_PACKET_SIZE]+1; - end - end + end + end end//always integer rsv_ideal_cnt,total_rsv_flit_number_old; @@ -477,13 +475,14 @@ module testbench_noc; wire all_done_in; assign all_done_in = (clk_counter > STOP_SIM_CLK) || ( total_sent_pck_num > STOP_PCK_NUM ); assign sent_done = all_done_in & ~ all_done_reg; - + logic report_active_ivcs; always @(`pronoc_clk_reset_edge)begin if (`pronoc_reset) begin all_done_reg <= 1'b0; rsv_ideal_cnt<=0; done<=1'b0; total_rsv_flit_number_old<=0; + report_active_ivcs<='0; end else begin all_done_reg <= all_done_in; total_rsv_flit_number_old<=total_rsv_flit_number; @@ -495,13 +494,15 @@ module testbench_noc; end if(rsv_ideal_cnt >= 100) begin // Injectors stopped sending packets, number of received and sent flits are not equal yet and for 100 cycles no flit is consumed. done<=1'b1; - #100 $display ("ERROR: The number of expected (%d) & received flits (%d) were not equal at the end of simulation",total_expect_rsv_flit_num ,total_rsv_flit_number); - + #50; + report_active_ivcs<=1'b1; + #50; + $display ("ERROR: The number of expected (%d) & received flits (%d) were not equal at the end of simulation",total_expect_rsv_flit_num ,total_rsv_flit_number); $stop; end end end - end + end initial total_active_endp=0; real avg_throughput,avg_latency_flit,avg_latency_pck,std_dev,avg_latency_per_hop,min_avg_latency_per_class; @@ -516,7 +517,7 @@ module testbench_noc; always @( posedge done) begin for (core_num=0; core_num0) total_active_endp = total_active_endp +1; - end + end avg_throughput= ((total_sent_flit_number*100)/total_active_endp )/clk_counter; avg_latency_flit =sum_clk_h2h/$itor(total_rsv_pck_num); avg_latency_pck =sum_clk_h2t/$itor(total_rsv_pck_num); @@ -725,4 +726,4 @@ module testbench_noc; ); endmodule -`endif \ No newline at end of file +`endif diff --git a/mpsoc/rtl/src_noc/debug.v b/mpsoc/rtl/src_noc/debug.v index 7236635..7021e9e 100644 --- a/mpsoc/rtl/src_noc/debug.v +++ b/mpsoc/rtl/src_noc/debug.v @@ -442,6 +442,11 @@ module endp_addr_encoder #( .id(id), .code(code) ); + end else if (TOPOLOGY == "MULTI_MESH") begin :mmesh + multimesh_address_encoder addr_encoder ( + .rid_in(id), + .addr_st_o(code) + ); end else begin :custom assign code =id; end @@ -459,15 +464,15 @@ module endp_addr_decoder #( ) ( id, code -); +); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2> c*V; return shiftted[V-1 : 0]; end endfunction - //Masks VCs acording to message classes logic [V-1 : 0] class_table [C-1 : 0]; - logic [V-1 : 0] ovc_message_class, ovc_topology; + logic [V-1 : 0] ovc_message_class; always_comb begin for(int i=0; iLB) ? log2(B+1) : log2(LB+1); typedef struct packed { - bit endp_port; + bit endp_port; // If set to 1, the corresponding port is connected to an endpoint. logic [EAw-1 : 0] endp_addr; // If endp_port is 1, this field represents the address of the connected endpoint. @@ -272,7 +269,7 @@ package pronoc_pkg; // when heterogeneous VC support is enabled. } ctrl_chanel_t; - localparam CTRL_CHANEL_w = $bits(ctrl_chanel_t); + localparam CTRL_CHANEL_w = $bits(ctrl_chanel_t); typedef struct packed { flit_chanel_t flit_chanel; @@ -311,7 +308,7 @@ package pronoc_pkg; hetero_ovc_unary = (HETERO_VC == 0) ? {V{1'b1}} : (HETERO_VC == 1) ? (1 << VC_CONFIG_TABLE [router_id][0]) - 1 : - (1 << VC_CONFIG_TABLE [router_id][router_port_num]) -1; + (1 << VC_CONFIG_TABLE [router_id][router_port_num]) -1; end endfunction @@ -329,12 +326,12 @@ package pronoc_pkg; typedef struct packed { integer value; - integer percentage; + integer percentage; }rnd_discrete_t; //packet injector interface localparam PCK_INJ_Dw =64;//TODO to be defined by user - localparam PCK_SIZw= log2(MAX_PCK_SIZ+1); + localparam PCK_SIZw= log2(MAX_PCK_SIZ+1); typedef struct packed { logic [PCK_INJ_Dw-1 : 0] data; @@ -348,7 +345,7 @@ package pronoc_pkg; logic [DISTw-1 : 0] distance; logic [15: 0] h2t_delay; } pck_injct_t; - localparam PCK_INJCT_w = $bits(pck_injct_t); + localparam PCK_INJCT_w = $bits(pck_injct_t); typedef struct packed { logic [BYPASSw-1 : 0] bypassed_num; diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 44e6c38..afcde33 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -113,8 +113,7 @@ module router_top #( .iport_info(iport_info), .oport_info(oport_info), .smart_ctrl_in(smart_ctrl), - .current_r_addr(current_r_addr), - .current_r_id(current_r_id), + .router_config_in(router_config_in), .chan_in(r2_chan_in), .chan_out(r2_chan_out), .ctrl_in(ctrl_in), @@ -294,17 +293,20 @@ module router_top #( end /* verilator lint_on WIDTH */ - - logic report_active_ivcs = 0; generate + `ifdef IVC_DEBUG + wire report_active_ivcs = testbench_noc.report_active_ivcs; for(i=0; iSOUTH)? i-SOUTH : LOCAL; + assign ctrl_out[i].endp_addr = router_config_in[ (ENP_NUM+1)*EAw-1 : ENP_NUM*EAw]; + end else if (IS_MULTI_MESH) begin + assign ctrl_out[i].endp_addr = router_config_in[EAw-1 : 0]; + end //TODO complete it for fattree and bin tree assign chan_out[i].flit= flit_out_all [(i+1)*Fw-1: i*Fw]; assign chan_out[i].flit_wr= flit_out_wr_all [i]; assign chan_out[i].credit= credit_out_all [(i+1)*V-1: i*V] | credit_release_out [(i+1)*V-1: i*V]; @@ -669,4 +680,4 @@ module credit_release_gen #( end end -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/routing.v b/mpsoc/rtl/src_noc/routing.v index 258ad2a..a514c90 100755 --- a/mpsoc/rtl/src_noc/routing.v +++ b/mpsoc/rtl/src_noc/routing.v @@ -197,6 +197,16 @@ module conventional_routing #( .dest_e_addr(dest_e_addr), .destport(destport) ); + /* verilator lint_off WIDTH */ + end else if (TOPOLOGY=="MULTI_MESH") begin : multimesh + /* verilator lint_on WIDTH */ + mesh_cluster_route_xyz #( + .NOC_ID(NOC_ID) + ) the_conventional_routing ( + .current_router_addr_i(current_r_addr), + .destination_router_addr_i(dest_e_addr[EAw-1:0]), + .router_port_out(destport) + ); end else begin :custom custom_ni_routing #( .TOPOLOGY(TOPOLOGY), @@ -398,6 +408,10 @@ module look_ahead_routing #( /* verilator lint_on WIDTH */ //look-ahead routing is not needed in star topology as there is only one router assign lkdestport_encoded={DSTPw{1'b0}}; + /* verilator lint_off WIDTH */ + end else if (TOPOLOGY == "MULTI_MESH") begin : multimesh + /* verilator lint_on WIDTH */ + assign lkdestport_encoded={DSTPw{1'b0}}; end else begin : custom custom_lkh_routing #( .TOPOLOGY(TOPOLOGY), diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index dd54037..20ea2fb 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -7,6 +7,7 @@ * Description: ***************************************/ `ifdef INCLUDE_TOPOLOGY_LOCALPARAM + localparam [0:0] /* verilator lint_off WIDTH */ IS_LINE = (TOPOLOGY == "LINE"), @@ -16,15 +17,20 @@ IS_TORUS= (TOPOLOGY == "TORUS"), IS_FATTREE=(TOPOLOGY == "FATTREE"), IS_TREE= (TOPOLOGY == "TREE"), - IS_STAR= (TOPOLOGY == "STAR"); + IS_STAR= (TOPOLOGY == "STAR"), + IS_MULTI_MESH=(TOPOLOGY == "MULTI_MESH"); /* verilator lint_on WIDTH */ - //MESH, TORUS Topology p=5 + //MESH, TORUS Topology p=5 localparam LOCAL = 0, EAST = 1, NORTH = 2, WEST = 3, SOUTH = 4; + //MULTI_MESH + localparam + UP = 5, + DOWN=6; //LINE RING Topology p=3 localparam @@ -34,11 +40,11 @@ function automatic integer log2; input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 4 ) port_buffer_size = LB; - end + end else if (IS_MULTI_MESH) begin + if (router_port_num == 0) port_buffer_size = LB; + end end endfunction - + /******************* * "RING" "LINE" "MESH" TORUS" "FMESH" ******************/ @@ -114,17 +124,17 @@ //route type localparam NX = T1, - NY = T2, + NY = T2, NL = T3, NXw = log2(NX), NYw= log2(NY), NLw= log2(NL), PPSw_MESH_TORI =4, //port presel width for adaptive routing - /* verilator lint_off WIDTH */ + /* verilator lint_off WIDTH */ ROUTE_TYPE_MESH_TORI = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", - R2R_CHANELS_MESH_TORI= (IS_RING || IS_LINE)? 2 : 4, + R2R_CHANELS_MESH_TORI= (IS_RING || IS_LINE)? 2 : 4, R2E_CHANELS_MESH_TORI= NL, RAw_MESH_TORI = ( IS_RING || IS_LINE)? NXw : NXw + NYw, EAw_MESH_TORI = (NL==1) ? RAw_MESH_TORI : RAw_MESH_TORI + NLw, @@ -133,7 +143,7 @@ MAX_P_MESH_TORI = R2R_CHANELS_MESH_TORI + R2E_CHANELS_MESH_TORI, DSTPw_MESH_TORI = R2R_CHANELS_MESH_TORI, // P-1 NE_PER_R_MESH_TORI = NL; - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ /**************** * FMESH @@ -144,8 +154,8 @@ MAX_P_FMESH = 4 + NL, EAw_FMESH = RAw_MESH_TORI + log2(MAX_P_FMESH); /****************** - * FATTREE - ******************/ + * FATTREE + * *****************/ localparam K=T1, L=T2, @@ -192,16 +202,28 @@ ***********************/ localparam ROUTE_TYPE_CUSTOM = "DETERMINISTIC", - NE_CUSTOM = T1, //total number of endpoints + NE_CUSTOM = T1, // total number of endpoints NR_CUSTOM = T2, // total number of routers EAw_CUSTOM = log2(NE_CUSTOM), RAw_CUSTOM = log2(NR_CUSTOM), MAX_P_CUSTOM = T3, DSTPw_CUSTOM = log2(MAX_P_CUSTOM), NE_PER_R_CUSTOM=MAX_P_CUSTOM;//just take the max possible value as it can be variable per router + /*********************** + * MULTI_MESH - made by yaml noc generator + ************************/ + localparam + ROUTE_TYPE_MULTI_MESH = "DETERMINISTIC", + NE_MULTI_MESH = T1, // total number of endpoints + NR_MULTI_MESH = T1, // total number of routers + RAw_MULTI_MESH = T2, + DAw_MULTI_MESH = 2*T2, // destination address width + EAw_MULTI_MESH = T2, + MAX_P_MULTI_MESH = 7, + DSTPw_MULTI_MESH = log2(MAX_P_MULTI_MESH); /* verilator lint_off WIDTH */ localparam - PPSw = PPSw_MESH_TORI, + PPSw = PPSw_MESH_TORI, // maximum number of port in a router in the topology MAX_P = (IS_FATTREE)? MAX_P_FATTREE: @@ -209,8 +231,9 @@ (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? MAX_P_MESH_TORI: (IS_FMESH)? MAX_P_MESH_TORI: (IS_STAR) ? MAX_P_STAR: + (IS_MULTI_MESH) ? MAX_P_MULTI_MESH: MAX_P_CUSTOM, - // destination port width in header flit + // destination port width in header flit DSTPw = // Each asserted bit indicats that the flit should be sent to that port (IS_FATTREE)? DSTPw_FATTREE: @@ -219,14 +242,16 @@ (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? DSTPw_MESH_TORI: (IS_FMESH)? DSTPw_MESH_TORI: (IS_STAR) ? DSTPw_STAR: + (IS_MULTI_MESH) ? DSTPw_MULTI_MESH: DSTPw_CUSTOM, - //router address width + //router address width RAw = (IS_FATTREE)? RAw_FATTREE: (IS_TREE)? RAw_TREE: (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? RAw_MESH_TORI: (IS_FMESH)? RAw_MESH_TORI: (IS_STAR) ? RAw_STAR: + (IS_MULTI_MESH) ? RAw_MULTI_MESH: RAw_CUSTOM, //endpoint address width EAw = @@ -235,15 +260,18 @@ (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? EAw_MESH_TORI: (IS_FMESH)? EAw_FMESH: (IS_STAR) ? EAw_STAR: - EAw_CUSTOM, - // total number of endpoints + (IS_MULTI_MESH) ? EAw_MULTI_MESH: + EAw_CUSTOM, + // total number of endpoints NE = (IS_FATTREE)? NE_FATTREE: (IS_TREE)? NE_TREE: (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? NE_MESH_TORI: (IS_FMESH)? NE_FMESH: (IS_STAR)? NE_STAR: + (IS_MULTI_MESH) ? NE_MULTI_MESH: NE_CUSTOM, + // total number of endpoint per router NE_PER_R = (IS_FATTREE)? NE_PER_R_FATTREE: @@ -251,6 +279,7 @@ (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? NE_PER_R_MESH_TORI: (IS_FMESH)? NE_PER_R_MESH_TORI: (IS_STAR)? NE_PER_R_STAR: + (IS_MULTI_MESH) ? 1: NE_PER_R_CUSTOM, //Destination endpoint(s) address width DAw_OFFSETw = (IS_MESH || IS_TORUS || IS_FMESH)? NX : 0, @@ -260,18 +289,20 @@ (CAST_TYPE == "MULTICAST_PARTIAL" && EAw >= MCAST_PRTLw) ? EAw +1 : (CAST_TYPE == "MULTICAST_PARTIAL" && EAw < MCAST_PRTLw) ? MCAST_PRTLw +1 : EAw +1, //broadcast - DAw = + DAw = + (IS_MULTI_MESH) ? DAw_MULTI_MESH : (CAST_TYPE == "UNICAST") ? EAw: - MCASTw + DAw_OFFSETw, - //total number of routers + MCASTw + DAw_OFFSETw, + //total number of routers NR = (IS_FATTREE)? NR_FATTREE: (IS_TREE)? NR_TREE: (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? NR_MESH_TORI: (IS_FMESH)? NR_FMESH: (IS_STAR) ? NR_STAR: - NR_CUSTOM, - //routing algorithm type + (IS_MULTI_MESH) ? NR_MULTI_MESH: + NR_CUSTOM, + //routing algorithm type ROUTE_TYPE = (IS_FATTREE)? ROUTE_TYPE_FATTREE: (IS_TREE)? ROUTE_TYPE_TREE: @@ -279,7 +310,7 @@ (IS_FMESH)? ROUTE_TYPE_MESH_TORI: (IS_STAR) ? ROUTE_TYPE_STAR: ROUTE_TYPE_CUSTOM; - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ function automatic integer mcast_id_to_endp_id; input integer mcast_id; reg [NE-1 : 0] mcast_list; @@ -293,11 +324,11 @@ /* verilator lint_on WIDTH */ mcast_id_to_endp_id =mcast_id; end else begin - while( k!=mcast_id+1) begin + while( k!=mcast_id+1) begin if( mcast_list[mcast_id_to_endp_id]==1'b1) begin - k=k+1; + k=k+1; end - mcast_id_to_endp_id= mcast_id_to_endp_id+1; + mcast_id_to_endp_id= mcast_id_to_endp_id+1; end end end @@ -337,12 +368,12 @@ input integer in; integer y, x, l,p, diff,mul; begin - mul = NX*NY*NL; + mul = NX*NY*NL; if(in < mul) begin y = ((in/NL) / NX ); x = ((in/NL) % NX ); l = (in % NL); - p = (l==0)? LOCAL : 4+l; + p = (l==0)? LOCAL : 4+l; end else begin diff = in - mul ; if( diff < NX) begin //top mesh edge @@ -363,9 +394,9 @@ p = EAST; end end//else - fmesh_addrencode = ( p<<(NXw+NYw) | (y< Date: Sun, 25 May 2025 18:51:08 +0200 Subject: [PATCH 022/107] fix string termination bug --- mpsoc/rtl/src_noc/router_top.sv | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index afcde33..98c5d3d 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -300,8 +300,7 @@ module router_top #( for(j=0; j Date: Mon, 26 May 2025 00:29:30 +0200 Subject: [PATCH 023/107] fix linting --- mpsoc/rtl/src_modelsim/multicast_injector.sv | 9 +-- mpsoc/rtl/src_noc/debug.v | 6 ++ mpsoc/rtl/src_noc/fmesh.sv | 18 +----- mpsoc/rtl/src_noc/header_flit.sv | 2 +- mpsoc/rtl/src_noc/mesh_torus.sv | 33 +++-------- mpsoc/rtl/src_noc/multicast.sv | 32 +++-------- mpsoc/rtl/src_noc/noc_top.sv | 16 ++---- mpsoc/rtl/src_noc/packet_injector.sv | 9 +-- mpsoc/rtl/src_noc/pronoc_pkg.sv | 6 +- mpsoc/rtl/src_noc/router_bypass.sv | 30 +++------- mpsoc/rtl/src_noc/router_two_stage.sv | 4 +- mpsoc/rtl/src_noc/ss_allocator.sv | 16 ++---- mpsoc/rtl/src_noc/traffic_gen_top.sv | 53 ++++-------------- mpsoc/rtl/src_openpiton/piton_mesh.sv | 59 +++++--------------- 14 files changed, 74 insertions(+), 219 deletions(-) diff --git a/mpsoc/rtl/src_modelsim/multicast_injector.sv b/mpsoc/rtl/src_modelsim/multicast_injector.sv index 142ffb8..8e74f5f 100644 --- a/mpsoc/rtl/src_modelsim/multicast_injector.sv +++ b/mpsoc/rtl/src_modelsim/multicast_injector.sv @@ -302,14 +302,7 @@ module multicast_injector #( assign chan_out.flit_chanel.credit= credit_o; assign chan_out.ctrl_chanel.credit_init_val= LB; assign chan_out.ctrl_chanel.endp_port =1'b1; - distance_gen #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw), - .DISTw(DISTw) - ) the_distance_gen ( + distance_gen the_distance_gen ( .src_e_addr(sender_endp_addr_reg[vc_bin]), .dest_e_addr(current_e_addr), .distance(pck_injct_out.distance) diff --git a/mpsoc/rtl/src_noc/debug.v b/mpsoc/rtl/src_noc/debug.v index 7021e9e..53b47db 100644 --- a/mpsoc/rtl/src_noc/debug.v +++ b/mpsoc/rtl/src_noc/debug.v @@ -431,7 +431,9 @@ module endp_addr_encoder #( .id(id), .code(code) ); + /* verilator lint_off WIDTH */ end else if (TOPOLOGY == "FMESH") begin :fmesh + /* verilator lint_on WIDTH */ fmesh_addr_encoder #( .NX(T1), .NY(T2), @@ -442,7 +444,9 @@ module endp_addr_encoder #( .id(id), .code(code) ); + /* verilator lint_off WIDTH */ end else if (TOPOLOGY == "MULTI_MESH") begin :mmesh + /* verilator lint_on WIDTH */ multimesh_address_encoder addr_encoder ( .rid_in(id), .addr_st_o(code) @@ -516,7 +520,9 @@ module endp_addr_decoder #( .id(id), .code(code) ); + /* verilator lint_off WIDTH */ end else if (TOPOLOGY == "MULTI_MESH") begin + /* verilator lint_on WIDTH */ multimesh_address_decoder addr_coder ( .rid_out(id), .addr_st_i(code) diff --git a/mpsoc/rtl/src_noc/fmesh.sv b/mpsoc/rtl/src_noc/fmesh.sv index c84f792..33ca885 100644 --- a/mpsoc/rtl/src_noc/fmesh.sv +++ b/mpsoc/rtl/src_noc/fmesh.sv @@ -358,26 +358,12 @@ endmodule /******************** * distance_gen ********************/ -module fmesh_distance_gen #( - parameter T1= 4, // number of router in x axis - parameter T2= 4, // number of router in y axis - parameter T3= 4, - parameter EAw=4, - parameter DISTw=4 -)( +module fmesh_distance_gen ( src_e_addr, dest_e_addr, distance ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 dest_x)? src_x - dest_x : dest_x - src_x; y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; diff --git a/mpsoc/rtl/src_noc/multicast.sv b/mpsoc/rtl/src_noc/multicast.sv index ea18ea6..de99e08 100644 --- a/mpsoc/rtl/src_noc/multicast.sv +++ b/mpsoc/rtl/src_noc/multicast.sv @@ -26,9 +26,7 @@ module multicast_routing # ( input [DAw-1 : 0] dest_e_addr; output [DSTPw-1 : 0] destport; generate - /* verilator lint_off WIDTH */ - if(TOPOLOGY=="MESH") begin: mesh - /* verilator lint_on WIDTH */ + if(IS_MESH) begin: mesh multicast_routing_mesh #( .NOC_ID(NOC_ID), .P(P) , @@ -38,9 +36,7 @@ module multicast_routing # ( .dest_e_addr(dest_e_addr), // destination endpoint address .destport(destport) ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "FMESH") begin : fmesh - /* verilator lint_on WIDTH */ + end else if (IS_FMESH) begin : fmesh multicast_routing_fmesh #( .NOC_ID(NOC_ID), .P(P) , @@ -50,9 +46,7 @@ module multicast_routing # ( .dest_e_addr(dest_e_addr), // destination endpoint address .destport(destport) ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "STAR") begin : star - /* verilator lint_on WIDTH */ + end else if (IS_STAR) begin : star multicast_routing_star #( .NOC_ID(NOC_ID), .P(P) , @@ -366,9 +360,7 @@ module mcast_dest_list_decode #( genvar i; generate - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "STAR") begin :star - /* verilator lint_on WIDTH */ + if(IS_STAR) begin :star assign mcast_dst_coded=dest_e_addr; end else begin :no_star assign {row_has_any_dest,mcast_dst_coded}=dest_e_addr; @@ -516,7 +508,7 @@ module multicast_chan_in_process #( wire [DAw-1 : 0] dest_e_addr; genvar i; generate - if(TOPOLOGY == "MESH") begin : mesh_ + if(IS_MESH) begin : mesh_ assign dest_e_addr = {row_has_any_dest,mcast_dst_coded}; if(SW_LOC == LOCAL || SW_LOC > SOUTH) begin :endp wire [NE/NX-1 : 0] endp_mask [NX-1 : 0]; @@ -544,9 +536,7 @@ module multicast_chan_in_process #( assign destport_o = destport; end end //mesh - /* verilator lint_off WIDTH */ - else if (TOPOLOGY == "FMESH" ) begin :fmesh_ - /* verilator lint_on WIDTH */ + else if ( IS_FMESH ) begin :fmesh_ assign dest_e_addr = {row_has_any_dest,mcast_dst_coded}; localparam MAX_ENDP_NUM_IN_SAME_ROW = NY * NL + NY + 2; localparam ENDP_NUM_IN_MIDLE_ROW = NY * NL + 2; @@ -583,9 +573,7 @@ module multicast_chan_in_process #( end assign destport_o = (endp_port) ? destport : destport_tmp ; assign row_has_any_dest = (endp_port) ? row_has_any_dest_endp_port : row_has_any_dest_in; - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "STAR" ) begin :star_ - /* verilator lint_on WIDTH */ + end else if (IS_STAR ) begin :star_ assign destport_o = destport; assign dest_e_addr = mcast_dst_coded; end @@ -674,10 +662,8 @@ module multicast_dst_sel # ( generate for (i=0; i 4) begin : local_ports assign goes_straight_o = 1'b0; // There is not a next router in this case at all end else begin :non_local @@ -414,9 +408,7 @@ module check_straight_oport #( assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; end//else end//mesh_tori - /* verilator lint_off WIDTH */ - else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :oneD - /* verilator lint_on WIDTH */ + else if(IS_RING | IS_LINE) begin :oneD if (SS_PORT_LOC == 0 || SS_PORT_LOC > 2) begin : local_ports assign goes_straight_o = 1'b0; // There is not a next router in this case at all end else begin :non_local @@ -507,7 +499,7 @@ module smart_validity_check_per_ivc #( smart_mask_available_ss_ovc_o; output reg [V-1 : 0] smart_ivc_granted_ovc_num_o; - + always @(*) begin smart_ivc_granted_ovc_num_o={V{1'b0}}; smart_ivc_granted_ovc_num_o[IVC_NUM]=smart_ivc_num_getting_ovc_grant_o; @@ -532,7 +524,7 @@ module smart_validity_check_per_ivc #( /* verilator lint_off WIDTH */ wire non_empty_ivc_condition =(PCK_TYPE == "SINGLE_FLIT")? 1'b0 :ivc_request; /* verilator lint_on WIDTH */ - + assign condition2=( ADD_PIPREG_AFTER_CROSSBAR == 1)? ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr| ss_ovc_crossbar_wr): ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr); // ss_port_link_reg_flit_wr are identical with ss_ovc_crossbar_wr when there is no link reg @@ -625,11 +617,9 @@ module smart_allocator_per_iport # ( wire [DSTPw-1 : 0] destport,lkdestport; wire goes_straight; - /* verilator lint_off WIDTH */ - localparam LOCATED_IN_NI= - (TOPOLOGY=="RING" || TOPOLOGY=="LINE") ? (SW_LOC == 0 || SW_LOC>2) : - (TOPOLOGY =="MESH" || TOPOLOGY=="TORUS" || TOPOLOGY == "FMESH")? (SW_LOC == 0 || SW_LOC>4) : 0; - /* verilator lint_on WIDTH */ + localparam LOCATED_IN_NI = + (IS_RING | IS_LINE) ? (SW_LOC == 0 || SW_LOC > 2) : + (IS_MESH | IS_TORUS | IS_FMESH) ? (SW_LOC == 0 || SW_LOC > 4 ) : 0; // does the route computation for the current router conventional_routing #( @@ -657,10 +647,6 @@ module smart_allocator_per_iport # ( pronoc_register #(.W(DSTPw)) reg1 (.in(destport), .reset(reset), .clk(clk), .out(smart_destport_o)); check_straight_oport #( - .TOPOLOGY ( TOPOLOGY), - .ROUTE_NAME ( ROUTE_NAME), - .ROUTE_TYPE ( ROUTE_TYPE), - .DSTPw ( DSTPw), .SS_PORT_LOC ( SS_PORT_LOC) ) check_straight ( .destport_coded_i (destport), diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 96d9a8b..59cd90f 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -435,9 +435,7 @@ module router_two_stage #( `ifdef SIMULATION generate - /* verilator lint_off WIDTH */ - if(DEBUG_EN && TOPOLOGY == "MESH")begin :dbg - /* verilator lint_on WIDTH */ + if(DEBUG_EN & IS_MESH)begin :dbg debug_mesh_edges #( .T1(T1), .T2(T2), diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index 02a2282..ce74081 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -217,7 +217,7 @@ module ssa_per_vc #( SW_LOC = V_GLOBAL/V, V_LOCAL = V_GLOBAL%V; /* verilator lint_off WIDTH */ - localparam SSA_EN_IN_PORT = ((TOPOLOGY== "MESH" || TOPOLOGY == "TORUS") && (ROUTE_TYPE == "FULL_ADAPTIVE") && (SS_PORT==2 || SS_PORT == 4) && ((1<0)begin :not_first_x assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; end else begin :first_x - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "LINE") begin : line_first_x - /* verilator lint_on WIDTH */ + if(IS_LINE) begin : line_first_x assign router_chan_in[x][BACKWARD]={PITON_CHANEL_w{1'b0}}; end else begin : ring_first_x assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; @@ -183,17 +177,11 @@ module piton_mesh assign router_chan_in[`router_id(x,y)][EAST]= router_chan_out [`router_id(x+1,y)][WEST]; //assign router_credit_in_all [`SELECT_WIRE(x,y,EAST,V)] = router_credit_out_all [`SELECT_WIRE((x+1),y,WEST,V)]; end else begin :last_x - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin :last_x_mesh - /* verilator lint_on WIDTH */ + if(IS_MESH) begin :last_x_mesh assign router_chan_in[`router_id(x,y)][EAST] = {PITON_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin : last_x_torus - /* verilator lint_on WIDTH */ + end else if(IS_TORUS) begin : last_x_torus assign router_chan_in[`router_id(x,y)][EAST] = router_chan_out [`router_id(0,y)][WEST]; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FMESH") begin : last_x_fmesh //connect to endp - /* verilator lint_on WIDTH */ + end else if(IS_MESH) begin : last_x_fmesh //connect to endp localparam EAST_ID = NX*NY*NL + 2*NX + NY +y; assign router_chan_in [`router_id(x,y)][EAST] = chan_in_all [EAST_ID]; assign chan_out_all [EAST_ID] = router_chan_out [`router_id(x,y)][EAST]; @@ -202,17 +190,11 @@ module piton_mesh if(y>0) begin : not_first_y assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; end else begin :first_y - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin : first_y_mesh - /* verilator lint_on WIDTH */ + if(IS_MESH) begin : first_y_mesh assign router_chan_in[`router_id(x,y)][NORTH] = {PITON_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :first_y_torus - /* verilator lint_on WIDTH */ + end else if(IS_TORUS) begin :first_y_torus assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(NY-1))][SOUTH]; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FMESH") begin : first_y_fmesh //connect to endp - /* verilator lint_on WIDTH */ + end else if(IS_FMESH) begin : first_y_fmesh //connect to endp localparam NORTH_ID = NX*NY*NL + x; assign router_chan_in [`router_id(x,y)][NORTH] = chan_in_all [NORTH_ID]; assign chan_out_all [NORTH_ID] = router_chan_out [`router_id(x,y)][NORTH]; @@ -221,17 +203,11 @@ module piton_mesh if(x>0)begin :not_first_x assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; end else begin :first_x - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin :first_x_mesh - /* verilator lint_on WIDTH */ + if(IS_MESH) begin :first_x_mesh assign router_chan_in[`router_id(x,y)][WEST] = {PITON_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :first_x_torus - /* verilator lint_on WIDTH */ + end else if(IS_TORUS) begin :first_x_torus assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FMESH") begin : first_x_fmesh //connect to endp - /* verilator lint_on WIDTH */ + end else if(IS_FMESH) begin : first_x_fmesh //connect to endp localparam WEST_ID = NX*NY*NL +2*NX + y; assign router_chan_in [`router_id(x,y)][WEST] = chan_in_all [WEST_ID]; assign chan_out_all [WEST_ID] = router_chan_out [`router_id(x,y)][WEST]; @@ -240,16 +216,11 @@ module piton_mesh if(y < NY-1) begin : firsty assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; end else begin : lasty - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "MESH") begin :ly_mesh - /* verilator lint_on WIDTH */ + if(IS_MESH) begin :ly_mesh assign router_chan_in[`router_id(x,y)][SOUTH]= {PITON_CHANEL_w{1'b0}}; - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "TORUS") begin :ly_torus - /* verilator lint_on WIDTH */ + end else if(IS_TORUS) begin :ly_torus assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; - end else if(TOPOLOGY == "FMESH") begin : ly_fmesh //connect to endp - /* verilator lint_on WIDTH */ + end else if(IS_FMESH) begin : ly_fmesh //connect to endp localparam SOUTH_ID = NX*NY*NL + NX + x; assign router_chan_in [`router_id(x,y)][SOUTH] = chan_in_all [SOUTH_ID]; assign chan_out_all [SOUTH_ID] = router_chan_out [`router_id(x,y)][SOUTH]; From 73086ed3cc6bfca2860c162457e0ed5c283a2b54 Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 26 May 2025 00:36:16 +0200 Subject: [PATCH 024/107] fix linting --- mpsoc/rtl/src_noc/mesh_torus.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 5928019..37b52fd 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -676,7 +676,7 @@ module mesh_torus_distance_gen ( Xw = log2(T1), // number of node in x axis Yw = log2(NYY); // number of node in y axis localparam [Xw : 0] NX = T1; - localparam [Yw : 0] NY = NYY; + localparam [Yw : 0] NY = NYY [Yw : 0]; input [EAw-1 : 0] src_e_addr; input [EAw-1 : 0] dest_e_addr; From 7d942d89861f9a7519af64fc8306c9235d3a6d2d Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 26 May 2025 14:59:40 +0200 Subject: [PATCH 025/107] add some configrations for altera compilation in intigration test --- .gitignore | 2 +- .../Altera/configurations/line4_smart3 | 16 + .../Altera/configurations/mesh_3x3_v2_ssa | 11 + .../configurations/mesh_4x4_2cycle_mcast_f | 8 + .../configurations/mesh_4x4_2cycle_xy_v2 | 7 + .../Altera/golden_ref/line4_smart3 | 41 + .../mesh_3x3_v2_ssa} | 0 .../Altera/golden_ref/mesh_4x4_2cycle_mcast_f | 39 + .../Altera/golden_ref/mesh_4x4_2cycle_xy_v2 | 47 + mpsoc/Integration_test/Altera/report | 47 - mpsoc/Integration_test/Altera/run.sh | 174 ++- .../Altera/src/noc_localparam.v | 50 - .../Integration_test/Altera/src/param_gen.pl | 38 + .../{synthetic_sim/src => }/deafult_noc_param | 2 +- .../configurations/general/mesh_3x3_v2_ssa | 12 + mpsoc/Integration_test/synthetic_sim/run.sh | 1 - .../Integration_test/synthetic_sim/src/src.pl | 1037 ++++++++--------- mpsoc/rtl/src_noc/inout_ports.sv | 4 +- mpsoc/rtl/src_noc/input_ports.sv | 14 +- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 2 +- mpsoc/rtl/src_noc/noc_top.sv | 2 + mpsoc/rtl/src_noc/pronoc_pkg.sv | 4 +- mpsoc/rtl/src_noc/ss_allocator.sv | 62 +- 23 files changed, 798 insertions(+), 822 deletions(-) create mode 100644 mpsoc/Integration_test/Altera/configurations/line4_smart3 create mode 100644 mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa create mode 100644 mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_mcast_f create mode 100644 mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_xy_v2 create mode 100644 mpsoc/Integration_test/Altera/golden_ref/line4_smart3 rename mpsoc/Integration_test/Altera/{report_old => golden_ref/mesh_3x3_v2_ssa} (100%) create mode 100644 mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f create mode 100644 mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 delete mode 100644 mpsoc/Integration_test/Altera/report delete mode 100644 mpsoc/Integration_test/Altera/src/noc_localparam.v create mode 100644 mpsoc/Integration_test/Altera/src/param_gen.pl rename mpsoc/Integration_test/{synthetic_sim/src => }/deafult_noc_param (97%) create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa diff --git a/.gitignore b/.gitignore index dd70c5f..82889d0 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,7 @@ mpsoc/remove_cycle/__pycache__ mpsoc_work/ mpsoc/rtl/src_openpiton/nocs mpsoc/Integration_test/synthetic_sim/result_logs/* - +mpsoc/Integration_test/Altera/result_logs/* diff --git a/mpsoc/Integration_test/Altera/configurations/line4_smart3 b/mpsoc/Integration_test/Altera/configurations/line4_smart3 new file mode 100644 index 0000000..9242ffb --- /dev/null +++ b/mpsoc/Integration_test/Altera/configurations/line4_smart3 @@ -0,0 +1,16 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + TOPOLOGY=>"\"LINE\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "\"NO\"", + "SELF_LOOP_EN" => "\"YES\"", + "MCAST_ENDP_LIST" => "'b11", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa new file mode 100644 index 0000000..b29f1f8 --- /dev/null +++ b/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa @@ -0,0 +1,11 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "3", + "T2" => "3", + "SELF_LOOP_EN" => "\"YES\"", + "SSA_EN"=> "\"YES\"", + "LB" => 16, + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_mcast_f new file mode 100644 index 0000000..a90f35c --- /dev/null +++ b/mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_mcast_f @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_xy_v2 b/mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_xy_v2 new file mode 100644 index 0000000..b7eb7d1 --- /dev/null +++ b/mpsoc/Integration_test/Altera/configurations/mesh_4x4_2cycle_xy_v2 @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "DEBUG_EN" => "0", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Altera/golden_ref/line4_smart3 b/mpsoc/Integration_test/Altera/golden_ref/line4_smart3 new file mode 100644 index 0000000..1e475c9 --- /dev/null +++ b/mpsoc/Integration_test/Altera/golden_ref/line4_smart3 @@ -0,0 +1,41 @@ + , Fr_max +pronoc_output_files, 159.64 , Fmax = 159.64 Mhz + +-, Combinational ALUTs +pronoc_output_files, 1696 , 36100 ( 5 % ) ; + + + + +-, Dedicated logic registers +pronoc_output_files, 1426 , 36100 ( 4 % ) ; + + + + +-, Memory ALUTs +pronoc_output_files, 0 , 18050 ( 0 % ) ; + + + + +-, ALMs: partially or completely used +pronoc_output_files, 1435 , 18050 ( 8 % ) + + + + +-, Logic utilization +pronoc_output_files, 2460 , 36100 ( 7 % ) + + + + +-, M9K blocks +pronoc_output_files, 20 , 319 ( 6 % ) ; + + + + +-, Total block memory bits +pronoc_output_files, 5808 , 2939904 ( < 1 % ) ; diff --git a/mpsoc/Integration_test/Altera/report_old b/mpsoc/Integration_test/Altera/golden_ref/mesh_3x3_v2_ssa similarity index 100% rename from mpsoc/Integration_test/Altera/report_old rename to mpsoc/Integration_test/Altera/golden_ref/mesh_3x3_v2_ssa diff --git a/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f new file mode 100644 index 0000000..7c1fe19 --- /dev/null +++ b/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f @@ -0,0 +1,39 @@ + +-, Combinational ALUTs +pronoc_output_files, 18343 , 36100 ( 51 % ) ; + + + + +-, Dedicated logic registers +pronoc_output_files, 8913 , 36100 ( 25 % ) ; + + + + +-, Memory ALUTs +pronoc_output_files, 0 , 18050 ( 0 % ) ; + + + + +-, ALMs: partially or completely used +pronoc_output_files, 12617 , 18050 ( 70 % ) + + + + +-, Logic utilization +pronoc_output_files, 22303 , 36100 ( 62 % ) + + + + +-, M9K blocks +pronoc_output_files, 128 , 319 ( 40 % ) ; + + + + +-, Total block memory bits +pronoc_output_files, 33792 , 2939904 ( 1 % ) ; diff --git a/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 b/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 new file mode 100644 index 0000000..9d0213e --- /dev/null +++ b/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 @@ -0,0 +1,47 @@ +extract_results(/home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc_work/verify/quartus_pronoc,pronoc); +/home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc_work/verify/quartus_pronoc +***************** results ***************** + , Fr_max +pronoc_output_files, 146.35 , Fmax = 146.35 Mhz + + + + +-, Combinational ALUTs +pronoc_output_files, 15546 , 36100 ( 43 % ) ; + + + + +-, Dedicated logic registers +pronoc_output_files, 9732 , 36100 ( 27 % ) ; + + + + +-, Memory ALUTs +pronoc_output_files, 0 , 18050 ( 0 % ) ; + + + + +-, ALMs: partially or completely used +pronoc_output_files, 11348 , 18050 ( 63 % ) + + + + +-, Logic utilization +pronoc_output_files, 18852 , 36100 ( 52 % ) + + + + +-, M9K blocks +pronoc_output_files, 64 , 319 ( 20 % ) ; + + + + +-, Total block memory bits +pronoc_output_files, 17408 , 2939904 ( < 1 % ) ; diff --git a/mpsoc/Integration_test/Altera/report b/mpsoc/Integration_test/Altera/report deleted file mode 100644 index a09699d..0000000 --- a/mpsoc/Integration_test/Altera/report +++ /dev/null @@ -1,47 +0,0 @@ -extract_results(/home/alireza/work/git/hca_git/mpsoc_work/verify/quartus_pronoc,pronoc); -/home/alireza/work/git/hca_git/mpsoc_work/verify/quartus_pronoc -***************** results ***************** - , Fr_max -pronoc_output_files, 125.9 , Fmax = 125.9 Mhz - - - - --, Combinational ALUTs -pronoc_output_files, 12032 , 36100 ( 33 % ) ; - - - - --, Dedicated logic registers -pronoc_output_files, 9376 , 36100 ( 26 % ) ; - - - - --, Memory ALUTs -pronoc_output_files, 0 , 18050 ( 0 % ) ; - - - - --, ALMs: partially or completely used -pronoc_output_files, 9309 , 18050 ( 52 % ) - - - - --, Logic utilization -pronoc_output_files, 14767 , 36100 ( 41 % ) - - - - --, M9K blocks -pronoc_output_files, 33 , 319 ( 10 % ) ; - - - - --, Total block memory bits -pronoc_output_files, 16320 , 2939904 ( < 1 % ) ; diff --git a/mpsoc/Integration_test/Altera/run.sh b/mpsoc/Integration_test/Altera/run.sh index 15ac250..fcc51f0 100755 --- a/mpsoc/Integration_test/Altera/run.sh +++ b/mpsoc/Integration_test/Altera/run.sh @@ -3,127 +3,99 @@ SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) +conf="mesh_4x4_2cycle_mcast_f" +conf="line4_smart3" - - +conf_file="${SCRPT_DIR_PATH}/configurations/$conf" work="${PRONOC_WORK}/verify/quartus_pronoc" top="quartus_pronoc" - - - - - - - - +log_dir="${SCRPT_DIR_PATH}/result_logs" +log_file="${log_dir}/$conf" +golden_ref="${SCRPT_DIR_PATH}/golden_ref/$conf" copy_filelist () { - fname=$1 - local DIR="$(dirname "${fname}")" - - - echo $DIR - pwd - - - while read line; do - # reading each line - #echo $line + fname=$1 + local DIR="$(dirname "${fname}")" + echo $DIR + pwd + while read line; do + # reading each line + #echo $line cd $DIR - - if test -f "$DIR/$line"; then - echo "copy $DIR/$line " - cp "$DIR/$line" $PITON_ROOT/build/src_verilog/ - fi - line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces - if [[ $line == -F* ]] || [[ $line == -f* ]] ; then - line=${line:2} # Remove the first three chars (leaving 4..end) - line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces - echo $line - echo "got another file list $line" - copy_filelist "$DIR/$line" - fi - done < $fname + if test -f "$DIR/$line"; then + echo "copy $DIR/$line " + cp "$DIR/$line" $PITON_ROOT/build/src_verilog/ + fi + line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces + if [[ $line == -F* ]] || [[ $line == -f* ]] ; then + line=${line:2} # Remove the first three chars (leaving 4..end) + line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces + echo $line + echo "got another file list $line" + copy_filelist "$DIR/$line" + fi + done < $fname } - - - - make_qsf () { - fname=$1 - oname=$2 - local DIR="$(dirname "${fname}")" - - - echo $oname - - pwd - - - while read line; do - # reading each line - #echo $line + fname=$1 + oname=$2 + local DIR="$(dirname "${fname}")" + echo $oname + pwd + while read line; do + # reading each line + #echo $line cd $DIR - - - if test -f "$DIR/$line"; then - echo "set_global_assignment -name SYSTEMVERILOG_FILE $DIR/$line">>"$oname" - # "$DIR/$line" $PITON_ROOT/build/src_verilog/ - fi - line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces - if [[ $line == -F* ]] || [[ $line == -f* ]] ; then - line=${line:2} # Remove the first three chars (leaving 4..end) - line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces - #echo $line - echo "got another file list $line" - make_qsf "$DIR/$line" "$oname" - fi - - if [[ $line == +incdir+* ]] ; then - line=${line:8} # Remove the first three chars (leaving 4..end) - echo "set_global_assignment -name SEARCH_PATH $DIR/$line">>"$oname" - fi - - done < $fname + if test -f "$DIR/$line"; then + echo "set_global_assignment -name SYSTEMVERILOG_FILE $DIR/$line">>"$oname" + # "$DIR/$line" $PITON_ROOT/build/src_verilog/ + fi + line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces + if [[ $line == -F* ]] || [[ $line == -f* ]] ; then + line=${line:2} # Remove the first three chars (leaving 4..end) + line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//')" # remove only the leading white spaces + #echo $line + echo "got another file list $line" + make_qsf "$DIR/$line" "$oname" + fi + if [[ $line == +incdir+* ]] ; then + line=${line:8} # Remove the first three chars (leaving 4..end) + echo "set_global_assignment -name SEARCH_PATH $DIR/$line">>"$oname" + fi + done < $fname } compile () { - - mkdir -p $work - filename=$SCRPT_DIR_PATH/src/file_list.f - qsf_name="$work/pronoc.qsf" - cp -f $SCRPT_DIR_PATH/src/pronoc.qsf $qsf_name - - echo "set_global_assignment -name TOP_LEVEL_ENTITY $top">>$qsf_name - make_qsf $filename "$qsf_name" - - - - - if [[ -z "${Quartus_bin}" ]]; then - #"Some default value because Quartus_bin is undefined" - Quartus_bin="/home/alireza/intelFPGA_lite/18.1/quartus/bin" - else - Quartus_bin="${Quartus_bin}" - fi - - cd $work - $Quartus_bin/quartus_map --64bit pronoc --read_settings_files=on - $Quartus_bin/quartus_fit --64bit pronoc --read_settings_files=on - $Quartus_bin/quartus_asm --64bit pronoc --read_settings_files=on - $Quartus_bin/quartus_sta --64bit pronoc - + mkdir -p $work + filename=$SCRPT_DIR_PATH/src/file_list.f + qsf_name="$work/pronoc.qsf" + cp -f $SCRPT_DIR_PATH/src/pronoc.qsf $qsf_name + echo "set_global_assignment -name TOP_LEVEL_ENTITY $top">>$qsf_name + make_qsf $filename "$qsf_name" + if [[ -z "${Quartus_bin}" ]]; then + #"Some default value because Quartus_bin is undefined" + Quartus_bin="/home/alireza/intelFPGA_lite/18.1/quartus/bin" + else + Quartus_bin="${Quartus_bin}" + fi + cd $work + $Quartus_bin/quartus_map --64bit pronoc --read_settings_files=on + $Quartus_bin/quartus_fit --64bit pronoc --read_settings_files=on + $Quartus_bin/quartus_asm --64bit pronoc --read_settings_files=on + $Quartus_bin/quartus_sta --64bit pronoc } +perl ${SCRPT_DIR_PATH}/src/param_gen.pl $conf_file compile wait; -perl ${SCRPT_DIR_PATH}/src/extract.prl "$PRONOC_WORK/verify/quartus_pronoc" "pronoc" > report - - +mkdir -p $log_dir +perl ${SCRPT_DIR_PATH}/src/extract.prl "$PRONOC_WORK/verify/quartus_pronoc" "pronoc" > $log_file +meld "$golden_ref" "$log_file" & +rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v diff --git a/mpsoc/Integration_test/Altera/src/noc_localparam.v b/mpsoc/Integration_test/Altera/src/noc_localparam.v deleted file mode 100644 index 60d1db2..0000000 --- a/mpsoc/Integration_test/Altera/src/noc_localparam.v +++ /dev/null @@ -1,50 +0,0 @@ - -`ifdef NOC_LOCAL_PARAM - - - - -//NoC parameters - localparam TOPOLOGY="MESH"; - localparam T1=3; - localparam T2=3; - localparam T3=1; - localparam V=2; - localparam B=4; - localparam LB=16; - localparam Fpay=32; - localparam ROUTE_NAME="XY"; - localparam PCK_TYPE = "MULTI_FLIT"; //"SINGLE_FLIT"; - localparam MIN_PCK_SIZE=1; - localparam BYTE_EN=0; - localparam SSA_EN="YES"; - localparam CONGESTION_INDEX=3; - localparam ESCAP_VC_MASK=2'b01; - localparam VC_REALLOCATION_TYPE="NONATOMIC"; - localparam COMBINATION_TYPE="COMB_NONSPEC"; - localparam MUX_TYPE="BINARY"; - localparam C=0; - localparam DEBUG_EN=1; - localparam ADD_PIPREG_AFTER_CROSSBAR=1'b0; - localparam FIRST_ARBITER_EXT_P_EN=1; - localparam SWA_ARBITER_TYPE="RRA"; - localparam WEIGHTw=4; - localparam AVC_ATOMIC_EN=0; - localparam CVw=(C==0)? V : C * V; - localparam CLASS_SETTING={CVw{1'b1}}; - localparam SMART_MAX=0; - localparam SELF_LOOP_EN="YES"; - localparam CAST_TYPE = "UNICAST"; - localparam MCAST_ENDP_LIST = 'b11110011; - //localparam MCAST_PRTLw=6; - - - - //simulation parameter - //localparam MAX_RATIO = 1000; - localparam MAX_PCK_NUM = 1000000000; - localparam MAX_PCK_SIZ = 16383; - localparam MAX_SIM_CLKs= 1000000000; - localparam TIMSTMP_FIFO_NUM = 16; - -`endif diff --git a/mpsoc/Integration_test/Altera/src/param_gen.pl b/mpsoc/Integration_test/Altera/src/param_gen.pl new file mode 100644 index 0000000..a97679f --- /dev/null +++ b/mpsoc/Integration_test/Altera/src/param_gen.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl -w +package ProNOC; +use strict; +use warnings; +use File::Basename; + + +#add home dir in perl 5.6 +use FindBin; +use lib $FindBin::Bin; +use constant::boolean; + +use File::Path qw(make_path); + + +use strict; +use warnings; + +use base 'Class::Accessor::Fast'; + + +my $script_path = dirname(__FILE__); +require "$script_path/../../synthetic_sim/src/src.pl"; + +my $conf_file=$ARGV[0]; + + +sub create_noc_param_vv { + my ($conf_file)=@_; + my $o = do $conf_file; + die "Could not parse $conf_file: $@" if $@; + die "Could not read $conf_file: $!" unless defined $o; + my $param = $o->{'noc_param'}; + my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); + save_file("$script_path/noc_localparam.v",$param_v); +} + +create_noc_param_vv ($conf_file); diff --git a/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param b/mpsoc/Integration_test/deafult_noc_param similarity index 97% rename from mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param rename to mpsoc/Integration_test/deafult_noc_param index 2ecce91..b024323 100644 --- a/mpsoc/Integration_test/synthetic_sim/src/deafult_noc_param +++ b/mpsoc/Integration_test/deafult_noc_param @@ -39,7 +39,7 @@ $model = bless({ "HETERO_VC"=> "0", "MAX_ROUTER"=>"1", "MAX_PORT"=>"1", - "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{0}", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{'{0}}", }, 'parameters_order' => { diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa new file mode 100644 index 0000000..3186dc8 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa @@ -0,0 +1,12 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "3", + "T2" => "3", + "SELF_LOOP_EN" => "\"YES\"", + "SSA_EN"=> "\"YES\"", + "LB" => 16, + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", + "Fpay" => "64", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/run.sh b/mpsoc/Integration_test/synthetic_sim/run.sh index d9b773b..5ce80a7 100755 --- a/mpsoc/Integration_test/synthetic_sim/run.sh +++ b/mpsoc/Integration_test/synthetic_sim/run.sh @@ -240,7 +240,6 @@ $my_ssh $my_server "cd ${SERVER_ROOT_DIR}/mpsoc/Integration_test/synthetic_sim/ else cd $SCRPT_DIR_PATH/src; bash server_run.sh $args - fi diff --git a/mpsoc/Integration_test/synthetic_sim/src/src.pl b/mpsoc/Integration_test/synthetic_sim/src/src.pl index 7add35f..07727d4 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/src.pl +++ b/mpsoc/Integration_test/synthetic_sim/src/src.pl @@ -1,13 +1,16 @@ #!/usr/bin/perl -w -use lib "../perl_lib"; +use strict; +use warnings; +use lib "../perl_lib"; use List::MoreUtils qw(uniq); use Proc::Background; use File::Path qw( rmtree ); use File::Path qw( make_path ); use Cwd qw(realpath); use Cwd 'abs_path'; +use File::Copy; my $script_path = dirname(__FILE__); my $dirname = realpath("$script_path/.."); @@ -18,48 +21,36 @@ print "confs_dir: $confs_dir\n"; print "Root: $root\n"; - my $rtl_dir = "$ENV{PRONOC_WORK}/verify/rtl"; my $work = "$ENV{PRONOC_WORK}/verify/work"; my $verify = "$ENV{PRONOC_WORK}/verify"; - - my $src_verilator = "$root/src_verilator"; my $src_c = "$root/src_c"; my $src = "$script_path"; - +my $noc_default_param_file= "$root/Integration_test/deafult_noc_param"; #require "$root/perl_gui/lib/perl/common.pl"; require "$root/perl_gui/lib/perl/topology.pl"; -use strict; -use warnings; - my $pp; - $pp= do "$src/deafult_noc_param"; - die "Error reading: $@" if $@; - - my $param = $pp->{'noc_param'}; - my %default_noc_param=%{$param}; - my @params=object_get_attribute_order($pp,'noc_param'); +$pp= do $noc_default_param_file; +die "Error reading: $@" if $@; +my $param = $pp->{'noc_param'}; +my %default_noc_param=%{$param}; +my @params=object_get_attribute_order($pp,'noc_param'); #read default param - - sub recompile_synful { # Define the command to recompile Synful my $cmd = "cd $src_c/synfull/traffic-generator/src && make; wait;"; - print "******************* Compile Synful *******************\n"; print "Executing command: $cmd\n"; - # Run the command and capture its exit status my $output = `$cmd 2>&1`; # Capture both stdout and stderr my $exit_status = $? >> 8; # Extract exit code - # Check for errors if ($exit_status != 0) { die "Error: Compilation of Synful failed with exit code $exit_status. Output:\n$output\n"; @@ -69,149 +60,128 @@ sub recompile_synful { } sub gen_noc_param_h{ - my $mpsoc=shift; - my $param_h="\n\n//NoC parameters\n"; - - my $topology = $mpsoc->object_get_attribute('noc_param','TOPOLOGY'); - $topology =~ s/"//g; - $param_h.="\t#define IS_${topology}\n"; - - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); - - my @params=$mpsoc->object_get_attribute_order('noc_param'); - my $custom_topology = $mpsoc->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); - foreach my $p (@params){ - my $val=$mpsoc->object_get_attribute('noc_param',$p); - next if($p eq "CUSTOM_TOPOLOGY_NAME"); - next if($p eq "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"); - $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); - if($p eq "MCAST_ENDP_LIST" || $p eq "ESCAP_VC_MASK"){ - $val="$NE".$val if($p eq 'MCAST_ENDP_LIST'); - $val =~ s/\'/\\\'/g; - $val="\"$val\""; - } - $param_h=$param_h."\t#define $p\t$val\n"; - - #print "$p:$val\n"; - - } - - - my $v=$mpsoc->object_get_attribute('noc_param',"V")-1; - my $escape=$mpsoc->object_get_attribute('noc_param',"ESCAP_VC_MASK"); - if (! defined $escape){ - #add_text_to_string (\$param_h,"\tlocalparam [$v :0] ESCAP_VC_MASK=1;\n"); - #add_text_to_string (\$pass_param,".ESCAP_VC_MASK(ESCAP_VC_MASK),\n"); - } - #add_text_to_string (\$param_h," \tlocalparam CVw=(C==0)? V : C * V;\n"); - #add_text_to_string (\$pass_param,".CVw(CVw)\n"); - - #remove 'b and 'h - #$param_h =~ s/\d\'b/ /g; - #$param_h =~ s/\'h/ /g; - - - return $param_h; + my $mpsoc=shift; + my $param_h="\n\n//NoC parameters\n"; + my $topology = $mpsoc->object_get_attribute('noc_param','TOPOLOGY'); + $topology =~ s/"//g; + $param_h.="\t#define IS_${topology}\n"; + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc); + my @params=$mpsoc->object_get_attribute_order('noc_param'); + my $custom_topology = $mpsoc->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); + foreach my $p (@params){ + my $val=$mpsoc->object_get_attribute('noc_param',$p); + next if($p eq "CUSTOM_TOPOLOGY_NAME"); + next if($p eq "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"); + $val=$custom_topology if($p eq "TOPOLOGY" && $val eq "\"CUSTOM\""); + if($p eq "MCAST_ENDP_LIST" || $p eq "ESCAP_VC_MASK"){ + $val="$NE".$val if($p eq 'MCAST_ENDP_LIST'); + $val =~ s/\'/\\\'/g; + $val="\"$val\""; + } + $param_h=$param_h."\t#define $p\t$val\n"; + + #print "$p:$val\n"; + + } + my $v=$mpsoc->object_get_attribute('noc_param',"V")-1; + my $escape=$mpsoc->object_get_attribute('noc_param',"ESCAP_VC_MASK"); + if (! defined $escape){ + #add_text_to_string (\$param_h,"\tlocalparam [$v :0] ESCAP_VC_MASK=1;\n"); + #add_text_to_string (\$pass_param,".ESCAP_VC_MASK(ESCAP_VC_MASK),\n"); + } + #add_text_to_string (\$param_h," \tlocalparam CVw=(C==0)? V : C * V;\n"); + #add_text_to_string (\$pass_param,".CVw(CVw)\n"); + + #remove 'b and 'h + #$param_h =~ s/\d\'b/ /g; + #$param_h =~ s/\'h/ /g; + return $param_h; } sub gen_sim_parameter_h { - my ($param_h,$includ_h,$ne,$nr,$router_p,$fifow)=@_; - - $param_h =~ s/\d\'b/ /g; - my $text= " + my ($param_h,$includ_h,$ne,$nr,$router_p,$fifow)=@_; + $param_h =~ s/\d\'b/ /g; + my $text= " #ifndef INCLUDE_PARAM - #define INCLUDE_PARAM \n \n - - $param_h - - #define NE $ne - #define NR $nr - #define ROUTER_P_NUM $router_p - - extern Vtraffic *traffic[NE]; - extern Vpck_inj *pck_inj[NE]; - extern int reset,clk; - - //simulation parameter - #define MAX_RATIO 1000 - #define AVG_LATENCY_METRIC \"HEAD_2_TAIL\" - #define TIMSTMP_FIFO_NUM $fifow - - $includ_h -\n \n \#endif" ; - return $text; -} + #define INCLUDE_PARAM \n \n + $param_h + + #define NE $ne + #define NR $nr + #define ROUTER_P_NUM $router_p + + extern Vtraffic *traffic[NE]; + extern Vpck_inj *pck_inj[NE]; + extern int reset,clk; + + //simulation parameter + #define MAX_RATIO 1000 + #define AVG_LATENCY_METRIC \"HEAD_2_TAIL\" + #define TIMSTMP_FIFO_NUM $fifow + + $includ_h +\n \n \#endif" ; + return $text; +} sub extract_and_update_noc_sim_statistic { - my ($stdout)=@_; - my $avg_latency =capture_number_after("average packet latency =",$stdout); - my $avg_flit_latency =capture_number_after("average flit latency =",$stdout); - my $sd_latency =capture_number_after("standard_dev =",$stdout); - my $avg_thput =capture_number_after("Avg throughput is:",$stdout); - my $total_time =capture_number_after("simulation clock cycles:",$stdout); - my $latency_perhop = capture_number_after("average latency per hop =",$stdout); - my %packet_rsvd_per_core = capture_cores_data("total number of received packets:",$stdout); - my %worst_rsvd_delay_per_core = capture_cores_data('worst-case-delay of received packets \(clks\):',$stdout); - my %packet_sent_per_core = capture_cores_data("total number of sent packets:",$stdout); - my %worst_sent_delay_per_core = capture_cores_data('worst-case-delay of sent packets \(clks\):',$stdout); - - + my ($stdout)=@_; + my $avg_latency =capture_number_after("average packet latency =",$stdout); + my $avg_flit_latency =capture_number_after("average flit latency =",$stdout); + my $sd_latency =capture_number_after("standard_dev =",$stdout); + my $avg_thput =capture_number_after("Avg throughput is:",$stdout); + my $total_time =capture_number_after("simulation clock cycles:",$stdout); + my $latency_perhop = capture_number_after("average latency per hop =",$stdout); + my %packet_rsvd_per_core = capture_cores_data("total number of received packets:",$stdout); + my %worst_rsvd_delay_per_core = capture_cores_data('worst-case-delay of received packets \(clks\):',$stdout); + my %packet_sent_per_core = capture_cores_data("total number of sent packets:",$stdout); + my %worst_sent_delay_per_core = capture_cores_data('worst-case-delay of sent packets \(clks\):',$stdout); } sub get_model_parameter { - my $model =shift; - my $o; - $o= do $model; - my %new_param=%{$o}; + my $model =shift; + my $o; + $o= do $model; + my %new_param=%{$o}; die "Error reading: $@" if $@; - my %temp; - foreach my $p (@params){ - $temp{$p} = $default_noc_param{$p}; - } - foreach my $p (sort keys %new_param){ - $temp{$p} = $new_param{$p}; - } - return %temp; + my %temp; + foreach my $p (@params){ + $temp{$p} = $default_noc_param{$p}; + } + foreach my $p (sort keys %new_param){ + $temp{$p} = $new_param{$p}; + } + return %temp; } sub gen_noc_localparam_v { - my ($m,$ref) = @_; - my %model = %{$ref}; - my %temp; - + my ($m,$ref) = @_; + my %model = %{$ref}; + my %temp; - foreach my $p (@params){ - $temp{$p} = $default_noc_param{$p}; + foreach my $p (@params){ + $temp{$p} = $default_noc_param{$p}; $m->{noc_param}{$p}=$default_noc_param{$p}; - } - foreach my $p (sort keys %model){ - $temp{$p} = $model{$p}; - $m->{noc_param}{$p}=$model{$p}; - } - - object_add_attribute_order($m,'noc_param',@params); - - my $param_v="`ifdef NOC_LOCAL_PARAM \n"; - foreach my $p (@params){ - $param_v.="localparam $p = $temp{$p};\n"; - } - $param_v.="`endif\n"; - - my ($nr,$ne,$router_p,$ref_tops,$includ_h) = get_noc_verilator_top_modules_info($m); - my %tops = %{$ref_tops}; - $tops{Vtraffic} = "--top-module traffic_gen_top"; - $tops{Vpck_inj} = "--top-module packet_injector_verilator"; - - - - - my $param_h=gen_noc_param_h($m); - $includ_h = gen_sim_parameter_h($param_h,$includ_h,$ne,$nr,$router_p,'16'); - - return ($param_v,$includ_h,\%tops); - + } + foreach my $p (sort keys %model){ + $temp{$p} = $model{$p}; + $m->{noc_param}{$p}=$model{$p}; + } + object_add_attribute_order($m,'noc_param',@params); + my $param_v="`ifdef NOC_LOCAL_PARAM \n"; + foreach my $p (@params){ + $param_v.="localparam $p = $temp{$p};\n"; + } + $param_v.="`endif\n"; + my ($nr,$ne,$router_p,$ref_tops,$includ_h) = get_noc_verilator_top_modules_info($m); + my %tops = %{$ref_tops}; + $tops{Vtraffic} = "--top-module traffic_gen_top"; + $tops{Vpck_inj} = "--top-module packet_injector_verilator"; + my $param_h=gen_noc_param_h($m); + $includ_h = gen_sim_parameter_h($param_h,$includ_h,$ne,$nr,$router_p,'16'); + return ($param_v,$includ_h,\%tops); } @@ -226,13 +196,11 @@ sub copy_src_files { print "Creating working directory: $rtl_dir\n"; make_path($rtl_dir, { mode => 0700 }) or die "Error: Cannot create directory $rtl_dir: $!\n"; $rtl_dir=realpath ($rtl_dir); - # Define source directories my %src_dirs = ( "$root/rtl/src_noc" => "$rtl_dir/src_noc", "$root/rtl/src_topology" => "$rtl_dir/src_topology", ); - # Copy source directories for my $src (keys %src_dirs) { my $dest = $src_dirs{$src}; @@ -240,503 +208,420 @@ sub copy_src_files { dircopy($src, $dest) or die "Error: Cannot copy $src to $dest: $!\n"; } } - # Remove specific file if it exists in the destination my $noc_localparam_file = "$rtl_dir/src_noc/noc_localparam.v"; unlink $noc_localparam_file if -e $noc_localparam_file; - # Copy individual Verilog files from root RTL directory for my $file (glob "$root/rtl/*.v") { copy($file, $rtl_dir) or die "Error: Cannot copy $file to $rtl_dir: $!\n"; } - print "Source files copied successfully.\n"; } - - - sub gen_file_list{ - my $path=shift; - my $f="+incdir+$rtl_dir/ + my $path=shift; + my $f="+incdir+$rtl_dir/ +incdir+$rtl_dir/src_noc/ +incdir+$path "; - my @files = File::Find::Rule->file() - ->name( '*.v','*.V','*.sv' ) - ->in( "$rtl_dir" ); - - #make sure source files have key word 'module' - my @sources; - foreach my $p (@files){ - push (@sources,$p) if(check_file_has_string($p,'endpackage')); - } - foreach my $p (@files){ - push (@sources,$p) if(check_file_has_string($p,'module')); - } - my $files = join ("\n",@sources); - $f.=$files; - - - open(FILE, ">$path/file_list.f") || die "Can not open: $!"; - print FILE $f; - close FILE; + my @files = File::Find::Rule->file() + ->name( '*.v','*.V','*.sv' ) + ->in( "$rtl_dir" ); + #make sure source files have key word 'module' + my @sources; + foreach my $p (@files){ + push (@sources,$p) if(check_file_has_string($p,'endpackage')); + } + foreach my $p (@files){ + push (@sources,$p) if(check_file_has_string($p,'module')); + } + my $files = join ("\n",@sources); + $f.=$files; + open(FILE, ">$path/file_list.f") || die "Can not open: $!"; + print FILE $f; + close FILE; } sub gen_verilator_sh{ - my ($ref,$file)=@_; - my %tops = %{$ref}; - my $make_lib=""; + my ($ref,$file)=@_; + my %tops = %{$ref}; + my $make_lib=""; my $jobs=0; - my $cmd= '#!/bin/bash - SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) - SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) - - cmn="-O3 -CFLAGS -O3" - currentver=$(verilator --version | head -n1 | cut -d" " -f2) - requiredver="4.0.0" - if [ "$(printf \'%s\n\' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then + my $cmd= '#!/bin/bash + SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) + SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) + + cmn="-O3 -CFLAGS -O3" + currentver=$(verilator --version | head -n1 | cut -d" " -f2) + requiredver="4.0.0" + if [ "$(printf \'%s\n\' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then echo "Verilator vesrion Greater than or equal to ${requiredver}, compile with -Wno-TIMESCALEMOD flag" - cmn=" $cmn -Wno-TIMESCALEMOD"; - else + cmn=" $cmn -Wno-TIMESCALEMOD"; + else echo "Verilator vesrion is Less than ${requiredver}" - fi + fi '; - - foreach my $top (sort keys %tops) { - $cmd.= "verilator -DNO_HETRO_IVC=1 -f \$SCRPT_DIR_PATH/file_list.f --cc $tops{$top} --prefix \"$top\" \$cmn & \n"; - } - $cmd.="wait\n"; - foreach my $top (sort keys %tops) { - - $cmd.=" - if ! [ -f \$SCRPT_DIR_PATH/obj_dir/$top.cpp ]; then - echo \"Failed to generate: \$SCRPT_DIR_PATH/obj_dir/$top.cpp \" - exit 1 - fi\n"; - $make_lib.="make lib$jobs &\n"; - $jobs++; - } - - - $cmd.=" + foreach my $top (sort keys %tops) { + $cmd.= "verilator -DNO_HETRO_IVC=1 -f \$SCRPT_DIR_PATH/file_list.f --cc $tops{$top} --prefix \"$top\" \$cmn & \n"; + } + $cmd.="wait\n"; + foreach my $top (sort keys %tops) { + + $cmd.=" + if ! [ -f \$SCRPT_DIR_PATH/obj_dir/$top.cpp ]; then + echo \"Failed to generate: \$SCRPT_DIR_PATH/obj_dir/$top.cpp \" + exit 1 + fi\n"; + $make_lib.="make lib$jobs &\n"; + $jobs++; + } + $cmd.=" cd \$SCRPT_DIR_PATH/obj_dir/ $make_lib wait make sim "; - save_file("$file",$cmd); - + save_file("$file",$cmd); } sub get_model_names { - my ($mref,$inref) = @_; - my @models = @{$mref}; - my ($paralel_run,$MIN,$MAX,$STEP,$model_dir)=@{$inref}; - my $full_path; - $full_path = "$model_dir" if (-d "$model_dir"); - $full_path = "$confs_dir/$model_dir" if (-d "$confs_dir/$model_dir"); - if (!defined $full_path){ - die "Error the model directory $model_dir or $confs_dir/$model_dir is not found\n"; - } - my @m; - if(scalar @models == 0){ - @m = glob("$full_path/*"); - return @m; - } - foreach my $p (@models) { - push (@m,"$full_path/$p"); - } - return @m; + my ($mref,$inref) = @_; + my @models = @{$mref}; + my ($paralel_run,$MIN,$MAX,$STEP,$model_dir)=@{$inref}; + my $full_path; + $full_path = "$model_dir" if (-d "$model_dir"); + $full_path = "$confs_dir/$model_dir" if (-d "$confs_dir/$model_dir"); + if (!defined $full_path){ + die "Error the model directory $model_dir or $confs_dir/$model_dir is not found\n"; + } + my @m; + if(scalar @models == 0){ + @m = glob("$full_path/*"); + return @m; + } + foreach my $p (@models) { + push (@m,"$full_path/$p"); + } + return @m; } - sub check_models_are_exsited { - my ($mref, $inref) = @_; - my @models = get_model_names(@_); - foreach my $m (@models){ - unless (-f $m ){ - die "Error: no such file $m"; - } - } + my ($mref, $inref) = @_; + my @models = get_model_names(@_); + foreach my $m (@models){ + unless (-f $m ){ + die "Error: no such file $m"; + } + } } sub gen_models { - my ($mref, $inref) = @_; - my @models = get_model_names(@_); - + my ($mref, $inref) = @_; + my @models = get_model_names(@_); mkdir("$work", 0700); $work=realpath($work); - - foreach my $m (@models){ - print "$m\n"; - unless (-f $m ){ - die "Error: no such file $m"; - } - #make noc localparam - my $o; - $o= do $m; + foreach my $m (@models){ + print "$m\n"; + unless (-f $m ){ + die "Error: no such file $m"; + } + #make noc localparam + my $o; + $o= do $m; die "Error reading: $@" if $@; - my $param = $o->{'noc_param'}; - my ($fname,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); - - - my $name = $fname; - my $make =$o->{'makefile'}; - - - my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); - - mkdir("$work/$name", 0700); - rmtree("$work/$name/obj_dir"); + my $param = $o->{'noc_param'}; + my ($fname,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); + my $name = $fname; + my $make =$o->{'makefile'}; + my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); + mkdir("$work/$name", 0700); + rmtree("$work/$name/obj_dir"); mkdir("$work/$name/obj_dir", 0700); - save_file("$work/$name/noc_localparam.v",$param_v); - - #generate file list - gen_file_list("$work/$name"); - gen_verilator_sh($tops,"$work/$name/verilator.sh"); - - #copy C files - my @files = File::Find::Rule->file() - ->name( '*.h' ) - ->in( "$src_verilator" ); - foreach my $p (@files){ - copy $p, "$work/$name/obj_dir/"; - } - copy "$src_verilator/simulator.cpp", "$work/$name/obj_dir/testbench.cpp"; - - #copy nettrace & synful - dircopy("$src_c/netrace-1.0","$work/$name/obj_dir/netrace-1.0"); - dircopy("$src_c/synfull","$work/$name/obj_dir/synful"); - - #generate make file - gen_verilator_makefile($tops,"$work/$name/obj_dir/Makefile"); - #generate param.h file - - - save_file("$work/$name/obj_dir/parameter.h",$include_h); - - - } - + save_file("$work/$name/noc_localparam.v",$param_v); + + #generate file list + gen_file_list("$work/$name"); + gen_verilator_sh($tops,"$work/$name/verilator.sh"); + #copy C files + my @files = File::Find::Rule->file() + ->name( '*.h' ) + ->in( "$src_verilator" ); + foreach my $p (@files){ + copy $p, "$work/$name/obj_dir/"; + } + copy "$src_verilator/simulator.cpp", "$work/$name/obj_dir/testbench.cpp"; + #copy nettrace & synful + dircopy("$src_c/netrace-1.0","$work/$name/obj_dir/netrace-1.0"); + dircopy("$src_c/synfull","$work/$name/obj_dir/synful"); + #generate make file + gen_verilator_makefile($tops,"$work/$name/obj_dir/Makefile"); + #generate param.h file + save_file("$work/$name/obj_dir/parameter.h",$include_h); + } } - - - - - sub compile_models{ - my($self,$inref,$mref)=@_; + my($self,$inref,$mref)=@_; my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; - - - my @models = get_model_names($mref,$inref); - - #generate compile command - my $i=0; - my $cmd; - foreach my $m (@models){ - my ($fname,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); - $cmd.=" cd $work/$fname; bash verilator.sh > $work/$fname/out.log 2>&1 &\n"; - $i++; - $cmd.="wait\n" if(($i % $paralel_run)==0) ; - } - $cmd.="wait\n" if(($i % $paralel_run)!=0) ; - #run command in terminal - print "*******************compile models******************\n$cmd\n"; - my $proc1 = Proc::Background->new($cmd); - $proc1->alive; - $proc1->wait; - $proc1->die; - + my @models = get_model_names($mref,$inref); + #generate compile command + my $i=0; + my $cmd; + foreach my $m (@models){ + my ($fname,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); + $cmd.=" cd $work/$fname; bash verilator.sh > $work/$fname/out.log 2>&1 &\n"; + $i++; + $cmd.="wait\n" if(($i % $paralel_run)==0) ; + } + $cmd.="wait\n" if(($i % $paralel_run)!=0) ; + #run command in terminal + print "*******************compile models******************\n$cmd\n"; + my $proc1 = Proc::Background->new($cmd); + $proc1->alive; + $proc1->wait; + $proc1->die; } + sub check_compilation_log { - my ($name,$ref,$inref,$log_file) = @_; + my ($name,$ref,$inref,$log_file) = @_; my @log_report_match =@{$ref}; - my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; - my $logfile = "$work/$name/out.log"; - - my @found; - foreach my $m (@log_report_match){ - open my $INPUT, '<', $logfile; - push(@found , grep ( /$m/, <$INPUT>)) ; - close($INPUT); - } - - foreach my $line (@found) { - append_text_to_file($log_file,"\t $line\n"); + my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; + my $logfile = "$work/$name/out.log"; + my @found; + foreach my $m (@log_report_match){ + open my $INPUT, '<', $logfile; + push(@found , grep ( /$m/, <$INPUT>)) ; + close($INPUT); + } + foreach my $line (@found) { + append_text_to_file($log_file,"\t $line\n"); } } - - - - sub check_compilation { - my ($self,$ref1,$inref,$mref,$log_file)=@_; - - my @models = get_model_names($mref,$inref); - - foreach my $m (@models){ - my ($name,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); - append_text_to_file($log_file,"****************************$name : Compile *******************************:\n"); - #check if testbench is generated successfully - if(-f "$work/$name/obj_dir/testbench"){ - append_text_to_file($log_file,"\t model is generated successfully.\n"); - check_compilation_log($name,$ref1,$inref,$log_file); - - }else{ - append_text_to_file($log_file,"\t model generation is FAILED.\n"); - check_compilation_log($name,$ref1,$inref,$log_file); - } - - } + my ($self,$ref1,$inref,$mref,$log_file)=@_; + my @models = get_model_names($mref,$inref); + foreach my $m (@models){ + my ($name,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); + append_text_to_file($log_file,"****************************$name : Compile *******************************:\n"); + #check if testbench is generated successfully + if(-f "$work/$name/obj_dir/testbench"){ + append_text_to_file($log_file,"\t model is generated successfully.\n"); + check_compilation_log($name,$ref1,$inref,$log_file); + }else{ + append_text_to_file($log_file,"\t model generation is FAILED.\n"); + check_compilation_log($name,$ref1,$inref,$log_file); + } + } } - sub run_all_models { - my ($self,$inref,$mref,$log_file) =@_; + my ($self,$inref,$mref,$log_file) =@_; my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; - my @models = get_model_names($mref,$inref); + my @models = get_model_names($mref,$inref); + foreach my $m (@models){ + run_traffic ($self,$m,'random',$inref,$log_file); + } foreach my $m (@models){ - run_traffic ($self,$m,'random',$inref,$log_file); - } - foreach my $m (@models){ - run_traffic ($self,$m,'transposed 1',$inref,$log_file); - } + run_traffic ($self,$m,'transposed 1',$inref,$log_file); + } } - - sub run_traffic { - my ($self,$model,$traffic,$inref,$log_file)=@_; - my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; - my ($name,$fpath,$fsuffix) = fileparse("$model",qr"\..[^.]*$"); - - my %param = get_model_parameter($model); - my $min_pck = $param{'MIN_PCK_SIZE'}; - - append_text_to_file($log_file,"****************************$name : $traffic traffic *******************************:\n"); - unless (-f "$work/$name/obj_dir/testbench"){ - append_text_to_file($log_file,"\t Failed. Simulation model is not avaialable\n"); - return; - } - - - - my $file_name="${traffic}_results"; + my ($self,$model,$traffic,$inref,$log_file)=@_; + my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; + my ($name,$fpath,$fsuffix) = fileparse("$model",qr"\..[^.]*$"); + my %param = get_model_parameter($model); + my $min_pck = $param{'MIN_PCK_SIZE'}; + append_text_to_file($log_file,"****************************$name\t: $traffic traffic *******************************:\n"); + unless (-f "$work/$name/obj_dir/testbench"){ + append_text_to_file($log_file,"\t Failed. Simulation model is not avaialable\n"); + return; + } + my $file_name="${traffic}_results"; $file_name =~ s/\s+//g; - - mkdir("$work/$name/$file_name/", 0700); - - my $i=0; - my $cmd; - - - for (my $inject=$MIN; $inject<=$MAX; $inject+=$STEP){ - $cmd.="$work/$name/obj_dir/testbench -t \"$traffic\" -m \"R,$min_pck,10\" -n 20000 -c 10000 -i $inject -p \"100,0,0,0,0\" > $work/$name/$file_name/sim$inject 2>&1 &\n"; - $i++; - $cmd.="wait\n" if(($i % $paralel_run)==0) ; - } - $cmd.="wait\n" if(($i % $paralel_run)!=0) ; - #run command in terminal - print "*******************Run simulation for $name******************\n$cmd\n"; - my $proc1 = Proc::Background->new($cmd); - $proc1->alive; - $proc1->wait; - $proc1->die; - - check_sim_results($self,$name,$traffic,$inref,$log_file); - + mkdir("$work/$name/$file_name/", 0700); + my $i=0; + my $cmd; + for (my $inject=$MIN; $inject<=$MAX; $inject+=$STEP){ + $cmd.="$work/$name/obj_dir/testbench -t \"$traffic\" -m \"R,$min_pck,10\" -n 20000 -c 10000 -i $inject -p \"100,0,0,0,0\" > $work/$name/$file_name/sim$inject 2>&1 &\n"; + $i++; + $cmd.="wait\n" if(($i % $paralel_run)==0) ; + } + $cmd.="wait\n" if(($i % $paralel_run)!=0) ; + #run command in terminal + print "*******************Run simulation for $name******************\n$cmd\n"; + my $proc1 = Proc::Background->new($cmd); + $proc1->alive; + $proc1->wait; + $proc1->die; + check_sim_results($self,$name,$traffic,$inref,$log_file); } - sub extract_result { - my ($self,$file,$filed)=@_; - - my @r = unix_grep($file,$filed); + my ($self,$file,$filed)=@_; + my @r = unix_grep($file,$filed); my $string = $r[0]; $string =~ s/[^0-9.]+//g; - return $string; - + return $string; } sub get_zero_load_and_saturation{ - my ($self,$name,$traffic,$path)=@_; - my %results; - my $ref = $self->{'name'}{"$name"}{'traffic'}{$traffic}{"packet_latency"}; - return if !defined $ref; - %results = %{$ref}; - - my $zero_latency=9999999; + my ($self,$name,$traffic,$path)=@_; + my %results; + my $ref = $self->{'name'}{"$name"}{'traffic'}{$traffic}{"packet_latency"}; + return if !defined $ref; + %results = %{$ref}; + my $zero_latency=9999999; my $saturat_inject=100; my $zero_inject; my $saturat_latency='-'; - - my $txt = "#name:$name\n"; - - foreach my $inj (sort {$a <=> $b} keys %results){ - $txt.="$inj $results{$inj}\n"; - if ($zero_latency > $results{$inj}) { - $zero_latency = $results{$inj}; - $zero_inject = $inj; - } - } - # assum saturation happens when the latency is 5 times of zero load - foreach my $inj (sort {$a <=> $b} keys %results){ - if($results{$inj} >= 5 * $zero_latency ) { - if($saturat_inject > $inj){ - $saturat_inject =$inj; - $saturat_latency=$results{$inj}; - } - } - } - $txt.="\n"; - save_file("$path/packet_latency.sv",$txt); - - - return ($zero_inject,$zero_latency, $saturat_inject,$saturat_latency); + my $txt = "#name:$name\n"; + foreach my $inj (sort {$a <=> $b} keys %results){ + $txt.="$inj $results{$inj}\n"; + if ($zero_latency > $results{$inj}) { + $zero_latency = $results{$inj}; + $zero_inject = $inj; + } + } + # assum saturation happens when the latency is 5 times of zero load + foreach my $inj (sort {$a <=> $b} keys %results){ + if($results{$inj} >= 5 * $zero_latency ) { + if($saturat_inject > $inj){ + $saturat_inject =$inj; + $saturat_latency=$results{$inj}; + } + } + } + $txt.="\n"; + save_file("$path/packet_latency.sv",$txt); + return ($zero_inject,$zero_latency, $saturat_inject,$saturat_latency); } - - - sub check_sim_results{ - my ($self,$name,$traffic,$inref,$log_file)=@_; + my ($self,$name,$traffic,$inref,$log_file)=@_; my ($paralel_run,$MIN,$MAX,$STEP) = @{$inref}; my $file_name="${traffic}_results"; $file_name =~ s/\s+//g; - my $results_path = "$work/$name/$file_name"; - - #my @results = glob("$results_path/*"); - #check for error - - for (my $inject=$MIN; $inject<=$MAX; $inject+=$STEP){ - my $file = "$results_path/sim$inject"; - - my @errors = unix_grep("$file","ERROR:"); - if (scalar @errors ){ - append_text_to_file($log_file,"\t Error in running simulation:\n @errors \n"); - $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="Failed"; - $self->{'name'}{"$name"}{'traffic'}{$traffic}{'message'}="@errors"; - return; - } - my @r = unix_grep($file,"\ttotal,"); - my $string = $r[0]; - my @fileds=split(',',$string); - my $val=$fileds[11]; - $val =~ s/[^0-9.]+//g; - # my $val = extract_result($self,$file,"average packet latency"); - if(length $val ==0){ - $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="Failed"; - $self->{'name'}{"$name"}{'traffic'}{$traffic}{'message'}="The average packet latency is undefined for $inject"; - return; - } - $self->{'name'}{"$name"}{'traffic'}{$traffic}{"packet_latency"}{$inject}="$val"; - - } - my ($z,$zl, $s,$sl) = get_zero_load_and_saturation ($self,$name,$traffic,$results_path); - print "($z,$zl, $s,$sl)\n"; - - #save results in a text file - - - - append_text_to_file($log_file,"\t Passed: zero load ($z,$zl) saturation ($s,$sl)\n"); - $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="passed"; + my $results_path = "$work/$name/$file_name"; + #my @results = glob("$results_path/*"); + #check for error + for (my $inject=$MIN; $inject<=$MAX; $inject+=$STEP){ + my $file = "$results_path/sim$inject"; + my @errors = unix_grep("$file","ERROR:"); + if (scalar @errors ){ + append_text_to_file($log_file,"\t Error in running simulation:\n @errors \n"); + $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="Failed"; + $self->{'name'}{"$name"}{'traffic'}{$traffic}{'message'}="@errors"; + return; + } + my @r = unix_grep($file,"\ttotal,"); + my $string = $r[0]; + my @fileds=split(',',$string); + my $val=$fileds[11]; + $val =~ s/[^0-9.]+//g; + # my $val = extract_result($self,$file,"average packet latency"); + if(length $val ==0){ + $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="Failed"; + $self->{'name'}{"$name"}{'traffic'}{$traffic}{'message'}="The average packet latency is undefined for $inject"; + return; + } + $self->{'name'}{"$name"}{'traffic'}{$traffic}{"packet_latency"}{$inject}="$val"; + + } + my ($z,$zl, $s,$sl) = get_zero_load_and_saturation ($self,$name,$traffic,$results_path); + print "($z,$zl, $s,$sl)\n"; + #save results in a text file + append_text_to_file($log_file,"\t Passed: zero load ($z,$zl) saturation ($s,$sl)\n"); + $self->{'name'}{"$name"}{'traffic'}{$traffic}{'overal_result'}="passed"; } - sub object_get_attribute_order{ - my ($self,$attribute)=@_; - return unless(defined $self->{parameters_order}{$attribute}); - my @order=@{$self->{parameters_order}{$attribute}}; - return uniq(@order) + my ($self,$attribute)=@_; + return unless(defined $self->{parameters_order}{$attribute}); + my @order=@{$self->{parameters_order}{$attribute}}; + return uniq(@order) } sub save_file { - my ($file_path,$text)=@_; - open my $fd, ">$file_path" or die "could not open $file_path: $!"; - print $fd $text; - close $fd; + my ($file_path,$text)=@_; + open my $fd, ">$file_path" or die "could not open $file_path: $!"; + print $fd $text; + close $fd; } sub object_add_attribute_order{ - my ($self,$attribute,@param)=@_; - my $r = $self->{'parameters_order'}{$attribute}; - my @a; - @a = @{$r} if(defined $r); - push (@a,@param); - @a=uniq(@a); - $self->{'parameters_order'}{$attribute} =\@a; + my ($self,$attribute,@param)=@_; + my $r = $self->{'parameters_order'}{$attribute}; + my @a; + @a = @{$r} if(defined $r); + push (@a,@param); + @a=uniq(@a); + $self->{'parameters_order'}{$attribute} =\@a; } sub append_text_to_file { - my ($file_path,$text)=@_; - open(my $fd, ">>$file_path") or die "could not open $file_path: $!"; - print $fd $text; - close $fd; + my ($file_path,$text)=@_; + open(my $fd, ">>$file_path") or die "could not open $file_path: $!"; + print $fd $text; + close $fd; } sub object_add_attribute{ - my ($self,$attribute1,$attribute2,$value)=@_; - if(!defined $attribute2){$self->{$attribute1}=$value;} - else {$self->{$attribute1}{$attribute2}=$value;} + my ($self,$attribute1,$attribute2,$value)=@_; + if(!defined $attribute2){$self->{$attribute1}=$value;} + else {$self->{$attribute1}{$attribute2}=$value;} } - - sub object_get_attribute{ - my ($self,$attribute1,$attribute2)=@_; - if(!defined $attribute2) {return $self->{$attribute1};} - return $self->{$attribute1}{$attribute2}; + my ($self,$attribute1,$attribute2)=@_; + if(!defined $attribute2) {return $self->{$attribute1};} + return $self->{$attribute1}{$attribute2}; } sub powi{ # x^y - my ($x,$y)=@_; # compute x to the y - my $r=1; - for (my $i = 0; $i < $y; ++$i ) { - $r *= $x; - } - return $r; + my ($x,$y)=@_; # compute x to the y + my $r=1; + for (my $i = 0; $i < $y; ++$i ) { + $r *= $x; + } + return $r; } sub sum_powi{ # x^(y-1) + x^(y-2) + ...+ 1; - my ($x,$y)=@_; # compute x to the y - my $r = 0; + my ($x,$y)=@_; # compute x to the y + my $r = 0; for (my $i = 0; $i < $y; $i++){ - $r += powi( $x, $i ); + $r += powi( $x, $i ); } - return $r; -} + return $r; +} sub log2{ - my $num=shift; - my $log=($num <=1) ? 1: 0; - while( (1<< $log) < $num) { - $log++; - } - return $log; + my $num=shift; + my $log=($num <=1) ? 1: 0; + while( (1<< $log) < $num) { + $log++; + } + return $log; } - sub remove_not_hex { - my $s=shift; - $s =~ s/[^0-9a-fA-F]//g; - return $s; + my $s=shift; + $s =~ s/[^0-9a-fA-F]//g; + return $s; } sub remove_not_number { - my $s=shift; - $s =~ s/[^0-9]//g; - return $s; - + my $s=shift; + $s =~ s/[^0-9]//g; + return $s; + } sub check_file_has_string { @@ -744,51 +629,46 @@ sub check_file_has_string { my $r; open(FILE,$file); if (grep{/$string/} ){ - $r= 1; #print "word found\n"; + $r= 1; #print "word found\n"; }else{ - $r= 0; #print "word not found\n"; + $r= 0; #print "word not found\n"; } close FILE; return $r; } - sub gen_verilator_makefile{ - my ($top_ref,$target_dir) =@_; - my %tops = %{$top_ref}; - my $p=''; - my $q=''; - my $h=''; - my $l; - my $lib_num=0; - my $all_lib=""; - foreach my $top (sort keys %tops) { - $p = "$p ${top}__ALL.a "; - $q = $q."lib$lib_num:\n\t\$(MAKE) -f ${top}.mk\n"; - $h = "$h ${top}.h "; - $l = $top; - $all_lib=$all_lib." lib$lib_num"; - $lib_num++; - } - - my $make= " - + my ($top_ref,$target_dir) =@_; + my %tops = %{$top_ref}; + my $p=''; + my $q=''; + my $h=''; + my $l; + my $lib_num=0; + my $all_lib=""; + foreach my $top (sort keys %tops) { + $p = "$p ${top}__ALL.a "; + $q = $q."lib$lib_num:\n\t\$(MAKE) -f ${top}.mk\n"; + $h = "$h ${top}.h "; + $l = $top; + $all_lib=$all_lib." lib$lib_num"; + $lib_num++; + } + my $make= " + default: sim - - include $l.mk lib: $all_lib $q - ####################################################################### # Compile flags CPPFLAGS += -DVL_DEBUG=1 -ifeq (\$(CFG_WITH_CCWARN),yes) # Local... Else don't burden users +ifeq (\$(CFG_WITH_CCWARN),yes)\t# Local... Else don't burden users CPPFLAGS += -DVL_THREADED=1 CPPFLAGS += -W -Werror -Wall endif @@ -804,51 +684,48 @@ sub gen_verilator_makefile{ # Linking final exe -- presumes have a sim_main.cpp -sim: testbench.o \$(VK_GLOBAL_OBJS) $p \$(SLIB) - \$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 -lpthread 2>&1 | c++filt +sim:\ttestbench.o \$(VK_GLOBAL_OBJS) $p \$(SLIB) +\t\$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 -lpthread 2>&1 | c++filt testbench.o: testbench.cpp $h \$(HLIB) clean: - rm *.o *.a testbench +\trm *.o *.a testbench "; -save_file ($target_dir,$make); - -} + save_file ($target_dir,$make); +} sub get_project_dir{ #mpsoc directory address - my $dir = Cwd::getcwd(); - my @p= split('/perl_gui',$dir); - @p= split('/Integration_test',$p[0]); - my $d = abs_path("$p[0]/../"); - - return $d; + my $dir = Cwd::getcwd(); + my @p= split('/perl_gui',$dir); + @p= split('/Integration_test',$p[0]); + my $d = abs_path("$p[0]/../"); + return $d; } #return lines containig pattern in a givn file sub unix_grep { - my ($file,$pattern)=@_; + my ($file,$pattern)=@_; open(FILE,$file); my @arr = ; my @lines = grep /$pattern/, @arr; - return @lines; + return @lines; } - sub regen_object { - my $path=shift; - $path = get_full_path_addr($path); - my $pp= eval { do $path }; - my $r= ($@ || !defined $pp); - return ($pp,$r,$@); + my $path=shift; + $path = get_full_path_addr($path); + my $pp= eval { do $path }; + my $r= ($@ || !defined $pp); + return ($pp,$r,$@); } sub get_full_path_addr{ - my $file=shift; - my $dir = Cwd::getcwd(); - my $full_path = "$dir/$file"; - return $full_path if -f ($full_path ); - return $file; + my $file=shift; + my $dir = Cwd::getcwd(); + my $full_path = "$dir/$file"; + return $full_path if -f ($full_path ); + return $file; } diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index 18e7cf7..6fc7a0b 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -295,7 +295,7 @@ module inout_ports #( .any_ovc_granted_in_outport_all(any_ovc_granted_in_outport_all), .ovc_avalable_all(ovc_avalable_all), .clk(clk), - .reset(reset), + .reset(reset), .ssa_ctrl_o(ssa_ctrl) ); @@ -305,7 +305,7 @@ module inout_ports #( end end //ssa - for(i=0;i< P;i=i+1) begin :p_ + for(i=0;i< P;i=i+1) begin :p_ assign ssa_flit_wr_all [i] = ssa_ctrl[i].ssa_flit_wr; end//for diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 205fa1c..7f01f28 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -228,7 +228,7 @@ module input_queue_per_port #( localparam VV = V * V, - VDSTPw = V * DSTPw, + VDSTPw = V * DSTPw, W = WEIGHTw, WP = W * P, P_1=( SELF_LOOP_EN=="NO")? P-1 : P, @@ -248,7 +248,7 @@ module input_queue_per_port #( PLw = (TOPOLOGY == "FMESH") ? Pw : ELw, VPLw= V * PLw, PRAw= P * RAw; - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ input reset, clk; input router_info_t router_info; @@ -336,7 +336,7 @@ module input_queue_per_port #( assign flit_wr =(flit_in_wr )? vc_num_in : {V{1'b0}}; assign rd_hdr_fwft_fifo = (ssa_ctrl_in.ivc_reset | vsa_ctrl_in.ivc_reset | (smart_ctrl_in.ivc_reset & ~ smart_ctrl_in.ivc_single_flit_pck)) & ~ multiple_dest; assign wr_hdr_fwft_fifo = hdr_flit_wr | (smart_hdr_en & ~ smart_ctrl_in.ivc_single_flit_pck); - assign ivc_request = ivc_not_empty; + assign ivc_request = ivc_not_empty; wire [V-1 : 0] flit_is_tail2; @@ -531,6 +531,7 @@ module input_queue_per_port #( .reset (reset), .clk (clk) ); + /* multi_mesh_ovc_list_per_ivc #( .IVC_NUM(i), //Input port VC number .P(P) //router IO number @@ -541,6 +542,7 @@ module input_queue_per_port #( .ovc_sel(ovc_sel_ivc[i]), .ovcs_out(candidate_ovcs [(i+1)*V-1 : i*V]) ); + */ end if(PCK_TYPE == "MULTI_FLIT") begin : multi_flit @@ -662,7 +664,7 @@ module input_queue_per_port #( ); end else begin :c_num_1 assign class_out[i] = 1'b0; - end + end //localparam CAST_TYPE = "UNICAST"; // multicast is not yet supported /* verilator lint_off WIDTH */ @@ -687,7 +689,7 @@ module input_queue_per_port #( .reset(reset), .clk(clk), .clear(clear_dspt_mulicast [i]) // clear the destination port once it got the entire packet - ); + ); //TODO remove multiple_dest[i] to see if it works? @@ -796,7 +798,7 @@ module input_queue_per_port #( .swap_port_presel(swap_port_presel[i]), .port_pre_sel(port_pre_sel), .odd_column(odd_column) - ); + ); /* verilator lint_off WIDTH */ if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 760807c..b6ce77c 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -145,7 +145,7 @@ module mesh_torus_noc_top #( (IS_MESH)? is_grounded : //last_y_mesh (IS_TORUS)? router_chan_out[fmesh_router_id(x, 0)][NORTH] : //last_y_torus chan_in_all[SOUTH_ID]; //last_y_fmesh - if(IS_FMESH) begin :IS_FMESH //connect to endpoints + if(IS_FMESH) begin :fmesh //connect to endpoints if(x == NX-1) assign chan_out_all [EAST_ID] = router_chan_out [fmesh_router_id(x,y)][EAST]; if(y ==0 ) assign chan_out_all [NORTH_ID] = router_chan_out [fmesh_router_id(x,y)][NORTH]; if (x ==0 ) assign chan_out_all [WEST_ID] = router_chan_out[fmesh_router_id(x, y)][WEST]; diff --git a/mpsoc/rtl/src_noc/noc_top.sv b/mpsoc/rtl/src_noc/noc_top.sv index ad37a5a..5d700fd 100644 --- a/mpsoc/rtl/src_noc/noc_top.sv +++ b/mpsoc/rtl/src_noc/noc_top.sv @@ -88,6 +88,7 @@ module noc_top #( .router_event (router_event ) ); end else if (IS_MULTI_MESH) begin : multimesh + /* multi_mesh #( .NOC_ID(NOC_ID) ) noc_top ( @@ -97,6 +98,7 @@ module noc_top #( .chan_out_all (chan_out_all ), .router_event (router_event ) ); + */ end else begin :custom_ custom_noc_top #( diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index c4f7d8f..37d6a00 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -21,7 +21,7 @@ package pronoc_pkg; Cw= (C==0)? 1 : log2(C), NRw = log2(NR), NEw = log2(NE), - Bw = log2(B), + Bw = log2(B), WRRA_CONFIG_INDEX=0, SMART_EN = (SMART_MAX !=0), SMART_NUM= (SMART_EN) ? SMART_MAX : 1, @@ -80,7 +80,7 @@ package pronoc_pkg; /********************* * ssa : static straight allocator: * enable single cycle latency for flits goes to the same direction -**********************/ +**********************/ typedef struct packed { logic [V-1 : 0] ovc_is_allocated; diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index ce74081..6dce726 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -35,7 +35,7 @@ module ss_allocator #( parameter NOC_ID=0, - parameter P=5 + parameter P=5 )( clk, reset, @@ -45,17 +45,17 @@ module ss_allocator #( any_ivc_sw_request_granted_all , ovc_avalable_all, ivc_info, - ovc_info, + ovc_info, ssa_ctrl_o ); - `NOC_CONF - localparam + `NOC_CONF + localparam PV = V * P, VV = V * V, PVV = PV * V, - PVDSTPw= PV * DSTPw, + PVDSTPw= PV * DSTPw, PFw = P * Fw, - DISABLED = P; + DISABLED = P; input [PFw-1 : 0] flit_in_all; input [P-1 : 0] flit_in_wr_all; @@ -83,7 +83,7 @@ module ss_allocator #( wire [PV-1 : 0] decreased_credit_in_ss_ovc; wire [PV-1 : 0] ivc_num_getting_sw_grantin_SS_all; wire [PV-1 : 0] ivc_request_all; - wire [PV-1 : 0] assigned_ovc_not_full_all; + wire [PV-1 : 0] assigned_ovc_not_full_all; wire [PVDSTPw-1 : 0] dest_port_encoded_all; wire [PVV-1 : 0] assigned_ovc_num_all; wire [PV-1 : 0] ovc_is_assigned_all; @@ -96,7 +96,7 @@ module ss_allocator #( localparam C_PORT = i/V; localparam SS_PORT = strieght_port (P,C_PORT); assign ivc_request_all[i] = ivc_info[C_PORT][i%V].ivc_req; - assign assigned_ovc_not_full_all[i] = ~ovc_info[SS_PORT][i%V].full; + //assign assigned_ovc_not_full_all[i] = ivc_info[C_PORT][i%V].assigned_ovc_not_full; assign dest_port_encoded_all [(i+1)*DSTPw-1 : i*DSTPw] = ivc_info[C_PORT][i%V].dest_port_encoded; assign assigned_ovc_num_all[(i+1)*V-1 : i*V] = ivc_info[C_PORT][i%V].assigned_ovc_num; @@ -114,8 +114,10 @@ module ss_allocator #( assign single_flit_pck_all[i]= 1'b0; assign ovc_single_flit_pck_all [i] =1'b0; assign ivc_num_getting_sw_grantin_SS_all[i]=1'b0; - // assign predict_flit_wr_all [i]=1'b0; + assign assigned_ovc_not_full_all[i]=1'b0; + // assign predict_flit_wr_all [i]=1'b0; end else begin : ssa + assign assigned_ovc_not_full_all[i] = ~ovc_info[SS_PORT][i%V].full; assign any_ovc_granted_in_ss_port[i]=any_ovc_granted_in_outport_all[SS_PORT]; assign ovc_avalable_in_ss_port[i]=ovc_avalable_all[(SS_PORT*V)+(i%V)]; assign ovc_allocated_all[(SS_PORT*V)+(i%V)]=ovc_allocated_in_ss_port[i]; @@ -128,20 +130,20 @@ module ss_allocator #( .NOC_ID(NOC_ID), .SS_PORT(SS_PORT), .V_GLOBAL(i), - .P(P) + .P(P) ) the_ssa_per_vc ( .flit_in_wr(flit_in_wr_all[(i/V)]), .flit_in(flit_in_all[((i/V)+1)*Fw-1 : (i/V)*Fw]), - .any_ivc_sw_request_granted(any_ivc_sw_request_granted_all[(i/V)]), - .any_ovc_granted_in_ss_port(any_ovc_granted_in_ss_port[i]), - .ovc_avalable_in_ss_port(ovc_avalable_in_ss_port[i]), + .any_ivc_sw_request_granted(any_ivc_sw_request_granted_all[(i/V)]), + .any_ovc_granted_in_ss_port(any_ovc_granted_in_ss_port[i]), + .ovc_avalable_in_ss_port(ovc_avalable_in_ss_port[i]), .ivc_request(ivc_request_all[i]), .assigned_ovc_not_full(assigned_ovc_not_full_all[i]), .destport_encoded(dest_port_encoded_all[(i+1)*DSTPw-1 : i*DSTPw]), .assigned_to_ssovc(assigned_ovc_num_all[(i*V)+(i%V)]), - .ovc_is_assigned(ovc_is_assigned_all[i]), - .ovc_allocated(ovc_allocated_in_ss_port[i]), - .ovc_released(ovc_released_in_ss_port[i]), + .ovc_is_assigned(ovc_is_assigned_all[i]), + .ovc_allocated(ovc_allocated_in_ss_port[i]), + .ovc_released(ovc_released_in_ss_port[i]), .granted_ovc_num(granted_ovc_num_all[(i+1)*V-1 : i*V]), .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant_all[i]), .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant_all[i]), @@ -152,11 +154,11 @@ module ss_allocator #( `ifdef SIMULATION ,.clk(clk) `endif - ); + ); end//ssa end// vc_loop - for(i=0;i Date: Mon, 26 May 2025 18:06:11 +0200 Subject: [PATCH 026/107] fix linting warnings --- .../synthetic_sim/golden_ref/general | 6 + mpsoc/rtl/src_noc/flit_buffer.sv | 167 +++++++++--------- mpsoc/rtl/src_noc/inout_ports.sv | 8 +- mpsoc/rtl/src_noc/input_ports.sv | 3 +- mpsoc/rtl/src_noc/output_ports.sv | 46 ++--- mpsoc/rtl/src_noc/packet_injector.sv | 24 +-- mpsoc/rtl/src_noc/router_bypass.sv | 21 +-- mpsoc/rtl/src_noc/router_top.sv | 2 +- 8 files changed, 142 insertions(+), 135 deletions(-) diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/general b/mpsoc/Integration_test/synthetic_sim/golden_ref/general index 606a952..a0c25e1 100644 --- a/mpsoc/Integration_test/synthetic_sim/golden_ref/general +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/general @@ -15,6 +15,8 @@ Verification Results: model is generated successfully. ****************************mesh_2x2_openpiton : Compile *******************************: model is generated successfully. +****************************mesh_3x3_v2_ssa : Compile *******************************: + model is generated successfully. ****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: model is generated successfully. ****************************mesh_4x4_smart3 : Compile *******************************: @@ -59,6 +61,8 @@ Verification Results: Passed: zero load (2,14.4245) saturation (30,98.3569) ****************************mesh_2x2_openpiton : random traffic *******************************: Passed: zero load (2,9.10156) saturation (66,72.3384) +****************************mesh_3x3_v2_ssa : random traffic *******************************: + Passed: zero load (2,10.2442) saturation (74,99.0811) ****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: Passed: zero load (2,14.4623) saturation (22,261.684) ****************************mesh_4x4_smart3 : random traffic *******************************: @@ -103,6 +107,8 @@ Verification Results: Passed: zero load (2,15.916) saturation (26,118.048) ****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: Passed: zero load (2,8.7482) saturation (100,-) +****************************mesh_3x3_v2_ssa : transposed 1 traffic *******************************: + Passed: zero load (10,10.3955) saturation (54,77.1181) ****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: Passed: zero load (2,14.8953) saturation (26,146.747) ****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index e934b98..fd6082c 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -30,7 +30,7 @@ module flit_buffer #( parameter V= 1, - parameter B = 4 + parameter B = 4 )( din, // Data in vc_num_wr,//write virtual channel @@ -52,14 +52,14 @@ module flit_buffer `NOC_CONF - localparam + localparam Bw = (B==1)? 1 : log2(B), BV = B * V, - BVw = log2(BV), + BVw = log2(BV), Vw = (V==1)? 1 : log2(V), DEPTHw = log2(B+1), BwV = Bw * V, - BVwV = BVw * V, + BVwV = BVw * V, RESTw = Fw -2-V , PTRw = ((2**Bw)==B)? Bw : BVw, // if B is power of 2 PTRw is Bw else is BVw ARRAYw = PTRw * V, @@ -76,21 +76,21 @@ module flit_buffer output [V-1 :0] vc_not_empty; input reset; input clk; - input [V-1 :0] ssa_rd; + input [V-1 :0] ssa_rd; input [V-1 :0] multiple_dest; - input [V-1 :0] sub_rd_ptr_ld; - output [V-1 : 0] flit_is_tail; + input [V-1 :0] sub_rd_ptr_ld; + output [V-1 : 0] flit_is_tail; //pointers wire [PTRw- 1 : 0] rd_ptr [V-1 :0]; - wire [PTRw- 1 : 0] wr_ptr [V-1 :0]; + wire [PTRw- 1 : 0] wr_ptr [V-1 :0]; reg [PTRw- 1 : 0] rd_ptr_next [V-1 :0]; reg [PTRw- 1 : 0] wr_ptr_next [V-1 :0]; reg [PTRw- 1 : 0] sub_rd_ptr_next [V-1 :0]; - wire [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; + wire [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; wire [PTRw-1 : 0] ptr_tmp [V-1 : 0]; wire [ARRAYw-1 : 0] rd_ptr_array; - wire [ARRAYw-1 : 0] wr_ptr_array; + wire [ARRAYw-1 : 0] wr_ptr_array; wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_din; wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_dout; @@ -98,40 +98,40 @@ module flit_buffer wire [V-1 : 0] rd; wire [DEPTHw-1 : 0] depth [V-1 :0]; reg [DEPTHw-1 : 0] depth_next [V-1 :0]; - wire [DEPTHw-1 : 0] sub_depth [V-1 :0]; - reg [DEPTHw-1 : 0] sub_depth_next [V-1 :0]; + wire [DEPTHw-1 : 0] sub_depth [V-1 :0]; + reg [DEPTHw-1 : 0] sub_depth_next [V-1 :0]; - reg [B-1 : 0] tail_fifo [V-1 : 0]; + reg [B-1 : 0] tail_fifo [V-1 : 0]; wire [1 : 0] flgs_in, flgs_out; wire [V-1: 0] vc_in; wire [RESTw-1 :0 ] flit_rest_in,flit_rest_out; wire [V-1 : 0] sub_rd; wire [V-1 : 0] sub_restore; - assign wr = (wr_en)? vc_num_wr : {V{1'b0}}; + assign wr = (wr_en)? vc_num_wr : {V{1'b0}}; - genvar i; + genvar i; generate /* verilator lint_off WIDTH */ if (CAST_TYPE != "UNICAST") begin : nouni /* verilator lint_on WIDTH */ assign sub_rd = (rd_en)? vc_num_rd : ssa_rd; assign sub_restore = sub_rd_ptr_ld; - assign rd = (rd_en)? vc_num_rd & ~multiple_dest : ssa_rd & ~multiple_dest; + assign rd = (rd_en)? vc_num_rd & ~multiple_dest : ssa_rd & ~multiple_dest; end else begin : unicast - assign rd = (rd_en)? vc_num_rd : ssa_rd; + assign rd = (rd_en)? vc_num_rd : ssa_rd; end /* verilator lint_off WIDTH */ if (PCK_TYPE == "MULTI_FLIT") begin :multi - /* verilator lint_on WIDTH */ - assign {flgs_in,vc_in,flit_rest_in}=din; + /* verilator lint_on WIDTH */ + assign {flgs_in,vc_in,flit_rest_in}=din; assign fifo_ram_din = {flgs_in,flit_rest_in}; assign {flgs_out,flit_rest_out} = fifo_ram_dout; - assign dout = {flgs_out,{V{1'bX}},flit_rest_out}; + assign dout = {flgs_out,{V{1'bX}},flit_rest_out}; end else begin : single assign fifo_ram_din = din[RAM_DATA_WIDTH-1 : 0]; - assign dout = {2'b11,{V{1'bX}},fifo_ram_dout}; + assign dout = {2'b11,{V{1'bX}},fifo_ram_dout}; end for(i=0;i 0); + assign vc_not_empty [i] = (sub_depth[i] > 0); end else begin : unicast assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = rd_ptr[i]; @@ -160,7 +160,7 @@ module flit_buffer end end//for -/***************** +/***************** Buffer width is power of 2 ******************/ @@ -171,10 +171,10 @@ module flit_buffer wire [Vw-1 : 0] wr_select_addr; wire [Vw-1 : 0] rd_select_addr; wire [Bw+Vw-1 : 0] wr_addr; - wire [Bw+Vw-1 : 0] rd_addr; + wire [Bw+Vw-1 : 0] rd_addr; assign wr_addr = {wr_select_addr,vc_wr_addr}; - assign rd_addr = {rd_select_addr,vc_rd_addr}; + assign rd_addr = {rd_select_addr,vc_rd_addr}; onehot_mux_1D #( .W(Bw), @@ -183,7 +183,7 @@ module flit_buffer .in(wr_ptr_array), .out(vc_wr_addr), .sel(vc_num_wr) - ); + ); onehot_mux_1D #( .W(Bw), @@ -195,14 +195,14 @@ module flit_buffer ); one_hot_to_bin #( - .ONE_HOT_WIDTH(V) + .ONE_HOT_WIDTH(V) ) wr_vc_start_addr ( .one_hot_code(vc_num_wr), .bin_code(wr_select_addr) ); one_hot_to_bin #( - .ONE_HOT_WIDTH(V) + .ONE_HOT_WIDTH(V) ) rd_vc_start_addr ( .one_hot_code(vc_num_rd), .bin_code(rd_select_addr) @@ -211,7 +211,7 @@ module flit_buffer fifo_ram #( .DATA_WIDTH (RAM_DATA_WIDTH), .ADDR_WIDTH (BVw ), - .SSA_EN(SSA_EN) + .SSA_EN(SSA_EN) ) the_queue ( .wr_data(fifo_ram_din), .wr_addr(wr_addr[BVw-1 : 0]), @@ -240,16 +240,16 @@ module flit_buffer if (wr[i] ) wr_ptr_next [i] = wr_ptr [i]+ 1'h1; if (rd[i] ) rd_ptr_next [i] = rd_ptr [i]+ 1'h1; if (wr[i] & ~rd[i]) depth_next [i] = depth[i] + 1'h1; - else if (~wr[i] & rd[i]) depth_next [i] = depth[i] - 1'h1; + else if (~wr[i] & rd[i]) depth_next [i] = depth[i] - 1'h1; end//always /* verilator lint_off WIDTH */ if (CAST_TYPE != "UNICAST") begin :multicast - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ always @ (*)begin sub_rd_ptr_next[i] = sub_rd_ptr[i]; if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i]; - else if(sub_rd[i]) sub_rd_ptr_next[i] = sub_rd_ptr[i]+ 1'h1; + else if(sub_rd[i]) sub_rd_ptr_next[i] = sub_rd_ptr[i]+ 1'h1; end /* verilator lint_off WIDTH */ @@ -266,7 +266,7 @@ module flit_buffer end//for V_ end else begin :no_pow2 -/***************** +/***************** Buffer width is not power of 2 ******************/ @@ -277,7 +277,7 @@ module flit_buffer pronoc_register #(.W(BVw),.RESET_TO(B*i)) reg1 (.in(rd_ptr_next[i]), .out(rd_ptr[i]), .reset(reset), .clk(clk)); pronoc_register #(.W(BVw),.RESET_TO(B*i)) reg2 (.in(wr_ptr_next[i]), .out(wr_ptr[i]), .reset(reset), .clk(clk)); - pronoc_register #(.W(DEPTHw) ) reg3 (.in(depth_next[i] ), .out(depth [i]), .reset(reset), .clk(clk)); + pronoc_register #(.W(DEPTHw) ) reg3 (.in(depth_next[i] ), .out(depth [i]), .reset(reset), .clk(clk)); always @(posedge clk) begin /* verilator lint_off WIDTH */ @@ -319,11 +319,11 @@ module flit_buffer assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][rd_ptr[i]-(B*i)] : 1'b1; /* verilator lint_on WIDTH */ end - end// for V_ + end// for V_ onehot_mux_1D #( .W(BVw), - .N(V) + .N(V) ) wr_mux ( .in(wr_ptr_array), .out(wr_addr), @@ -332,7 +332,7 @@ module flit_buffer onehot_mux_1D #( .W(BVw), - .N(V) + .N(V) ) rd_mux ( .in(rd_ptr_array), .out(rd_addr), @@ -342,7 +342,7 @@ module flit_buffer fifo_ram_mem_size #( .DATA_WIDTH (RAM_DATA_WIDTH), .MEM_SIZE (BV ), - .SSA_EN(SSA_EN) + .SSA_EN(SSA_EN) ) the_queue ( .wr_data (fifo_ram_din), .wr_addr (wr_addr), @@ -377,7 +377,7 @@ module flit_buffer /* verilator lint_off WIDTH */ if (CAST_TYPE != "UNICAST") begin :multicast - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ always @(posedge clk) begin if (wr[i] && (sub_depth[i] == B [DEPTHw-1 : 0]) && !sub_rd[i]) begin @@ -412,7 +412,7 @@ module flit_buffer end /* verilator lint_off WIDTH */ if (rd[i] && !wr[i] && (depth[i] == {DEPTHw{1'b0}} && SSA_EN =="YES" ))begin - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time); $finish; end @@ -434,7 +434,7 @@ endmodule module fifo_ram #( parameter DATA_WIDTH = 32, parameter ADDR_WIDTH = 8, - parameter SSA_EN="YES" // "YES" , "NO" + parameter SSA_EN="YES" // "YES" , "NO" )( wr_data, wr_addr, @@ -446,13 +446,13 @@ module fifo_ram #( ); - input [DATA_WIDTH-1 : 0] wr_data; + input [DATA_WIDTH-1 : 0] wr_data; input [ADDR_WIDTH-1 : 0] wr_addr; input [ADDR_WIDTH-1 : 0] rd_addr; input wr_en; input rd_en; input clk; - output [DATA_WIDTH-1 : 0] rd_data; + output [DATA_WIDTH-1 : 0] rd_data; reg [DATA_WIDTH-1:0] memory_rd_data; // memory @@ -494,9 +494,9 @@ endmodule module fifo_ram_mem_size #( parameter DATA_WIDTH = 32, parameter MEM_SIZE = 200, - parameter SSA_EN = "YES" // "YES" , "NO" + parameter SSA_EN = "YES" // "YES" , "NO" ) ( - wr_data, + wr_data, wr_addr, rd_addr, wr_en, @@ -509,22 +509,21 @@ module fifo_ram_mem_size #( input integer number; begin log2=(number <=1) ? 1: 0; while(2**log2 | [3][0] [2] */ - smart_chanel_t smart_chanel_next [P-1 : 0]; + smart_chanel_t smart_chanel_next [P-1 : 0]; genvar i,j,z; generate for (i=0;i Date: Tue, 27 May 2025 18:33:42 +0200 Subject: [PATCH 027/107] merge altera integration results in one log file --- .../Altera/golden_ref/line4_smart3 | 41 ---- .../Altera/golden_ref/mesh_3x3_v2_ssa | 46 ----- .../Altera/golden_ref/mesh_4x4_2cycle_mcast_f | 39 ---- .../Altera/golden_ref/mesh_4x4_2cycle_xy_v2 | 47 ----- .../Altera/golden_ref/report.csv | 5 + mpsoc/Integration_test/Altera/run.sh | 113 +++++++++-- mpsoc/Integration_test/Altera/src/extract.prl | 180 +++++++++--------- mpsoc/Integration_test/synthetic_sim/run.sh | 68 +++---- 8 files changed, 222 insertions(+), 317 deletions(-) delete mode 100644 mpsoc/Integration_test/Altera/golden_ref/line4_smart3 delete mode 100644 mpsoc/Integration_test/Altera/golden_ref/mesh_3x3_v2_ssa delete mode 100644 mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f delete mode 100644 mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 create mode 100644 mpsoc/Integration_test/Altera/golden_ref/report.csv diff --git a/mpsoc/Integration_test/Altera/golden_ref/line4_smart3 b/mpsoc/Integration_test/Altera/golden_ref/line4_smart3 deleted file mode 100644 index 1e475c9..0000000 --- a/mpsoc/Integration_test/Altera/golden_ref/line4_smart3 +++ /dev/null @@ -1,41 +0,0 @@ - , Fr_max -pronoc_output_files, 159.64 , Fmax = 159.64 Mhz - --, Combinational ALUTs -pronoc_output_files, 1696 , 36100 ( 5 % ) ; - - - - --, Dedicated logic registers -pronoc_output_files, 1426 , 36100 ( 4 % ) ; - - - - --, Memory ALUTs -pronoc_output_files, 0 , 18050 ( 0 % ) ; - - - - --, ALMs: partially or completely used -pronoc_output_files, 1435 , 18050 ( 8 % ) - - - - --, Logic utilization -pronoc_output_files, 2460 , 36100 ( 7 % ) - - - - --, M9K blocks -pronoc_output_files, 20 , 319 ( 6 % ) ; - - - - --, Total block memory bits -pronoc_output_files, 5808 , 2939904 ( < 1 % ) ; diff --git a/mpsoc/Integration_test/Altera/golden_ref/mesh_3x3_v2_ssa b/mpsoc/Integration_test/Altera/golden_ref/mesh_3x3_v2_ssa deleted file mode 100644 index 6011be7..0000000 --- a/mpsoc/Integration_test/Altera/golden_ref/mesh_3x3_v2_ssa +++ /dev/null @@ -1,46 +0,0 @@ -***************** results ***************** - , Fr_max -pronoc_output_files, 125.5 , Fmax = 125.5 Mhz - - - - --, Combinational ALUTs -pronoc_output_files, 12019 , 36100 ( 33 % ) ; - - - - --, Dedicated logic registers -pronoc_output_files, 9370 , 36100 ( 26 % ) ; - - - - --, Memory ALUTs -pronoc_output_files, 0 , 18050 ( 0 % ) ; - - - - --, ALMs: partially or completely used -pronoc_output_files, 9253 , 18050 ( 51 % ) - - - - --, Logic utilization -pronoc_output_files, 15031 , 36100 ( 42 % ) - - - - --, M9K blocks -pronoc_output_files, 33 , 319 ( 10 % ) ; - - - - --, Total block memory bits -pronoc_output_files, 16320 , 2939904 ( < 1 % ) ; - diff --git a/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f deleted file mode 100644 index 7c1fe19..0000000 --- a/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_mcast_f +++ /dev/null @@ -1,39 +0,0 @@ - --, Combinational ALUTs -pronoc_output_files, 18343 , 36100 ( 51 % ) ; - - - - --, Dedicated logic registers -pronoc_output_files, 8913 , 36100 ( 25 % ) ; - - - - --, Memory ALUTs -pronoc_output_files, 0 , 18050 ( 0 % ) ; - - - - --, ALMs: partially or completely used -pronoc_output_files, 12617 , 18050 ( 70 % ) - - - - --, Logic utilization -pronoc_output_files, 22303 , 36100 ( 62 % ) - - - - --, M9K blocks -pronoc_output_files, 128 , 319 ( 40 % ) ; - - - - --, Total block memory bits -pronoc_output_files, 33792 , 2939904 ( 1 % ) ; diff --git a/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 b/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 deleted file mode 100644 index 9d0213e..0000000 --- a/mpsoc/Integration_test/Altera/golden_ref/mesh_4x4_2cycle_xy_v2 +++ /dev/null @@ -1,47 +0,0 @@ -extract_results(/home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc_work/verify/quartus_pronoc,pronoc); -/home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc_work/verify/quartus_pronoc -***************** results ***************** - , Fr_max -pronoc_output_files, 146.35 , Fmax = 146.35 Mhz - - - - --, Combinational ALUTs -pronoc_output_files, 15546 , 36100 ( 43 % ) ; - - - - --, Dedicated logic registers -pronoc_output_files, 9732 , 36100 ( 27 % ) ; - - - - --, Memory ALUTs -pronoc_output_files, 0 , 18050 ( 0 % ) ; - - - - --, ALMs: partially or completely used -pronoc_output_files, 11348 , 18050 ( 63 % ) - - - - --, Logic utilization -pronoc_output_files, 18852 , 36100 ( 52 % ) - - - - --, M9K blocks -pronoc_output_files, 64 , 319 ( 20 % ) ; - - - - --, Total block memory bits -pronoc_output_files, 17408 , 2939904 ( < 1 % ) ; diff --git a/mpsoc/Integration_test/Altera/golden_ref/report.csv b/mpsoc/Integration_test/Altera/golden_ref/report.csv new file mode 100644 index 0000000..612c967 --- /dev/null +++ b/mpsoc/Integration_test/Altera/golden_ref/report.csv @@ -0,0 +1,5 @@ +File| ALMs:partiallyorcompletelyused| MemoryALUTs| Totalblockmemorybits| M9Kblocks| Dedicatedlogicregisters| CombinationalALUTs| Logicutilization| Maxfrequency +line4_smart3| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz +mesh_3x3_v2_ssa| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz +mesh_4x4_2cycle_mcast_f| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz +mesh_4x4_2cycle_xy_v2| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz diff --git a/mpsoc/Integration_test/Altera/run.sh b/mpsoc/Integration_test/Altera/run.sh index fcc51f0..4836bfe 100755 --- a/mpsoc/Integration_test/Altera/run.sh +++ b/mpsoc/Integration_test/Altera/run.sh @@ -3,15 +3,45 @@ SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) -conf="mesh_4x4_2cycle_mcast_f" -conf="line4_smart3" - -conf_file="${SCRPT_DIR_PATH}/configurations/$conf" -work="${PRONOC_WORK}/verify/quartus_pronoc" -top="quartus_pronoc" +# Source the environment variables +conf_dir="${SCRPT_DIR_PATH}/configurations" log_dir="${SCRPT_DIR_PATH}/result_logs" -log_file="${log_dir}/$conf" -golden_ref="${SCRPT_DIR_PATH}/golden_ref/$conf" +golden_dir="${SCRPT_DIR_PATH}/golden_ref" +work="${PRONOC_WORK}/verify/quartus_pronoc" +log_work="${PRONOC_WORK}/verify/logs" +mkdir -p $log_work +mkdir -p $log_dir + + + + +quartus_get_result () { + conf=$1 + if [[ -z "$conf" ]]; then + echo "No configuration provided" + exit 1 + fi + if [[ ! -f "${SCRPT_DIR_PATH}/configurations/$conf" ]]; then + echo "Configuration file ${SCRPT_DIR_PATH}/configurations/$conf does not exist" + exit 1 + fi + if [[ ! -d "${SCRPT_DIR_PATH}/result_logs" ]]; then + mkdir -p "${SCRPT_DIR_PATH}/result_logs" + fi + conf_file="${SCRPT_DIR_PATH}/configurations/$conf" + top="quartus_pronoc" + log_file="${log_work}/$conf" + golden_ref="${SCRPT_DIR_PATH}/golden_ref/$conf" + + + perl ${SCRPT_DIR_PATH}/src/param_gen.pl $conf_file + #compile + wait; + mkdir -p $log_work + perl ${SCRPT_DIR_PATH}/src/extract.prl "$PRONOC_WORK/verify/quartus_pronoc" "pronoc" > $log_file + #meld "$golden_ref" "$log_file" & + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v +} copy_filelist () { fname=$1 @@ -88,14 +118,67 @@ compile () { $Quartus_bin/quartus_sta --64bit pronoc } -perl ${SCRPT_DIR_PATH}/src/param_gen.pl $conf_file +report_all_configurations () { + output_file="$log_dir/report.csv" + > "$output_file" # Empty the file at start + # Initialize a set to track unique metric names + declare -A all_keys -compile + # First pass: collect all metric names + for file in "$log_work"/*; do + while IFS= read -r line; do + [[ -z "$line" || "$line" =~ ^# ]] && continue + IFS='|' read -ra parts <<< "$line" + key="${parts[0]// /}" # Trim whitespace from key + all_keys["$key"]=1 + done < "$file" + done -wait; + # Build the header + { + printf "File" + for key in "${!all_keys[@]}"; do + printf "| %s" "$key" + done + printf "\n" + } >> "$output_file" -mkdir -p $log_dir -perl ${SCRPT_DIR_PATH}/src/extract.prl "$PRONOC_WORK/verify/quartus_pronoc" "pronoc" > $log_file + # Second pass: extract values for each file + for file in "$log_work"/*; do + declare -A data + data["File"]="${file##*/}" + + while IFS= read -r line; do + [[ -z "$line" || "$line" =~ ^# ]] && continue + IFS='|' read -ra parts <<< "$line" + key="${parts[0]// /}" + val="${parts[1]// /}" + data["$key"]="$val" + done < "$file" + + { + printf "%s" "${data["File"]}" + for key in "${!all_keys[@]}"; do + printf "| %s" "${data[$key]}" + done + printf "\n" + } >> "$output_file" + + unset data + done +} + +for f in "$conf_dir"/*; do + if [[ -d "$f" ]]; then + continue + fi + conf=$(basename "$f") + echo "Compile configuration $conf" + quartus_get_result "$conf" +done + + +report_all_configurations -meld "$golden_ref" "$log_file" & -rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v +meld "$golden_dir/report.csv" "$log_dir/report.csv" & +echo "All configurations processed. Results are in $log_dir/report.csv" \ No newline at end of file diff --git a/mpsoc/Integration_test/Altera/src/extract.prl b/mpsoc/Integration_test/Altera/src/extract.prl index d8ac929..a27ee7b 100755 --- a/mpsoc/Integration_test/Altera/src/extract.prl +++ b/mpsoc/Integration_test/Altera/src/extract.prl @@ -1,116 +1,106 @@ #!/usr/bin/perl -w -use Cwd qw(getcwd); -use IPC::Run qw( run start pump finish timeout ); - - - -my @HWs = ( -"; Logic utilization ;", -"; Combinational ALUTs ;", -"; Memory ALUTs ;", -"; Dedicated logic registers ;", -"; Total block memory bits ;", -"; ALMs: partially or completely used ;", -"; M9K blocks ;" +use strict; +use warnings; +use Cwd qw(getcwd); +use IPC::Run qw(run timeout); + +# Regular expression to match hardware utilization results like: +# 2,460 / 36,100 ( 7 % ) +# 5808 , 2939904 ( < 1 % ) +my $result_reg = '[[:space:]]*[0-9,]+[[:space:]]*[,/][[:space:]]*[0-9,]+[[:space:]]*' + . '\([[:space:]]*(<\s*)?[0-9]+[[:space:]]*%[[:space:]]*\)[[:space:]]*;'; + +# Hash of report labels and their corresponding regex patterns +my %HWs = ( + 'Logic utilization' => ';[[:space:]]*Logic utilization[[:space:]]*;' . $result_reg, + 'Combinational ALUTs' => ';[[:space:]]*Combinational ALUTs[[:space:]]*;' . $result_reg, + 'Memory ALUTs' => ';[[:space:]]*Memory ALUTs[[:space:]]*;' . $result_reg, + 'Dedicated logic registers' => ';[[:space:]]*Dedicated logic registers[[:space:]]*;' . $result_reg, + 'Total block memory bits' => ';[[:space:]]*Total block memory bits[[:space:]]*;' . $result_reg, + 'ALMs: partially or completely used' => ';[[:space:]]*ALMs:[[:space:]]*partially or completely used[[:space:]]*;' . $result_reg, + 'M9K blocks' => ';[[:space:]]*M9K blocks[[:space:]]*;' . $result_reg, ); - - -my $csv=""; +# Result containers my %freq; my %results; +my $csv = ""; sub extract_results { - my ($dir,$parent) =@_; - my @cat = qw( bash ); - chdir "$dir"; - print getcwd()."\n"; - - my ($in, $out, $err); - #Fmax - $in ='grep -R "; clk ; ;$" | sort'; - run \@cat, \$in, \$out, \$err, timeout( 10 ) or die "grep: $?"; - - - my @lines = split("\n",$out); - foreach my $l (@lines) { - - my @f=split ('/',$l); - my $name= "${parent}_$f[0]"; - - @f=split (':',$l); - @f=split (';',$f[1]); - $f[1] =~ s/MHz//; - - if(!defined $freq{$name}){ - $freq{$name}=$f[1]; - }else{#get the minum reported max frequency - $freq{$name}=$f[1] if($f[1]< $freq{$name}); - } - - } - - - - - foreach my $hw (@HWs){ - - - - my @cat = qw( bash ); - my $in ="grep -R \"$hw\" | sort"; - $hw =~ s/[\;]//g; - - #$csv.="-,$hw\n"; - $out=undef; - run \@cat, \$in, \$out, \$err, timeout( 10 ) or die "grep: $?"; - @lines = split("\n",$out); - - foreach my $l (@lines) { - unless ( index($l,".fit.rpt") >= 0){ next;} - - my @f=split ('/',$l); - - my $name= "${parent}_$f[0]"; - my @ff = split (/\; /,$l); - my $val=$ff[2]; - $val =~ s/,//g; - my @vv = split ("/",$val); - my $t =join(',',@vv); - #$csv.= "$name, $t \n" if (defined $val) ; - $results{$hw}{$name}=$t if (defined $val) ; - } - } - + my ($dir, $parent) = @_; + chdir $dir or die "Cannot change to directory $dir: $!"; + + # ----------------------- + # Extract Fmax frequency + # ----------------------- + my ($in, $out, $err); + $in = 'grep -R "; clk ; ;$" | sort'; + run ['bash'], \$in, \$out, \$err, timeout(10) or die "Error running Fmax grep: $?"; + + for my $line (split "\n", $out) { + my ($file) = split '/', $line; + my $name = "${parent}_$file"; + + my @parts = split ':', $line; + my @fields = split ';', $parts[1]; + my $mhz = $fields[1]; + $mhz =~ s/MHz//; + + $freq{$name} = $mhz if !defined($freq{$name}) || $mhz < $freq{$name}; + } + + # ----------------------- + # Extract HW usage stats + # ----------------------- + for my $metric (sort keys %HWs) { + my $regex = $HWs{$metric}; + my $grep_cmd = "grep -RE '$regex' | sort"; + + $out = undef; + run ['bash'], \$grep_cmd, \$out, \$err, timeout(10) or die "Error running grep for $metric: $?"; + + for my $line (split "\n", $out) { + next unless $line =~ /\.fit\.rpt/; + + my ($file) = split '/', $line; + my $name = "${parent}_$file"; + + my @fields = split(/\; /, $line); + my $value = $fields[2]; + $value =~ s/[;,]//g; + + my @numbers = split /[\/,]/, $value; + $results{$metric}{$name} = join(',', @numbers); + } + } } +# Main execution +extract_results($ARGV[0], $ARGV[1]); +# Print frequency results +$csv .= "Max frequency |"; +for my $p (sort keys %freq) { + $csv .= "$freq{$p}, $freq{$p} MHz\n"; +} -print "extract_results($ARGV[0],$ARGV[1]);\n"; - -extract_results($ARGV[0],$ARGV[1]); +# Print hardware utilization results +for my $metric (sort keys %results) { + $csv .= "\n$metric |"; + for my $design (sort keys %{ $results{$metric} }) { + $csv .= " $results{$metric}{$design}\n"; + } +} +#grep -RE "Warning[[:space:]]*\(" -$csv.=" , Fr_max\n"; -foreach my $p (sort keys %freq){ - $csv.= "$p, $freq{$p}, Fmax = $freq{$p} Mhz\n"; -} +# Output +print $csv; -foreach my $p (sort keys %results){ - my $ref = $results{$p}; - my %r = %{$results{$p}} if (defined $ref) ; - $csv.= "\n\n\n\n" ; - $csv.="-,$p\n"; - foreach my $p (sort keys %r){ - $csv.= "$p, $r{$p} \n"; - } -} -print "***************** results *****************\n"; - print $csv; diff --git a/mpsoc/Integration_test/synthetic_sim/run.sh b/mpsoc/Integration_test/synthetic_sim/run.sh index 5ce80a7..0d3cea8 100755 --- a/mpsoc/Integration_test/synthetic_sim/run.sh +++ b/mpsoc/Integration_test/synthetic_sim/run.sh @@ -3,9 +3,9 @@ servers=( 'mn5') #servers' shorthand name. They should be defined in ~/.ssh/config : # -# Host your_short_name -# HostName server.on.the.web -# User user_to_user +# Host your_short_name +# HostName server.on.the.web +# User user_to_user my_ssh="ssh -t -o StrictHostKeyChecking=no" @@ -34,11 +34,11 @@ ProNoC=$(realpath "$SCRPT_DIR_PATH/../..") my_srcs=( "rtl" "Integration_test" - "src_verilator" - "src_c/netrace-1.0" - "src_c/synfull" - "script" - "/perl_gui/lib/perl" ) + "src_verilator" + "src_c/netrace-1.0" + "src_c/synfull" + "script" + "/perl_gui/lib/perl" ) @@ -175,7 +175,7 @@ fi #step one login in the server and find how much is bussy function get_server_load_percentage { - # Retrieve uptime and core information from the server + # Retrieve uptime and core information from the server out=$($my_ssh "$1" "uptime") load_avg=$(echo "$out" | grep -oP '(?<=load average: )[\d.]+' | head -n 1) # Extract 1-minute load average nproc=$($my_ssh "$1" "nproc" | tr -d '\r') # Remove any extra characters (e.g., carriage return) @@ -190,40 +190,40 @@ function get_server_load_percentage { function select_a_server { - min_load="100" - for i in "${servers[@]}"; do - echo "get load average on $i server" - get_server_load_percentage $i - if [ $min_load -gt $load_percentage ] - then - min_load=$load_percentage - my_server=$i - fi - done - if [ $min_load -gt $max_allowed_server_load_percentage ] - then - echo "[INFO] All servers are busy. Cannot continue" - exit - fi - echo "[INFO] Server $my_server is selected for running the integration test." + min_load="100" + for i in "${servers[@]}"; do + echo "get load average on $i server" + get_server_load_percentage $i + if [ $min_load -gt $load_percentage ] + then + min_load=$load_percentage + my_server=$i + fi + done + if [ $min_load -gt $max_allowed_server_load_percentage ] + then + echo "[INFO] All servers are busy. Cannot continue" + exit + fi + echo "[INFO] Server $my_server is selected for running the integration test." } function copy_sources { - $my_ssh $my_server rm -rf ${SERVER_ROOT_DIR} - $my_ssh $my_server mkdir -p "${SERVER_ROOT_DIR}/mpsoc/perl_gui/lib/" + $my_ssh $my_server rm -rf ${SERVER_ROOT_DIR} + $my_ssh $my_server mkdir -p "${SERVER_ROOT_DIR}/mpsoc/perl_gui/lib/" $my_ssh $my_server mkdir -p "${SERVER_ROOT_DIR}/mpsoc/src_c/" - $my_ssh $my_server mkdir -p "${SERVER_ROOT_DIR}/mpsoc_work" - for i in "${my_srcs[@]}"; do - echo "Copy $i on the server" - $my_scp -r "$ProNoC/$i" "$my_server:${SERVER_ROOT_DIR}/mpsoc/$i" - done + $my_ssh $my_server mkdir -p "${SERVER_ROOT_DIR}/mpsoc_work" + for i in "${my_srcs[@]}"; do + echo "Copy $i on the server" + $my_scp -r "$ProNoC/$i" "$my_server:${SERVER_ROOT_DIR}/mpsoc/$i" + done } function run_test { - cmd="export PRONOC_WORK=${SERVER_ROOT_DIR}/mpsoc_work;" - $my_ssh $my_server $cmd + cmd="export PRONOC_WORK=${SERVER_ROOT_DIR}/mpsoc_work;" + $my_ssh $my_server $cmd } From 24b5262e3b0dcdb828f98662fd20866f458da1e0 Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 28 May 2025 18:38:31 +0200 Subject: [PATCH 028/107] fix linting --- .../Altera/golden_ref/report.csv | 6 +- mpsoc/Integration_test/Altera/run.sh | 6 +- .../synthetic_sim/src/server_run.sh | 3 +- mpsoc/rtl/src_modelsim/multicast_injector.sv | 134 ++++++++++-------- mpsoc/rtl/src_noc/fmesh.sv | 4 +- mpsoc/rtl/src_noc/multicast.sv | 6 +- mpsoc/rtl/src_noc/packet_injector.sv | 131 ++++++++--------- mpsoc/rtl/src_noc/pronoc_pkg.sv | 12 +- mpsoc/rtl/src_noc/router_bypass.sv | 48 +++---- mpsoc/rtl/src_noc/router_top.sv | 7 +- mpsoc/rtl/src_noc/router_two_stage.sv | 105 ++++++++------ mpsoc/rtl/src_noc/topology_localparam.v | 21 ++- mpsoc/rtl/src_noc/traffic_gen_top.sv | 60 ++++---- mpsoc/rtl/src_openpiton/wrapper.sv | 30 ++-- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 26 ++-- 15 files changed, 313 insertions(+), 286 deletions(-) diff --git a/mpsoc/Integration_test/Altera/golden_ref/report.csv b/mpsoc/Integration_test/Altera/golden_ref/report.csv index 612c967..4a748b5 100644 --- a/mpsoc/Integration_test/Altera/golden_ref/report.csv +++ b/mpsoc/Integration_test/Altera/golden_ref/report.csv @@ -1,5 +1,5 @@ File| ALMs:partiallyorcompletelyused| MemoryALUTs| Totalblockmemorybits| M9Kblocks| Dedicatedlogicregisters| CombinationalALUTs| Logicutilization| Maxfrequency line4_smart3| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz -mesh_3x3_v2_ssa| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz -mesh_4x4_2cycle_mcast_f| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz -mesh_4x4_2cycle_xy_v2| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz +mesh_3x3_v2_ssa| 9674,18050(54%)| 0,18050(0%)| 16320,2939904(<1%)| 33,319(10%)| 9856,36100(27%)| 12903,36100(36%)| 15846,36100(44%)| 131.65,131.65MHz +mesh_4x4_2cycle_mcast_f| 12617,18050(70%)| 0,18050(0%)| 33792,2939904(1%)| 128,319(40%)| 8913,36100(25%)| 18343,36100(51%)| 22303,36100(62%)| 139.63,139.63MHz +mesh_4x4_2cycle_xy_v2| 11348,18050(63%)| 0,18050(0%)| 17408,2939904(<1%)| 64,319(20%)| 9732,36100(27%)| 15546,36100(43%)| 18852,36100(52%)| 146.35,146.35MHz diff --git a/mpsoc/Integration_test/Altera/run.sh b/mpsoc/Integration_test/Altera/run.sh index 4836bfe..dd89310 100755 --- a/mpsoc/Integration_test/Altera/run.sh +++ b/mpsoc/Integration_test/Altera/run.sh @@ -35,8 +35,10 @@ quartus_get_result () { perl ${SCRPT_DIR_PATH}/src/param_gen.pl $conf_file - #compile + + compile wait; + mkdir -p $log_work perl ${SCRPT_DIR_PATH}/src/extract.prl "$PRONOC_WORK/verify/quartus_pronoc" "pronoc" > $log_file #meld "$golden_ref" "$log_file" & @@ -181,4 +183,4 @@ done report_all_configurations meld "$golden_dir/report.csv" "$log_dir/report.csv" & -echo "All configurations processed. Results are in $log_dir/report.csv" \ No newline at end of file +echo "All configurations processed. Results are in $log_dir/report.csv" diff --git a/mpsoc/Integration_test/synthetic_sim/src/server_run.sh b/mpsoc/Integration_test/synthetic_sim/src/server_run.sh index 5b9bd95..2be366c 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/server_run.sh +++ b/mpsoc/Integration_test/synthetic_sim/src/server_run.sh @@ -7,7 +7,8 @@ SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) export PRONOC_WORK=$(realpath "$SCRPT_DIR_PATH/../../../../mpsoc_work") -export VERILATOR_ROOT=~/scratch/`whoami`/verilator_4_104 +export VERILATOR_ROOT=~/scratch/`whoami`/verilator_4_104 +#export VERILATOR_ROOT=~/scratch/`whoami`/verilator_5_014 export PATH=$PATH:$VERILATOR_ROOT/bin export C_INCLUDE_PATH=$VERILATOR_ROOT/include export CPLUS_INCLUDE_PATH=$VERILATOR_ROOT/include diff --git a/mpsoc/rtl/src_modelsim/multicast_injector.sv b/mpsoc/rtl/src_modelsim/multicast_injector.sv index 8e74f5f..4ef4f8f 100644 --- a/mpsoc/rtl/src_modelsim/multicast_injector.sv +++ b/mpsoc/rtl/src_modelsim/multicast_injector.sv @@ -45,9 +45,7 @@ module multicast_injector #( .EAw(EAw), .DSTPw(DSTPw), .LOCATED_IN_NI(1) - ) - routing_module - ( + ) routing_module ( .reset(reset), .clk(clk), .current_r_addr(current_r_addr), @@ -67,14 +65,14 @@ module multicast_injector #( .NOC_ID(NOC_ID), .DATA_w(HDR_DATA_w) ) the_header_flit_generator ( - .flit_out (hdr_flit_out), - .vc_num_in (pck_injct_in.vc), - .class_in (pck_injct_in.class_num), - .dest_e_addr_in (pck_injct_in.endp_addr), - .src_e_addr_in (current_e_addr), - .weight_in (pck_injct_in.init_weight), - .destport_in (destport), - .data_in (hdr_data_in), + .flit_out (hdr_flit_out), + .vc_num_in (pck_injct_in.vc), + .class_in (pck_injct_in.class_num), + .dest_e_addr_in (pck_injct_in.endp_addr), + .src_e_addr_in (current_e_addr), + .weight_in (pck_injct_in.init_weight), + .destport_in (destport), + .data_in (hdr_data_in), .be_in({BEw{1'b1}} )// Be is not used in simulation as we dont sent real data ); localparam @@ -84,17 +82,17 @@ module multicast_injector #( REMAIN_DAT_FLIT = REMAIN_DAT_FLIT_I + REMAIN_DAT_FLIT_F, CNTw = log2(REMAIN_DAT_FLIT), MIN_PCK_SIZ = REMAIN_DAT_FLIT +1; - reg [PCK_SIZw-1 : 0] counter, counter_next; - reg [CNTw-1 : 0] counter2,counter2_next; + reg [PCK_SIZw-1 : 0] counter, counter_next; + reg [CNTw-1 : 0] counter2,counter2_next; reg tail,head; wire [Fpay -1 : 0] remain_dat [REMAIN_DAT_FLIT -1 : 0]; wire [Fpay-1 : 0] dataIn = remain_dat[counter2]; enum {HEADER, BODY,TAIL} flit_type,flit_type_next; - wire [V-1 : 0] wr_vc_send = (flit_wr)? pck_injct_in.vc : {V{1'b0}}; - wire [V-1 : 0] vc_fifo_full; + wire [V-1 : 0] wr_vc_send = (flit_wr)? pck_injct_in.vc : {V{1'b0}}; + wire [V-1 : 0] vc_fifo_full; wire noc_ready; localparam - LAST_TMP =PCK_INJ_Dw - (Fpay*REMAIN_DAT_FLIT_I)-HDR_DATA_w, + LAST_TMP =PCK_INJ_Dw - (Fpay*REMAIN_DAT_FLIT_I)-HDR_DATA_w, LASTw=(LAST_TMP==0)? Fpay : LAST_TMP; genvar i; generate @@ -107,13 +105,13 @@ module multicast_injector #( endgenerate one_hot_mux #( - .IN_WIDTH (V ), - .SEL_WIDTH (V ), - .OUT_WIDTH (1 ) + .IN_WIDTH (V ), + .SEL_WIDTH (V ), + .OUT_WIDTH (1 ) ) one_hot_mux1 ( - .mux_in (~ vc_fifo_full ), - .mux_out (noc_ready ), - .sel (pck_injct_in.vc ) + .mux_in (~ vc_fifo_full), + .mux_out (noc_ready), + .sel (pck_injct_in.vc) ); always @ (*) begin @@ -202,6 +200,7 @@ module multicast_injector #( genvar k; reg [PCK_SIZw-1 : 0] rsv_counter [V-1 : 0]; reg [EAw-1 : 0] sender_endp_addr_reg [V-1 : 0]; + logic [Cw-1 : 0] sender_class_reg [V-1 : 0]; logic [15:0] h2t_counter [V-1 : 0]; logic [15:0] h2t_counter_next [V-1 : 0]; @@ -225,18 +224,20 @@ module multicast_injector #( rsv_counter[i]<= {PCK_SIZw{1'b0}}; h2t_counter[i]<= 16'd0; sender_endp_addr_reg [i]<= {EAw{1'b0}}; + sender_class_reg [i]<= {Cw{1'b0}}; end else begin h2t_counter[i]<=h2t_counter_next[i]; if(chan_in.flit_chanel.flit.vc[i] & chan_in.flit_chanel.flit_wr ) begin if(chan_in.flit_chanel.flit.hdr_flag)begin rsv_counter[i]<= {{(PCK_SIZw-1){1'b0}}, 1'b1}; sender_endp_addr_reg [i]<= hdr_flit_i.src_e_addr; - //synthesis translate_off + sender_class_reg [i]<= hdr_flit_i.message_class; + `ifdef SIMULATION if(hdr_flit_i.dest_e_addr != current_e_addr) begin $display("%t: ERROR: packet destination address %d does not match reciver endp address %d. %m",$time,hdr_flit_i.dest_e_addr , current_e_addr ); $finish; end//if hdr_flit_i - //synthesis translate_on + `endif //SIMULATION end //if hdr_flag else rsv_counter[i]<= rsv_counter[i]+1'b1; end//flit wr @@ -257,8 +258,8 @@ module multicast_injector #( end //if end //else end// always - if (k == 0 ) assign pck_data_o [i][HDR_DATA_w-1 : 0] = pck_data_o_gen [i][0][HDR_DATA_w-1 : 0]; - else if (k == REMAIN_DAT_FLIT) assign pck_data_o [i][PCK_INJ_Dw-1 : (k-1)*Fpay+ HDR_DATA_w] = pck_data_o_gen [i][k][LASTw-1: 0]; + if (k == 0 ) assign pck_data_o [i][HDR_DATA_w-1 : 0] = pck_data_o_gen [i][0][HDR_DATA_w-1 : 0]; + else if (k == REMAIN_DAT_FLIT) assign pck_data_o [i][PCK_INJ_Dw-1 : (k-1)*Fpay+ HDR_DATA_w] = pck_data_o_gen [i][k][LASTw-1: 0]; else assign pck_data_o [i][(k)*Fpay+HDR_DATA_w -1 : (k-1)*Fpay+ HDR_DATA_w] = pck_data_o_gen [i][k]; end //for k `ifdef SIMULATION @@ -274,38 +275,47 @@ module multicast_injector #( wire [V-1 : 0] vc_reg; wire tail_flag_reg, hdr_flag_reg; - pronoc_register #(.W(V)) register1 (.in(chan_in.flit_chanel.flit.vc), .reset (reset ), .clk (clk),.out(vc_reg)); - pronoc_register #(.W(1)) register2 (.in(chan_in.flit_chanel.flit.hdr_flag), .reset (reset ), .clk (clk),.out(hdr_flag_reg)); - pronoc_register #(.W(1)) register3 (.in(chan_in.flit_chanel.flit.tail_flag & chan_in.flit_chanel.flit_wr ),.reset (reset ), .clk (clk),.out(tail_flag_reg)); + logic [DISTw-1: 0] distance; + pronoc_register #(.W(V)) register1 (.in(chan_in.flit_chanel.flit.vc), .reset (reset ), .clk (clk),.out(vc_reg)); + pronoc_register #(.W(1)) register2 (.in(chan_in.flit_chanel.flit.hdr_flag), .reset (reset ), .clk (clk),.out(hdr_flag_reg)); + pronoc_register #(.W(1)) register3 (.in(chan_in.flit_chanel.flit.tail_flag & chan_in.flit_chanel.flit_wr ),.reset (reset ), .clk (clk),.out(tail_flag_reg)); wire [Vw-1 : 0] vc_bin; one_hot_to_bin #( - .ONE_HOT_WIDTH (V), - .BIN_WIDTH (Vw ) + .ONE_HOT_WIDTH (V), + .BIN_WIDTH (Vw ) ) one_hot_to_bin ( - .one_hot_code (vc_reg ), - .bin_code (vc_bin ) + .one_hot_code (vc_reg ), + .bin_code (vc_bin ) ); - assign pck_injct_out.data = pck_data_o[vc_bin]; - assign pck_injct_out.size = rsv_counter[vc_bin]; - assign pck_injct_out.h2t_delay = h2t_counter[vc_bin]; - assign pck_injct_out.ready = (flit_type == HEADER)? ~vc_fifo_full : {V{1'b0}}; - assign pck_injct_out.endp_addr = sender_endp_addr_reg[vc_bin]; - assign pck_injct_out.vc = vc_reg; - assign pck_injct_out.pck_wr = tail_flag_reg; - assign chan_out.flit_chanel.flit.hdr_flag =head; - assign chan_out.flit_chanel.flit.tail_flag=tail; - assign chan_out.flit_chanel.flit.vc=pck_injct_in.vc; - assign chan_out.flit_chanel.flit_wr=flit_wr; - assign chan_out.flit_chanel.flit.payload = (flit_type== HEADER)? hdr_flit_out[Fpay-1 : 0] : dataIn; - assign chan_out.smart_chanel = {SMART_CHANEL_w{1'b0}}; - assign chan_out.flit_chanel.congestion = {CONGw{1'b0}}; - assign chan_out.flit_chanel.credit= credit_o; - assign chan_out.ctrl_chanel.credit_init_val= LB; - assign chan_out.ctrl_chanel.endp_port =1'b1; + always_comb begin + pck_injct_out.data = pck_data_o[vc_bin]; + pck_injct_out.size = rsv_counter[vc_bin]; + pck_injct_out.h2t_delay = h2t_counter[vc_bin]; + pck_injct_out.ready = (flit_type == HEADER)? ~vc_fifo_full : {V{1'b0}}; + pck_injct_out.endp_addr = sender_endp_addr_reg[vc_bin]; + pck_injct_out.class_num = sender_class_reg[vc_bin]; + pck_injct_out.init_weight = WEIGHT_INIT; + pck_injct_out.vc = vc_reg; + pck_injct_out.pck_wr = tail_flag_reg; + pck_injct_out.distance = distance; + + chan_out.flit_chanel.flit.hdr_flag =head; + chan_out.flit_chanel.flit.tail_flag=tail; + chan_out.flit_chanel.flit.vc=pck_injct_in.vc; + chan_out.flit_chanel.flit_wr=flit_wr; + chan_out.flit_chanel.flit.payload = (flit_type == HEADER)? hdr_flit_out[Fpay-1 : 0] : dataIn; + chan_out.flit_chanel.congestion = {CONGw{1'b0}}; + chan_out.flit_chanel.credit= credit_o; + chan_out.smart_chanel = {SMART_CHANEL_w{1'b0}}; + for(int i=0;i1)? - flit.payload [CLASS_MSB : CLASS_LSB] : - {Cw{1'b0}}; - /* verilator lint_off WIDTH */ - assign hdr_flit.weight = (SWA_ARBITER_TYPE != "RRA")? - /* verilator lint_on WIDTH */ - flit.payload [WEIGHT_MSB : WEIGHT_LSB]: - {WEIGHTw{1'bX}}; - assign hdr_flit.be = (BYTE_EN)? - flit.payload [BE_MSB : BE_LSB]: - {BEw{1'bX}}; + always_comb begin + hdr_flit.src_e_addr = flit.payload [E_SRC_MSB : E_SRC_LSB]; + hdr_flit.dest_e_addr = flit.payload [E_DST_MSB : E_DST_LSB]; + hdr_flit.destport = flit.payload [DST_P_MSB : DST_P_LSB]; + hdr_flit.message_class = (C>1)? flit.payload [CLASS_MSB : CLASS_LSB] : {Cw{1'b0}}; + hdr_flit.weight = (IS_WRRA)? flit.payload [WEIGHT_MSB : WEIGHT_LSB] : {WEIGHTw{1'b0}}; + hdr_flit.be = (BYTE_EN)? flit.payload [BE_MSB : BE_LSB]: {BEw{1'b0}}; + end - assign offset = flit.payload [DATA_MSB : DATA_LSB]; + wire [OFFSETw-1 : 0 ] offset = flit.payload [DATA_MSB : DATA_LSB]; generate - if(Dw > OFFSETw) begin : if1 + if(Dw > OFFSETw) begin : if1 assign data_o={{(Dw-OFFSETw){1'b0}},offset}; end else begin : if2 assign data_o=offset[Dw-1 : 0]; - end - endgenerate + end + endgenerate endmodule `ifdef SIMULATION diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 6b94036..7fb57c9 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -436,9 +436,10 @@ module router_top_v output router_event_t router_event [P-1 : 0]; router_config_t router_config_in; - assign router_config_in.router_id= current_r_id [NRw-1 : 0]; - assign router_config_in.router_addr=current_r_addr; - + always_comb begin + router_config_in.router_id= current_r_id [NRw-1 : 0]; + router_config_in.router_addr=current_r_addr; + end router_top #( .NOC_ID(NOC_ID), .ROUTER_ID(ROUTER_ID), diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 59cd90f..262789d 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -154,19 +154,44 @@ module router_two_stage #( wire [CRDTw-1 : 0 ] credit_init_val_out [P-1 : 0][V-1 : 0]; logic [31:0] current_r_id; logic [RAw-1 : 0] current_r_addr; + router_info_t router_info; + wire [P-1 : 0] granted_oport_one_hot [P-1 : 0]; + wire [EAw-1 : 0] endp_addrs [NE_PER_R-1 : 0]; + + function automatic int get_enp_num(input int i); + if(IS_LINE | IS_RING | IS_MESH | IS_FMESH | IS_TORUS) begin + return (i > SOUTH) ? i - SOUTH : LOCAL; + end else if (IS_MULTI_MESH) begin + return LOCAL; + end else return 0; //TODO complete it for fattree and bin tree + endfunction + always_comb begin current_r_addr = router_config_in.router_addr; current_r_id = 0; current_r_id [NRw-1 : 0] = router_config_in.router_id; - end - - router_info_t router_info; - assign router_info.router_id=current_r_id; - assign router_info.router_addr=current_r_addr; - assign router_info.neighbors_r_addr[PRAw-1 : 0] = neighbors_r_addr; - + router_info.router_id=current_r_id; + router_info.router_addr=current_r_addr; + router_info.neighbors_r_addr[PRAw-1 : 0] = neighbors_r_addr; + for (int port=0; portSOUTH)? i-SOUTH : LOCAL; - assign ctrl_out[i].endp_addr = router_config_in[ (ENP_NUM+1)*EAw-1 : ENP_NUM*EAw]; - end else if (IS_MULTI_MESH) begin - assign ctrl_out[i].endp_addr = router_config_in[EAw-1 : 0]; - end //TODO complete it for fattree and bin tree assign chan_out[i].flit= flit_out_all [(i+1)*Fw-1: i*Fw]; assign chan_out[i].flit_wr= flit_out_wr_all [i]; assign chan_out[i].credit= credit_out_all [(i+1)*V-1: i*V] | credit_release_out [(i+1)*V-1: i*V]; @@ -210,6 +236,7 @@ module router_two_stage #( assign iport_info[i].swa_grant = ivc_num_getting_sw_grant[(i+1)*V-1: i*V]; assign iport_info[i].any_ivc_get_swa_grant= any_ivc_sw_request_granted_all[i]; assign iport_info[i].ivc_req = ivc_request_all [(i+1)*V-1: i*V]; + assign iport_info[i].granted_oport_one_hot [P-1:0] = granted_oport_one_hot[i]; assign vsa_ctrl[i].ovc_is_allocated = ovc_allocated_all [(i+1)*V-1: i*V]; assign vsa_ctrl[i].ovc_is_released = vsa_ovc_released_all[(i+1)*V-1: i*V]; @@ -219,20 +246,7 @@ module router_two_stage #( assign vsa_ctrl[i].buff_space_decreased = vsa_credit_decreased_all[(i+1)*V-1: i*V]; assign vsa_ctrl[i].ivc_granted_ovc_num = granted_ovc_num_all[(i+1)*VV-1: i*VV]; - if(SELF_LOOP_EN == "NO") begin :nslp - add_sw_loc_one_hot #( - .P(P), - .SW_LOC(i) - )add( - .destport_in(granted_dest_port_all[(i+1)*P_1-1: i*P_1]), - .destport_out(iport_info[i].granted_oport_one_hot[P-1 : 0]) - ); - end else begin :slp - assign iport_info[i].granted_oport_one_hot[P-1 : 0] = granted_dest_port_all[(i+1)*P_1-1: i*P_1]; - end - for (j=0;j Date: Thu, 29 May 2025 01:02:58 +0200 Subject: [PATCH 029/107] add VCS script --- .../VCS/configurations/line4_smart3 | 16 +++++++ .../VCS/configurations/mesh_3x3_v2_ssa | 11 +++++ .../configurations/mesh_4x4_2cycle_mcast_f | 8 ++++ .../VCS/configurations/mesh_4x4_2cycle_xy_v2 | 7 +++ mpsoc/Integration_test/VCS/run.sh | 47 +++++++++++++++++++ mpsoc/Integration_test/VCS/src/file_list.f | 6 +++ mpsoc/Integration_test/VCS/src/param_gen.pl | 46 ++++++++++++++++++ .../perl_gui/lib/perl/topology_verilog_gen.pl | 2 +- mpsoc/rtl/src_noc/noc_localparam.v | 2 +- ...custom1Rcustom_look_ahead_routing_genvar.v | 2 +- 10 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 mpsoc/Integration_test/VCS/configurations/line4_smart3 create mode 100644 mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa create mode 100644 mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_mcast_f create mode 100644 mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_xy_v2 create mode 100644 mpsoc/Integration_test/VCS/run.sh create mode 100644 mpsoc/Integration_test/VCS/src/file_list.f create mode 100644 mpsoc/Integration_test/VCS/src/param_gen.pl diff --git a/mpsoc/Integration_test/VCS/configurations/line4_smart3 b/mpsoc/Integration_test/VCS/configurations/line4_smart3 new file mode 100644 index 0000000..9242ffb --- /dev/null +++ b/mpsoc/Integration_test/VCS/configurations/line4_smart3 @@ -0,0 +1,16 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + TOPOLOGY=>"\"LINE\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "\"NO\"", + "SELF_LOOP_EN" => "\"YES\"", + "MCAST_ENDP_LIST" => "'b11", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa new file mode 100644 index 0000000..b29f1f8 --- /dev/null +++ b/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa @@ -0,0 +1,11 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "3", + "T2" => "3", + "SELF_LOOP_EN" => "\"YES\"", + "SSA_EN"=> "\"YES\"", + "LB" => 16, + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_mcast_f new file mode 100644 index 0000000..a90f35c --- /dev/null +++ b/mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_mcast_f @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_xy_v2 b/mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_xy_v2 new file mode 100644 index 0000000..b7eb7d1 --- /dev/null +++ b/mpsoc/Integration_test/VCS/configurations/mesh_4x4_2cycle_xy_v2 @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "DEBUG_EN" => "0", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/VCS/run.sh b/mpsoc/Integration_test/VCS/run.sh new file mode 100644 index 0000000..170d6c1 --- /dev/null +++ b/mpsoc/Integration_test/VCS/run.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) +SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) + +# Source the environment variables +conf_dir="${SCRPT_DIR_PATH}/configurations" +log_dir="${SCRPT_DIR_PATH}/result_logs" +work="${PRONOC_WORK}/verify/vcs" +file_list="${SCRPT_DIR_PATH}/src/file_list.f" + +mkdir -p $work +mkdir -p $log_dir + +VCS_WORK_LIB=work + +VCS_COMMON_ARGS=" -full64 -notice -nc -kdb -timescale=1ps/1ps -sverilog -debug_access +vcs+lic+wait " +VCS_ANALYZE_ARGS=" +lint=all,noVCDE,noVNGS,noPCTIO-L,noPCTIO +systemverilogext+.sv -work $VCS_WORK_LIB +warn=all " + + +vcs_lint () { + conf=$1 + if [[ -z "$conf" ]]; then + echo "No configuration provided" + exit 1 + fi + if [[ ! -f "${SCRPT_DIR_PATH}/configurations/$conf" ]]; then + echo "Configuration file ${SCRPT_DIR_PATH}/configurations/$conf does not exist" + exit 1 + fi + if [[ ! -d "${SCRPT_DIR_PATH}/result_logs" ]]; then + mkdir -p "${SCRPT_DIR_PATH}/result_logs" + fi + conf_file="${SCRPT_DIR_PATH}/configurations/$conf" + log_file="${log_work}/$conf" + + + perl ${SCRPT_DIR_PATH}/src/param_gen.pl $conf_file + + vcs $VCS_COMMON_ARGS $VCS_ANALYZE_ARGS -f $file_list -lint + + +} + + + +vcs_lint line4_smart3 diff --git a/mpsoc/Integration_test/VCS/src/file_list.f b/mpsoc/Integration_test/VCS/src/file_list.f new file mode 100644 index 0000000..1f5742d --- /dev/null +++ b/mpsoc/Integration_test/VCS/src/file_list.f @@ -0,0 +1,6 @@ ++incdir+./src + +-F ./../../rtl/src_noc/noc_filelist.f +-F ./../../rtl/src_topology/custom_flist.f + + diff --git a/mpsoc/Integration_test/VCS/src/param_gen.pl b/mpsoc/Integration_test/VCS/src/param_gen.pl new file mode 100644 index 0000000..1ad4763 --- /dev/null +++ b/mpsoc/Integration_test/VCS/src/param_gen.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl +package ProNOC; +use strict; +use warnings; +use File::Basename; + + +#add home dir in perl 5.6 +use FindBin; +use lib $FindBin::Bin; +use Cwd qw(realpath); + + + + +use File::Path qw(make_path); + + +use strict; +use warnings; + + + + +my $script_path = dirname(__FILE__); + +require "$script_path/../../synthetic_sim/src/src.pl"; +use lib "../synthetic_sim/src/perl_lib"; + +use constant::boolean; +use base 'Class::Accessor::Fast'; + +my $conf_file=$ARGV[0]; + + +sub create_noc_param_vv { + my ($conf_file)=@_; + my $o = do $conf_file; + die "Could not parse $conf_file: $@" if $@; + die "Could not read $conf_file: $!" unless defined $o; + my $param = $o->{'noc_param'}; + my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); + save_file("$script_path/noc_localparam.v",$param_v); +} + +create_noc_param_vv ($conf_file); diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index b855a7c..b88e1e5 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -929,7 +929,7 @@ sub generate_routing_v { src_e_addr_delay<=src_e_addr; end end - ${name}_look_ahead_routing_genvar_comb #( + ${Vname}_look_ahead_routing_genvar_comb #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw), diff --git a/mpsoc/rtl/src_noc/noc_localparam.v b/mpsoc/rtl/src_noc/noc_localparam.v index f82b045..bf5f394 100644 --- a/mpsoc/rtl/src_noc/noc_localparam.v +++ b/mpsoc/rtl/src_noc/noc_localparam.v @@ -156,7 +156,7 @@ localparam MAX_ROUTER=1; localparam MAX_PORT=1; - localparam int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]='{0}; + localparam int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]='{'{0}}; //int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT] : Defines how a heterogeneous number of VCs are distributed in the NoC. // - HETERO_VC= 0: Uniform VC configuration. All routers and ports have // the same number of VCs, and this parameter is not used. diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v index a5264fa..94ecf6a 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v @@ -60,7 +60,7 @@ module Tcustom1Rcustom_look_ahead_routing_genvar #( src_e_addr_delay<=src_e_addr; end end - custom1_look_ahead_routing_genvar_comb #( + Tcustom1Rcustom_look_ahead_routing_genvar_comb #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw), From bb4269d8671ee80a6b360e48d13647453052fc61 Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 29 May 2025 14:46:03 +0200 Subject: [PATCH 030/107] Replace SELF_LOOP_EN string parameter (YES/NO) with binary (1/0) --- .../Altera/configurations/line4_smart3 | 2 +- .../Altera/configurations/mesh_3x3_v2_ssa | 6 +- .../FPGA-kc07/src/deafult_noc_param | 2 +- .../VCS/configurations/line4_smart3 | 2 +- .../VCS/configurations/mesh_3x3_v2_ssa | 2 +- mpsoc/Integration_test/deafult_noc_param | 2 +- .../failed-model/mesh_4x4_openpiton_mcast_f | 27 +- .../general/fmesh_1x1_openpiton | 2 +- .../general/fmesh_2x2_openpiton | 2 +- .../general/fmesh_8x8_openpiton | 2 +- .../configurations/general/mesh_2x2_openpiton | 2 +- .../configurations/general/mesh_3x3_v2_ssa | 2 +- .../configurations/general/mesh_4x4_smart3 | 2 +- .../configurations/general/mesh_4x4_v1_B15 | 2 +- .../configurations/line-ring/line2_openpiton | 2 +- .../configurations/line-ring/line4_smart3 | 2 +- .../configurations/line-ring/line_4_v1_B15 | 2 +- .../configurations/multicast/mesh_4x4_LB5_B4 | 2 +- .../multicast/mesh_4x4_selflp_mcast_f | 2 +- .../multicast/star6_2cycle_mcast_par | 2 +- mpsoc/perl_gui/lib/emulate/tt.EML | 2 +- mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC | 2 +- mpsoc/perl_gui/lib/multi_nocs/test.phy | 8 +- mpsoc/perl_gui/lib/multi_nocs/tt.phy | 6 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 4 +- mpsoc/perl_gui/lib/soc/mor1k_tile.SOC | 2 +- mpsoc/rtl/arch/baseline.v | 10 +- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 1196 +++++++---------- mpsoc/rtl/src_noc/comb-spec1.v | 6 +- mpsoc/rtl/src_noc/comb_nonspec.sv | 65 +- mpsoc/rtl/src_noc/comb_spec2.v | 4 +- mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv | 6 +- mpsoc/rtl/src_noc/crossbar.v | 26 +- mpsoc/rtl/src_noc/debug.v | 14 +- mpsoc/rtl/src_noc/fattree_route.v | 22 +- mpsoc/rtl/src_noc/fmesh.sv | 13 +- mpsoc/rtl/src_noc/inout_ports.sv | 17 +- mpsoc/rtl/src_noc/input_ports.sv | 34 +- mpsoc/rtl/src_noc/mesh_torus.sv | 34 +- mpsoc/rtl/src_noc/multicast.sv | 30 +- mpsoc/rtl/src_noc/noc_localparam.v | 2 +- mpsoc/rtl/src_noc/output_ports.sv | 45 +- mpsoc/rtl/src_noc/pronoc_pkg.sv | 12 +- mpsoc/rtl/src_noc/router_bypass.sv | 84 +- mpsoc/rtl/src_noc/router_top.sv | 2 +- mpsoc/rtl/src_noc/router_two_stage.sv | 4 +- mpsoc/rtl/src_noc/ss_allocator.sv | 16 +- mpsoc/rtl/src_noc/topology_localparam.v | 2 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 16 +- mpsoc/rtl/src_noc/tree_route.v | 14 +- mpsoc/rtl/src_noc/wrra.v | 24 +- mpsoc/rtl/src_openpiton/noc_localparam.v | 2 +- mpsoc/rtl/src_openpiton/wrapper.sv | 6 +- mpsoc/script/synfull/noc_localparam.v | 120 +- mpsoc/smart-netrace/models/B4_V1_S0 | 2 +- mpsoc/smart-netrace/models/B4_V1_S2 | 2 +- mpsoc/smart-netrace/models/B4_V1_S4 | 2 +- mpsoc/smart-netrace/models/B4_V1_S7 | 2 +- mpsoc/smart-netrace/src/deafult_noc_param | 2 +- mpsoc/src_verilator/netrace_lib.h | 600 ++++----- mpsoc/src_verilator/simulator.cpp | 8 +- mpsoc/src_verilator/simulator.h | 325 +++-- mpsoc/src_verilator/synful_wrapper.h | 316 ++--- mpsoc/src_verilator/traffic_synthetic.h | 483 ++++--- 64 files changed, 1728 insertions(+), 1933 deletions(-) diff --git a/mpsoc/Integration_test/Altera/configurations/line4_smart3 b/mpsoc/Integration_test/Altera/configurations/line4_smart3 index 9242ffb..ca6769d 100644 --- a/mpsoc/Integration_test/Altera/configurations/line4_smart3 +++ b/mpsoc/Integration_test/Altera/configurations/line4_smart3 @@ -10,7 +10,7 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"NO\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa index b29f1f8..6838566 100644 --- a/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa +++ b/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa @@ -2,10 +2,10 @@ $model = bless( { 'noc_param'=> { "T1" => "3", "T2" => "3", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "SSA_EN"=> "\"YES\"", "LB" => 16, - "DEBUG_EN" => "0", - "MIN_PCK_SIZE" => "1", + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param b/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param index ea24d7d..af5b865 100644 --- a/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param +++ b/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param @@ -27,7 +27,7 @@ $model = bless( { "WEIGHTw" => "4", "AVC_ATOMIC_EN" => "0", "SMART_MAX" => "0", -"SELF_LOOP_EN" => "\"NO\"", +"SELF_LOOP_EN" => "0", "MAX_PCK_NUM " => " 1000000000", "MAX_PCK_SIZ " => " 16383" , "MAX_SIM_CLKs" => " 1000000000", diff --git a/mpsoc/Integration_test/VCS/configurations/line4_smart3 b/mpsoc/Integration_test/VCS/configurations/line4_smart3 index 9242ffb..ca6769d 100644 --- a/mpsoc/Integration_test/VCS/configurations/line4_smart3 +++ b/mpsoc/Integration_test/VCS/configurations/line4_smart3 @@ -10,7 +10,7 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"NO\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa index b29f1f8..4722917 100644 --- a/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa +++ b/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa @@ -2,7 +2,7 @@ $model = bless( { 'noc_param'=> { "T1" => "3", "T2" => "3", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "SSA_EN"=> "\"YES\"", "LB" => 16, "DEBUG_EN" => "0", diff --git a/mpsoc/Integration_test/deafult_noc_param b/mpsoc/Integration_test/deafult_noc_param index b024323..fdbe82b 100644 --- a/mpsoc/Integration_test/deafult_noc_param +++ b/mpsoc/Integration_test/deafult_noc_param @@ -28,7 +28,7 @@ $model = bless({ "AVC_ATOMIC_EN" => "0", "CLASS_SETTING" => "{V{1'b1}}", "SMART_MAX" => "0", - "SELF_LOOP_EN" => "\"NO\"", + "SELF_LOOP_EN" => "0", "MAX_PCK_NUM " => " 1000000000", "MAX_PCK_SIZ " => " 16383" , "MAX_SIM_CLKs" => " 1000000000", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f b/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f index 49d5467..805d174 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f +++ b/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f @@ -1,15 +1,14 @@ $model = bless( { - 'compile' => "verilate_mesh.sh", - 'noc_param'=> { - "T1" => "4", - "T2" => "4", - "V" => "1", - "ESCAP_VC_MASK" => "1'b1", - "B" => "4", - "LB" => "16", - "Fpay" => "64", - "SSA_EN" => "\"YES\"", - "SELF_LOOP_EN" => "\"YES\"", - "CAST_TYPE" => "\"MULTICAST_FULL\"", - } -}, 'ProNOC' ); + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton index fd30c47..4c45a74 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton @@ -9,7 +9,7 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"YES\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "MIN_PCK_SIZE" => "1" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton index e2cfc21..4b300a9 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton @@ -9,6 +9,6 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"YES\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton index e110fa6..9de1472 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton @@ -9,6 +9,6 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"YES\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton index cc8d20c..7d92b59 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton @@ -8,6 +8,6 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"YES\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa index 3186dc8..fc507e6 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa @@ -2,7 +2,7 @@ $model = bless( { 'noc_param'=> { "T1" => "3", "T2" => "3", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "SSA_EN"=> "\"YES\"", "LB" => 16, "DEBUG_EN" => "0", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 index 1618a2d..fc638f6 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 @@ -10,6 +10,6 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"NO\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 index 05bb0f9..f3d2143 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 @@ -8,6 +8,6 @@ $model = bless( { "LB" => "15", "Fpay" => "64", "SSA_EN" => "\"NO\"", - "SELF_LOOP_EN" => "\"NO\"", + "SELF_LOOP_EN" => "0", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton index 8be327c..7814b63 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton @@ -8,7 +8,7 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"YES\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 index 9242ffb..ca6769d 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 @@ -10,7 +10,7 @@ $model = bless( { "LB" => "16", "Fpay" => "64", "SSA_EN" => "\"NO\"", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 index 0f205e5..7bb248a 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 @@ -9,6 +9,6 @@ $model = bless( { "LB" => "15", "Fpay" => "64", "SSA_EN" => "\"NO\"", - "SELF_LOOP_EN" => "\"NO\"", + "SELF_LOOP_EN" => "0", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_LB5_B4 b/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_LB5_B4 index d726f79..50ac90c 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_LB5_B4 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_LB5_B4 @@ -7,6 +7,6 @@ $model = bless( { "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", "MCAST_ENDP_LIST" => "16'b110011000111101", "Fpay" => "64", - "SELF_LOOP_EN" => "\"YES\"" + "SELF_LOOP_EN" => "1" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_selflp_mcast_f b/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_selflp_mcast_f index 1a9c662..5c5852e 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_selflp_mcast_f +++ b/mpsoc/Integration_test/synthetic_sim/configurations/multicast/mesh_4x4_selflp_mcast_f @@ -4,6 +4,6 @@ $model = bless( { "T2" => "4", "CAST_TYPE" => "\"MULTICAST_FULL\"", "Fpay" => "64", - "SELF_LOOP_EN" => "\"YES\"" + "SELF_LOOP_EN" => "1" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/multicast/star6_2cycle_mcast_par b/mpsoc/Integration_test/synthetic_sim/configurations/multicast/star6_2cycle_mcast_par index 815288d..3bf044e 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/multicast/star6_2cycle_mcast_par +++ b/mpsoc/Integration_test/synthetic_sim/configurations/multicast/star6_2cycle_mcast_par @@ -6,6 +6,6 @@ $model = bless( { "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", "Fpay" => "32", "MCAST_ENDP_LIST" => "'b001011", - "SELF_LOOP_EN" => "\"YES\"" + "SELF_LOOP_EN" => "1" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/emulate/tt.EML b/mpsoc/perl_gui/lib/emulate/tt.EML index 0d1dcb3..385d254 100644 --- a/mpsoc/perl_gui/lib/emulate/tt.EML +++ b/mpsoc/perl_gui/lib/emulate/tt.EML @@ -30,7 +30,7 @@ $emulate = bless( { 'WEIGHTw' => '4', 'ESCAP_VC_MASK' => '2\'b01', 'C' => 0, - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'SWA_ARBITER_TYPE' => '"RRA"', 'MUX_TYPE' => '"BINARY"', 'V' => '2', diff --git a/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC b/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC index 258ebe9..dcc529a 100644 --- a/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC +++ b/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC @@ -589,7 +589,7 @@ $mpsoc = bless( { 'LB' => '4', 'MUX_TYPE' => '"BINARY"', 'SWA_ARBITER_TYPE' => '"RRA"', - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'CONGESTION_INDEX' => 3, 'DEBUG_EN' => '0', 'BYTE_EN' => '1', diff --git a/mpsoc/perl_gui/lib/multi_nocs/test.phy b/mpsoc/perl_gui/lib/multi_nocs/test.phy index b7f1132..be4db0a 100644 --- a/mpsoc/perl_gui/lib/multi_nocs/test.phy +++ b/mpsoc/perl_gui/lib/multi_nocs/test.phy @@ -11,7 +11,7 @@ $phy = bless( { 'noc_param1' => { - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'ADD_PIPREG_AFTER_CROSSBAR' => '1\'b0', 'V' => '2', 'LB' => '4', @@ -71,7 +71,7 @@ $phy = bless( { 'LB' => '4', 'V' => '2', 'ADD_PIPREG_AFTER_CROSSBAR' => '1\'b0', - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'SMART_MAX' => '0', 'CONGESTION_INDEX' => 3, 'MIN_PCK_SIZE' => '2', @@ -264,7 +264,7 @@ $phy = bless( { 'T3' => '1', 'MIN_PCK_SIZE' => '2', 'SMART_MAX' => '0', - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'V' => '2', 'ADD_PIPREG_AFTER_CROSSBAR' => '1\'b0', 'LB' => '4' @@ -282,7 +282,7 @@ $phy = bless( { 'V' => '2', 'ADD_PIPREG_AFTER_CROSSBAR' => '1\'b0', 'LB' => '4', - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'BYTE_EN' => 0, 'DEBUG_EN' => '0', 'SWA_ARBITER_TYPE' => '"RRA"', diff --git a/mpsoc/perl_gui/lib/multi_nocs/tt.phy b/mpsoc/perl_gui/lib/multi_nocs/tt.phy index 2d46d0d..50a3bc4 100644 --- a/mpsoc/perl_gui/lib/multi_nocs/tt.phy +++ b/mpsoc/perl_gui/lib/multi_nocs/tt.phy @@ -39,7 +39,7 @@ $phy = bless( { 'ROUTE_NAME' => '"XY"', 'ESCAP_VC_MASK' => '2\'b01', 'DEBUG_EN' => '0', - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'WEIGHTw' => '4', 'SWA_ARBITER_TYPE' => '"RRA"', 'MIN_PCK_SIZE' => '2', @@ -198,7 +198,7 @@ $phy = bless( { 'SMART_MAX' => '0', 'Fpay' => '32', 'CAST_TYPE' => '"UNICAST"', - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'WEIGHTw' => '4', 'DEBUG_EN' => '0', 'ESCAP_VC_MASK' => '2\'b01', @@ -234,7 +234,7 @@ $phy = bless( { 'SMART_MAX' => '0', 'DEBUG_EN' => '0', 'WEIGHTw' => '4', - 'SELF_LOOP_EN' => '"NO"', + 'SELF_LOOP_EN' => '0', 'AVC_ATOMIC_EN' => 0, 'VC_REALLOCATION_TYPE' => '"NONATOMIC"', 'ROUTE_NAME' => '"XY"', diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index 5e75a24..c87e64d 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -1052,8 +1052,8 @@ sub noc_config{ $label='Self loop enable'; $param='SELF_LOOP_EN'; - $default='"NO"'; - $content='"NO","YES"'; + $default='0'; + $content='0,1'; $type='Combo-box'; $info="Allows a router input port to send packets to its own output port, enabling self-communication for tiles."; diff --git a/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC b/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC index d2cc171..0c9f513 100644 --- a/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC +++ b/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC @@ -1520,7 +1520,7 @@ For XILINX FPGAs define it as "XILINX_JTAG_WB". In this case, the UART uses BSCA 'value' => '"XY"' }, 'SELF_LOOP_EN' => { - 'value' => '"NO"' + 'value' => '0' }, 'RAw' => { 'value' => '16' diff --git a/mpsoc/rtl/arch/baseline.v b/mpsoc/rtl/arch/baseline.v index ab55b93..2afb3a2 100755 --- a/mpsoc/rtl/arch/baseline.v +++ b/mpsoc/rtl/arch/baseline.v @@ -35,7 +35,7 @@ module baseline_allocator #( parameter TREE_ARBITER_EN = 0, parameter DEBUG_EN = 1, parameter SWA_ARBITER_TYPE = "WRRA", - parameter SELF_LOOP_EN= "NO" + parameter SELF_LOOP_EN= 0 ) ( dest_port_all, @@ -62,11 +62,11 @@ module baseline_allocator #( localparam PV = V * P, PVV = PV * V, - P_1 = (SELF_LOOP_EN == "NO") ? P-1 : P, + P_1 = (SELF_LOOP_EN) ? P : P-1, PP_1 = P_1 * P, - PVP_1 = PV * P_1; - - input [PVP_1-1: 0] dest_port_all; + PVP_1 = PV * P_1; + + input [PVP_1-1: 0] dest_port_all; input [PV-1: 0] ovc_is_assigned_all; input [PV-1: 0] ivc_request_all; input [PV-1: 0] assigned_ovc_not_full_all; diff --git a/mpsoc/rtl/src_modelsim/traffic_pattern.sv b/mpsoc/rtl/src_modelsim/traffic_pattern.sv index 804fe73..9cde94d 100755 --- a/mpsoc/rtl/src_modelsim/traffic_pattern.sv +++ b/mpsoc/rtl/src_modelsim/traffic_pattern.sv @@ -1,60 +1,51 @@ /************************************** * Module: traffic_pattern -* Date:2015-10-05 -* Author: alireza +* Date:2015-10-05 +* Author: alireza * * Description: ***************************************/ `include "pronoc_def.v" - - /************************************ - - pck_class_in_gen - +* pck_class_in_gen ***********************************/ - + module pck_class_in_gen #( parameter C = 4, // number of packet class parameter C0_p = 25, // the percentage of injected packets with class 0 parameter C1_p = 25, parameter C2_p = 25, - parameter C3_p = 25 + parameter C3_p = 25 )( pck_class_o, - en, + en, reset, clk - ); - + function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21)? log2(C) : 1, RNDw = log2(100); - + output reg [Cw-1 : 0] pck_class_o; - input reset,clk,en; - reg [RNDw-1 : 0] rnd; - - - - // generate a random num between 0 to 99 + input reset,clk,en; + reg [RNDw-1 : 0] rnd; + // generate a random num between 0 to 99 always @(posedge clk ) begin - if(en | `pronoc_reset) begin - rnd = $urandom_range(99,0); - end + if(en | `pronoc_reset) begin + rnd = $urandom_range(99,0); + end end always @(*) begin @@ -63,29 +54,22 @@ module pck_class_in_gen #( else if ( rnd < (C0_p+C1_p+C2_p)) pck_class_o =2; else pck_class_o =3; end - - - endmodule /********************************** - - pck_dst_gen - +* pck_dst_gen *********************************/ -module pck_dst_gen - #( +module pck_dst_gen #( parameter NOC_ID=0, - parameter TRAFFIC = "RANDOM", + parameter TRAFFIC = "RANDOM", parameter HOTSPOT_NODE_NUM = 4, parameter MCAST_TRAFFIC_RATIO =50, parameter MCAST_PCK_SIZ_MIN = 2, parameter MCAST_PCK_SIZ_MAX = 4, parameter MIN_PACKET_SIZE=5, parameter MAX_PACKET_SIZE=5, - parameter PCK_SIZ_SEL="random-discrete", + parameter PCK_SIZ_SEL="random-discrete", parameter DISCRETE_PCK_SIZ_NUM=1 - )( en, current_e_addr, @@ -100,19 +84,13 @@ module pck_dst_gen custom_traffic_en, pck_size_o, rnd_discrete - - ); - `NOC_CONF - - localparam ADDR_DIMENSION = (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") ? 2 : 1; // "RING" and FULLY_CONNECT - - - - - localparam PCK_CNTw = log2(MAX_PCK_NUM+1), - HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; + localparam ADDR_DIMENSION = (IS_MESH | IS_TORUS) ? 2 : 1; // "RING" and FULLY_CONNECT + + localparam + PCK_CNTw = log2(MAX_PCK_NUM+1), + HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; input reset,clk,en; input [NEw-1 : 0] core_num; @@ -122,172 +100,158 @@ module pck_dst_gen output valid_dst; input [NEw-1 : 0] custom_traffic_t; input custom_traffic_en; - output [PCK_SIZw-1:0] pck_size_o; input rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1: 0]; input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; - - - wire [EAw-1 : 0] unicast_dest_e_addr; - wire [PCK_SIZw-1 : 0] pck_size_uni; - - pck_dst_gen_unicast #( - .NOC_ID(NOC_ID), - .TRAFFIC(TRAFFIC), - .HOTSPOT_NODE_NUM(HOTSPOT_NODE_NUM) - ) - unicast - ( - .en (en ), - .current_e_addr (current_e_addr ), - .core_num (core_num ), - .pck_number (pck_number ), - .dest_e_addr (unicast_dest_e_addr), - .clk (clk ), - .reset (reset ), - .valid_dst (valid_dst ), - .hotspot_info (hotspot_info ), - .custom_traffic_t (custom_traffic_t), - .custom_traffic_en(custom_traffic_en) - ); - - pck_size_gen #( - .NOC_ID(NOC_ID), - .MIN(MIN_PACKET_SIZE), - .MAX(MAX_PACKET_SIZE), - .PCK_SIZ_SEL(PCK_SIZ_SEL), - .DISCRETE_PCK_SIZ_NUM(DISCRETE_PCK_SIZ_NUM) - ) - unicast_pck_size - ( - .reset(reset), - .clk(clk), - .en(en), - .pck_size(pck_size_uni) , - .rnd_discrete(rnd_discrete) - ); - - - generate - if(CAST_TYPE == "UNICAST") begin :uni - assign dest_e_addr = unicast_dest_e_addr; - assign pck_size_o = pck_size_uni; - end else begin :multi - reg [DAw-1 : 0] multicast_dest_e_addr,temp; - reg [6: 0] rnd_reg; - wire [PCK_SIZw-1 : 0] pck_size_mcast; - reg [PCK_SIZw-1 : 0] pck_siz_tmp; - wire [NEw-1 : 0] unicast_id_num; - - - endp_addr_decoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - ) enc ( - .code(unicast_dest_e_addr), - .id(unicast_id_num) - ); - - - pck_size_gen #( - .NOC_ID(NOC_ID), - .MIN(MCAST_PCK_SIZ_MIN), - .MAX(MCAST_PCK_SIZ_MAX), - .PCK_SIZ_SEL("random-range"), - .DISCRETE_PCK_SIZ_NUM(DISCRETE_PCK_SIZ_NUM) - ) mcast_pck_size ( - .reset(reset), - .clk(clk), - .en(en), - .pck_size(pck_size_mcast) , - .rnd_discrete(rnd_discrete) - ); - - always @(posedge clk ) begin - if(en | reset) begin - rnd_reg <= $urandom_range(99,0); - end - end - - if(CAST_TYPE == "MULTICAST_FULL") begin :mful - - always @( * ) begin - multicast_dest_e_addr = {DAw{1'b0}}; - temp={DAw{1'b0}}; - temp[unicast_id_num]=1'b1; - pck_siz_tmp= pck_size_uni; - if(rnd_reg >= MCAST_TRAFFIC_RATIO) begin - multicast_dest_e_addr[unicast_id_num]=1'b1; - end - else begin - multicast_dest_e_addr = $urandom(); - pck_siz_tmp=pck_size_mcast; - end - if(SELF_LOOP_EN == "NO") multicast_dest_e_addr[core_num]=1'b0; - end - - - - assign dest_e_addr = (multicast_dest_e_addr=={DAw{1'b0}} )? temp : multicast_dest_e_addr ; - assign pck_size_o = pck_siz_tmp; - - end else if(CAST_TYPE == "MULTICAST_PARTIAL") begin :mpar - - always @( * ) begin - multicast_dest_e_addr = {DAw{1'b0}}; - temp={unicast_dest_e_addr,1'b1}; - pck_siz_tmp= pck_size_uni; - if(rnd_reg >= MCAST_TRAFFIC_RATIO) begin - multicast_dest_e_addr = {unicast_dest_e_addr,1'b1}; - end - else begin - multicast_dest_e_addr = $urandom(); - multicast_dest_e_addr[0] =1'b0; - pck_siz_tmp=pck_size_mcast; - if(SELF_LOOP_EN == "NO") begin - if(MCAST_ENDP_LIST[core_num]==1'b1) multicast_dest_e_addr[endp_id_to_mcast_id(core_num)+1]=1'b0; - end - end - end - - assign dest_e_addr = (multicast_dest_e_addr=={DAw{1'b0}} )? temp : multicast_dest_e_addr ; - assign pck_size_o = pck_siz_tmp; - - - - end else begin //Broadcast - - always @( * ) begin - multicast_dest_e_addr = {DAw{1'b0}}; - pck_siz_tmp = pck_size_uni; - if(rnd_reg >= MCAST_TRAFFIC_RATIO) begin - multicast_dest_e_addr = {unicast_dest_e_addr,1'b1}; - end - else begin - pck_siz_tmp=pck_size_mcast; - end - end - assign dest_e_addr = multicast_dest_e_addr ; - assign pck_size_o = pck_siz_tmp; - - - end - - end endgenerate - + wire [EAw-1 : 0] unicast_dest_e_addr; + wire [PCK_SIZw-1 : 0] pck_size_uni; + + pck_dst_gen_unicast #( + .NOC_ID(NOC_ID), + .TRAFFIC(TRAFFIC), + .HOTSPOT_NODE_NUM(HOTSPOT_NODE_NUM) + ) unicast ( + .en (en ), + .current_e_addr (current_e_addr ), + .core_num (core_num ), + .pck_number (pck_number ), + .dest_e_addr (unicast_dest_e_addr), + .clk (clk ), + .reset (reset ), + .valid_dst (valid_dst ), + .hotspot_info (hotspot_info ), + .custom_traffic_t (custom_traffic_t), + .custom_traffic_en(custom_traffic_en) + ); + + pck_size_gen #( + .NOC_ID(NOC_ID), + .MIN(MIN_PACKET_SIZE), + .MAX(MAX_PACKET_SIZE), + .PCK_SIZ_SEL(PCK_SIZ_SEL), + .DISCRETE_PCK_SIZ_NUM(DISCRETE_PCK_SIZ_NUM) + ) unicast_pck_size ( + .reset(reset), + .clk(clk), + .en(en), + .pck_size(pck_size_uni) , + .rnd_discrete(rnd_discrete) + ); + + generate + if(CAST_TYPE == "UNICAST") begin :uni + assign dest_e_addr = unicast_dest_e_addr; + assign pck_size_o = pck_size_uni; + end else begin :multi + reg [DAw-1 : 0] multicast_dest_e_addr,temp; + reg [6: 0] rnd_reg; + wire [PCK_SIZw-1 : 0] pck_size_mcast; + reg [PCK_SIZw-1 : 0] pck_siz_tmp; + wire [NEw-1 : 0] unicast_id_num; + + endp_addr_decoder #( + .T1(T1), + .T2(T2), + .T3(T3), + .NE(NE), + .EAw(EAw), + .TOPOLOGY(TOPOLOGY) + ) enc ( + .code(unicast_dest_e_addr), + .id(unicast_id_num) + ); + + pck_size_gen #( + .NOC_ID(NOC_ID), + .MIN(MCAST_PCK_SIZ_MIN), + .MAX(MCAST_PCK_SIZ_MAX), + .PCK_SIZ_SEL("random-range"), + .DISCRETE_PCK_SIZ_NUM(DISCRETE_PCK_SIZ_NUM) + ) mcast_pck_size ( + .reset(reset), + .clk(clk), + .en(en), + .pck_size(pck_size_mcast) , + .rnd_discrete(rnd_discrete) + ); + + always @(posedge clk ) begin + if(en | reset) begin + rnd_reg <= $urandom_range(99,0); + end + end + + if(CAST_TYPE == "MULTICAST_FULL") begin :mful + + always @( * ) begin + multicast_dest_e_addr = {DAw{1'b0}}; + temp={DAw{1'b0}}; + temp[unicast_id_num]=1'b1; + pck_siz_tmp= pck_size_uni; + if(rnd_reg >= MCAST_TRAFFIC_RATIO) begin + multicast_dest_e_addr[unicast_id_num]=1'b1; + end + else begin + multicast_dest_e_addr = $urandom(); + pck_siz_tmp=pck_size_mcast; + end + if(SELF_LOOP_EN == 0) multicast_dest_e_addr[core_num]=1'b0; + end + + assign dest_e_addr = (multicast_dest_e_addr=={DAw{1'b0}} )? temp : multicast_dest_e_addr ; + assign pck_size_o = pck_siz_tmp; + + end else if(CAST_TYPE == "MULTICAST_PARTIAL") begin :mpar + + always @( * ) begin + multicast_dest_e_addr = {DAw{1'b0}}; + temp={unicast_dest_e_addr,1'b1}; + pck_siz_tmp= pck_size_uni; + if(rnd_reg >= MCAST_TRAFFIC_RATIO) begin + multicast_dest_e_addr = {unicast_dest_e_addr,1'b1}; + end + else begin + multicast_dest_e_addr = $urandom(); + multicast_dest_e_addr[0] =1'b0; + pck_siz_tmp=pck_size_mcast; + if(SELF_LOOP_EN == 0) begin + if(MCAST_ENDP_LIST[core_num]==1'b1) multicast_dest_e_addr[endp_id_to_mcast_id(core_num)+1]=1'b0; + end + end + end + + assign dest_e_addr = (multicast_dest_e_addr=={DAw{1'b0}} )? temp : multicast_dest_e_addr ; + assign pck_size_o = pck_siz_tmp; + + end else begin //Broadcast + + always @( * ) begin + multicast_dest_e_addr = {DAw{1'b0}}; + pck_siz_tmp = pck_size_uni; + if(rnd_reg >= MCAST_TRAFFIC_RATIO) begin + multicast_dest_e_addr = {unicast_dest_e_addr,1'b1}; + end + else begin + pck_siz_tmp=pck_size_mcast; + end + end + assign dest_e_addr = multicast_dest_e_addr ; + assign pck_size_o = pck_siz_tmp; + + + end + end endgenerate endmodule - - + +/********************************** +* pck_dst_gen_unicast +*********************************/ module pck_dst_gen_unicast #( parameter NOC_ID=0, - parameter TRAFFIC = "RANDOM", + parameter TRAFFIC = "RANDOM", parameter HOTSPOT_NODE_NUM = 4 )( en, @@ -299,16 +263,14 @@ module pck_dst_gen_unicast reset, valid_dst, hotspot_info, - custom_traffic_t, - custom_traffic_en + custom_traffic_t, + custom_traffic_en ); - `NOC_CONF - localparam ADDR_DIMENSION = (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") ? 2 : 1; // "RING" and FULLY_CONNECT - - - localparam PCK_CNTw = log2(MAX_PCK_NUM+1), - HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; + localparam + ADDR_DIMENSION = (IS_MESH | IS_TORUS) ? 2 : 1; // "RING" and FULLY_CONNECT + PCK_CNTw = log2(MAX_PCK_NUM+1), + HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; input reset,clk,en; input [NEw-1 : 0] core_num; @@ -316,45 +278,34 @@ module pck_dst_gen_unicast input [EAw-1 : 0] current_e_addr; output [EAw-1 : 0] dest_e_addr; output valid_dst; - input [NEw-1 : 0] custom_traffic_t; - input custom_traffic_en; - + input [NEw-1 : 0] custom_traffic_t; + input custom_traffic_en; input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; - - generate if ( ADDR_DIMENSION == 2) begin :two_dim - two_dimension_pck_dst_gen #( - .NOC_ID(NOC_ID), - .TRAFFIC(TRAFFIC), - .HOTSPOT_NODE_NUM(HOTSPOT_NODE_NUM) - - ) - the_two_dimension_pck_dst_gen - ( - .reset(reset), - .clk(clk), - .en(en), - .core_num(core_num), - .pck_number(pck_number), - .current_e_addr(current_e_addr), + .NOC_ID(NOC_ID), + .TRAFFIC(TRAFFIC), + .HOTSPOT_NODE_NUM(HOTSPOT_NODE_NUM) + ) the_two_dimension_pck_dst_gen ( + .reset(reset), + .clk(clk), + .en(en), + .core_num(core_num), + .pck_number(pck_number), + .current_e_addr(current_e_addr), .dest_e_addr(dest_e_addr), - .valid_dst(valid_dst), - .hotspot_info(hotspot_info), - .custom_traffic_t(custom_traffic_t), - .custom_traffic_en(custom_traffic_en) + .valid_dst(valid_dst), + .hotspot_info(hotspot_info), + .custom_traffic_t(custom_traffic_t), + .custom_traffic_en(custom_traffic_en) ); - end else begin : one_dim - one_dimension_pck_dst_gen #( - .NOC_ID(NOC_ID), - .TRAFFIC(TRAFFIC), - .HOTSPOT_NODE_NUM(HOTSPOT_NODE_NUM) - ) - the_one_dimension_pck_dst_gen - ( + .NOC_ID(NOC_ID), + .TRAFFIC(TRAFFIC), + .HOTSPOT_NODE_NUM(HOTSPOT_NODE_NUM) + ) the_one_dimension_pck_dst_gen ( .reset(reset), .clk(clk), .en(en), @@ -364,23 +315,21 @@ module pck_dst_gen_unicast .dest_e_addr(dest_e_addr), .valid_dst(valid_dst), .hotspot_info(hotspot_info), - .custom_traffic_t(custom_traffic_t), - .custom_traffic_en(custom_traffic_en) - ); - - end + .custom_traffic_t(custom_traffic_t), + .custom_traffic_en(custom_traffic_en) + ); + end endgenerate endmodule - - - - + +/********************************** +* two_dimension_pck_dst_gen +**********************************/ module two_dimension_pck_dst_gen #( parameter NOC_ID=0, - parameter TRAFFIC = "RANDOM", + parameter TRAFFIC = "RANDOM", parameter HOTSPOT_NODE_NUM = 4 - )( en, current_e_addr, @@ -393,105 +342,84 @@ module two_dimension_pck_dst_gen hotspot_info, custom_traffic_t, custom_traffic_en -); - +); `NOC_CONF - - - - - localparam PCK_CNTw = log2(MAX_PCK_NUM+1), - HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; + localparam + PCK_CNTw = log2(MAX_PCK_NUM+1), + HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; input reset,clk,en; input [NEw-1 : 0] core_num; input [PCK_CNTw-1 : 0] pck_number; input [EAw-1 : 0] current_e_addr; output [EAw-1 : 0] dest_e_addr; - output valid_dst; + output valid_dst; input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; - input [NEw-1 : 0] custom_traffic_t; - input custom_traffic_en; - - + input [NEw-1 : 0] custom_traffic_t; + input custom_traffic_en; - wire [NXw-1 : 0] current_x; - wire [NYw-1 : 0] current_y; - wire [NLw-1 : 0] current_l; - wire [NXw-1 : 0] dest_x; + wire [NXw-1 : 0] current_x; + wire [NYw-1 : 0] current_y; + wire [NLw-1 : 0] current_l; + wire [NXw-1 : 0] dest_x; wire [NYw-1 : 0] dest_y; - wire [NLw-1 : 0] dest_l; - - mesh_tori_endp_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) - src_addr_decode - ( - .e_addr(current_e_addr), - .ex(current_x), - .ey(current_y), - .el(current_l), - .valid( ) - ); + wire [NLw-1 : 0] dest_l; + mesh_tori_endp_addr_decode #( + .TOPOLOGY(TOPOLOGY), + .T1(T1), + .T2(T2), + .T3(T3), + .EAw(EAw) + ) src_addr_decode ( + .e_addr(current_e_addr), + .ex(current_x), + .ey(current_y), + .el(current_l), + .valid( ) + ); wire off_flag; - - - - - wire [NEw-1 : 0] dest_ip_num; genvar i; - - generate + + generate if (TRAFFIC == "RANDOM") begin + logic [6 : 0] rnd_reg; + always @(posedge clk ) begin + if(en | `pronoc_reset) begin + rnd_reg = $urandom_range(NE-1,0); + if(SELF_LOOP_EN == 0) while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core + + end + end + assign dest_ip_num = rnd_reg; + endp_addr_encoder #( + .T1(T1), + .T2(T2), + .T3(T3), + .NE(NE), + .EAw(EAw), + .TOPOLOGY(TOPOLOGY) + ) addr_encoder ( + .id(dest_ip_num), + .code(dest_e_addr) + ); - logic [6 : 0] rnd_reg; - - always @(posedge clk ) begin - if(en | `pronoc_reset) begin - rnd_reg = $urandom_range(NE-1,0); - if(SELF_LOOP_EN == "NO") while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core - - end - end - assign dest_ip_num = rnd_reg; - - endp_addr_encoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - ) - addr_encoder - ( - .id(dest_ip_num), - .code(dest_e_addr) - ); - - end else if (TRAFFIC == "HOTSPOT") begin - - hot_spot_dest_gen #( - .NOC_ID(NOC_ID), - .HOTSPOT_NUM(HOTSPOT_NUM), - .NE(NE), - .NEw(NEw) - ) hspot ( - .reset(reset), - .clk(clk), - .en(en), - .hotspot_info(hotspot_info), - .dest_ip_num (dest_ip_num), - .core_num(core_num), - .off_flag(off_flag) - ); - + end else if (TRAFFIC == "HOTSPOT") begin + hot_spot_dest_gen #( + .NOC_ID(NOC_ID), + .HOTSPOT_NUM(HOTSPOT_NUM), + .NE(NE), + .NEw(NEw) + ) hspot ( + .reset(reset), + .clk(clk), + .en(en), + .hotspot_info(hotspot_info), + .dest_ip_num (dest_ip_num), + .core_num(core_num), + .off_flag(off_flag) + ); endp_addr_encoder #( .T1(T1), .T2(T2), @@ -503,61 +431,47 @@ module two_dimension_pck_dst_gen .id(dest_ip_num), .code(dest_e_addr) ); - - end else if( TRAFFIC == "TRANSPOSE1") begin - assign dest_x = NX-current_y-1; assign dest_y = NY-current_x-1; assign dest_l = NL-current_l-1; assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; endp_addr_decoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) + .T1(T1), + .T2(T2), + .T3(T3), + .NE(NE), + .EAw(EAw), + .TOPOLOGY(TOPOLOGY) )enc ( - .code(dest_e_addr), - .id(dest_ip_num) - ); - - - - - + .code(dest_e_addr), + .id(dest_ip_num) + ); end else if( TRAFFIC == "TRANSPOSE2") begin :transpose2 - assign dest_x = current_y; assign dest_y = current_x; assign dest_l = current_l; assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - endp_addr_decoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - )enc - ( - .code(dest_e_addr), - .id(dest_ip_num) - ); - - - + .T1(T1), + .T2(T2), + .T3(T3), + .NE(NE), + .EAw(EAw), + .TOPOLOGY(TOPOLOGY) + )enc ( + .code(dest_e_addr), + .id(dest_ip_num) + ); end else if( TRAFFIC == "BIT_REVERSE") begin :bitreverse for(i=0; i<(EAw); i=i+1'b1) begin :lp//reverse the address assign dest_ip_num[i] = current_e_addr [((EAw)-1)-i]; end - + endp_addr_encoder #( .T1(T1), .T2(T2), @@ -565,176 +479,136 @@ module two_dimension_pck_dst_gen .NE(NE), .EAw(EAw), .TOPOLOGY(TOPOLOGY) - ) - addr_encoder( + ) addr_encoder( .id(dest_ip_num), .code(dest_e_addr) - ); - - + ); + end else if( TRAFFIC == "BIT_COMPLEMENT") begin :bitcomp - assign dest_x = ~current_x; assign dest_y = ~current_y; assign dest_l = ~dest_l; assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - endp_addr_decoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - )enc - ( - .code(dest_e_addr), - .id(dest_ip_num) - ); - - - - + .T1(T1), + .T2(T2), + .T3(T3), + .NE(NE), + .EAw(EAw), + .TOPOLOGY(TOPOLOGY) + ) enc ( + .code(dest_e_addr), + .id(dest_ip_num) + ); end else if( TRAFFIC == "TORNADO" ) begin :tornado //[(x+(k/2-1)) mod k, (y+(k/2-1)) mod k], assign dest_x = (current_x> ((NX+1)/2))? current_x- ((NX+1)/2) -1 : (NX/2)+current_x-1; // = ((current_x + ((NX/2)-1))%NX); assign dest_y = (current_y> ((NY+1)/2))? current_y- ((NY+1)/2) -1 : (NY/2)+current_y-1; // = ((current_y + ((NY/2)-1))%NY); assign dest_l = current_l; assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - - endp_addr_decoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - )enc - ( - .code(dest_e_addr), - .id(dest_ip_num) - ); - - - - end else if( TRAFFIC == "NEIGHBOR") begin :neighbor - //dx = sx + 1 mod k - assign dest_x = (current_x + 1) >= NX? 0 : (current_x + 1); - assign dest_y = (current_y + 1) >= NY? 0 : (current_y + 1); - assign dest_l = current_l; - assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - - endp_addr_decoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - )enc - ( - .code(dest_e_addr), - .id(dest_ip_num) - ); - - - - - end else if( TRAFFIC == "SHUFFLE") begin: shuffle - //di = si−1 mod b - for(i=1; i<(EAw); i=i+1'b1) begin :lp//reverse the address + endp_addr_decoder #( + .T1(T1), + .T2(T2), + .T3(T3), + .NE(NE), + .EAw(EAw), + .TOPOLOGY(TOPOLOGY) + ) enc ( + .code(dest_e_addr), + .id(dest_ip_num) + ); + end else if( TRAFFIC == "NEIGHBOR") begin :neighbor + //dx = sx + 1 mod k + assign dest_x = (current_x + 1) >= NX? 0 : (current_x + 1); + assign dest_y = (current_y + 1) >= NY? 0 : (current_y + 1); + assign dest_l = current_l; + assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; + endp_addr_decoder #( + .T1(T1), + .T2(T2), + .T3(T3), + .NE(NE), + .EAw(EAw), + .TOPOLOGY(TOPOLOGY) + )enc( + .code(dest_e_addr), + .id(dest_ip_num) + ); + end else if( TRAFFIC == "SHUFFLE") begin: shuffle + //di = si−1 mod b + for(i=1; i<(EAw); i=i+1'b1) begin :lp//reverse the address assign dest_ip_num[i] = current_e_addr [i-1]; end - assign dest_ip_num[0] = current_e_addr [EAw-1]; - endp_addr_encoder #( + assign dest_ip_num[0] = current_e_addr [EAw-1]; + endp_addr_encoder #( .T1(T1), .T2(T2), .T3(T3), .NE(NE), .EAw(EAw), .TOPOLOGY(TOPOLOGY) - ) - addr_encoder( + ) addr_encoder( .id(dest_ip_num), .code(dest_e_addr) ); - - end else if(TRAFFIC == "BIT_ROTATION") begin :bitrot - //di = si+1 mod b - for(i=0; i<(EAw-1); i=i+1'b1) begin :lp//reverse the address + //di = si+1 mod b + for(i=0; i<(EAw-1); i=i+1'b1) begin :lp//reverse the address assign dest_ip_num[i] = current_e_addr [i+1]; end - assign dest_ip_num[EAw-1] = current_e_addr [0]; - endp_addr_encoder #( + assign dest_ip_num[EAw-1] = current_e_addr [0]; + endp_addr_encoder #( .T1(T1), .T2(T2), .T3(T3), .NE(NE), .EAw(EAw), .TOPOLOGY(TOPOLOGY) - ) - addr_encoder( + ) addr_encoder( .id(dest_ip_num), .code(dest_e_addr) ); - - end else if(TRAFFIC == "CUSTOM" )begin - + end else if(TRAFFIC == "CUSTOM" )begin + assign dest_ip_num = custom_traffic_t; - endp_addr_encoder #( + endp_addr_encoder #( .T1(T1), .T2(T2), .T3(T3), .NE(NE), .EAw(EAw), .TOPOLOGY(TOPOLOGY) - ) - addr_encoder - ( + ) addr_encoder ( .id(dest_ip_num), .code(dest_e_addr) ); - - assign off_flag = ~custom_traffic_en; - - + assign off_flag = ~custom_traffic_en; + end else begin - initial begin - $display("ERROR: Undefined Traffic pattern:%s",TRAFFIC); - $stop; - end - end - - - - wire valid_temp = (dest_ip_num <= (NE-1)); - - if (TRAFFIC == "HOTSPOT" || TRAFFIC == "CUSTOM") begin - assign valid_dst = ~off_flag & valid_temp; - end else begin - assign valid_dst = valid_temp; - end - - + initial begin + $display("ERROR: Undefined Traffic pattern:%s",TRAFFIC); + $stop; + end + end + + wire valid_temp = (dest_ip_num <= (NE-1)); + + if (TRAFFIC == "HOTSPOT" || TRAFFIC == "CUSTOM") begin + assign valid_dst = ~off_flag & valid_temp; + end else begin + assign valid_dst = valid_temp; + end endgenerate - endmodule - - -/************ - +/************ +* ************/ - - -module one_dimension_pck_dst_gen -#( - parameter NOC_ID=0, - parameter TRAFFIC = "RANDOM", - parameter HOTSPOT_NODE_NUM = 4 - +module one_dimension_pck_dst_gen #( + parameter NOC_ID=0, + parameter TRAFFIC = "RANDOM", + parameter HOTSPOT_NODE_NUM = 4 )( en, core_num, @@ -748,10 +622,7 @@ module one_dimension_pck_dst_gen custom_traffic_t, custom_traffic_en ); - `NOC_CONF - - localparam PCK_CNTw = log2(MAX_PCK_NUM+1), HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; @@ -763,83 +634,68 @@ module one_dimension_pck_dst_gen output [EAw-1 : 0] dest_e_addr; output valid_dst; input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; - input [NEw-1 : 0] custom_traffic_t; - input custom_traffic_en; + input [NEw-1 : 0] custom_traffic_t; + input custom_traffic_en; wire [NEw-1 : 0] dest_ip_num; wire off_flag; genvar i; generate if (TRAFFIC == "RANDOM") begin - logic [6 : 0] rnd_reg; - - always @(posedge clk ) begin - if(en | `pronoc_reset) begin - rnd_reg = $urandom_range(NE-1,0); - if(SELF_LOOP_EN == "NO") while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core - end - end - assign dest_ip_num = rnd_reg; - - - end else if (TRAFFIC == "HOTSPOT") begin - - hot_spot_dest_gen #( - .NOC_ID(NOC_ID), - .HOTSPOT_NUM(HOTSPOT_NUM), - .NE(NE), - .NEw(NEw) - ) hspot ( - .clk(clk), - .en(en), - .hotspot_info(hotspot_info), - .dest_ip_num (dest_ip_num), - .core_num(core_num), - .off_flag(off_flag) - ); - - + logic [6 : 0] rnd_reg; + always @(posedge clk ) begin + if(en | `pronoc_reset) begin + rnd_reg = $urandom_range(NE-1,0); + if(SELF_LOOP_EN == 0) while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core + end + end + assign dest_ip_num = rnd_reg; + end else if (TRAFFIC == "HOTSPOT") begin + hot_spot_dest_gen #( + .NOC_ID(NOC_ID), + .HOTSPOT_NUM(HOTSPOT_NUM), + .NE(NE), + .NEw(NEw) + ) hspot ( + .clk(clk), + .en(en), + .hotspot_info(hotspot_info), + .dest_ip_num (dest_ip_num), + .core_num(core_num), + .off_flag(off_flag) + ); end else if( TRAFFIC == "TRANSPOSE1") begin :tran1 - assign dest_ip_num = NE-core_num-1; - end else if( TRAFFIC == "BIT_REVERSE") begin :bitreverse - for(i=0; i ((NE+1)/2))? core_num- ((NE+1)/2) -1 : (NE/2)+core_num-1; // = ((current_x + ((NX/2)-1))%NX); - - end else if( TRAFFIC == "NEIGHBOR") begin :neighbor - //dx = sx + 1 mod k - assign dest_ip_num = ((core_num + 1) >= NE) ? 0 : (core_num + 1); - - end else if( TRAFFIC == "SHUFFLE") begin: shuffle - //di = si−1 mod b - for(i=1; i<(NEw); i=i+1'b1) begin :lp + assign dest_ip_num = (core_num > ((NE+1)/2))? core_num- ((NE+1)/2) -1 : (NE/2)+core_num-1; // = ((current_x + ((NX/2)-1))%NX); + end else if( TRAFFIC == "NEIGHBOR") begin :neighbor + //dx = sx + 1 mod k + assign dest_ip_num = ((core_num + 1) >= NE) ? 0 : (core_num + 1); + + end else if( TRAFFIC == "SHUFFLE") begin: shuffle + //di = si−1 mod b + for(i=1; i<(NEw); i=i+1'b1) begin :lp assign dest_ip_num[i] = core_num [i-1]; end - assign dest_ip_num[0] = core_num [NEw-1]; - + assign dest_ip_num[0] = core_num [NEw-1]; end else if(TRAFFIC == "BIT_ROTATION") begin :bitrot - //di = si+1 mod b - for(i=0; i<(NEw-1); i=i+1) begin :lp//reverse the address + //di = si+1 mod b + for(i=0; i<(NEw-1); i=i+1) begin :lp//reverse the address assign dest_ip_num[i] = core_num [i+1]; end - assign dest_ip_num[NEw-1] = core_num [0]; - - end else if(TRAFFIC == "CUSTOM" )begin - assign off_flag = ~custom_traffic_en; - assign dest_ip_num = custom_traffic_t; - end - + assign dest_ip_num[NEw-1] = core_num [0]; + end else if(TRAFFIC == "CUSTOM" )begin + assign off_flag = ~custom_traffic_en; + assign dest_ip_num = custom_traffic_t; + end + endp_addr_encoder #( .T1(T1), .T2(T2), @@ -847,164 +703,142 @@ module one_dimension_pck_dst_gen .NE(NE), .EAw(EAw), .TOPOLOGY(TOPOLOGY) - ) - addr_encoder - ( + ) addr_encoder ( .id(dest_ip_num), .code(dest_e_addr) ); - - wire valid_temp = (dest_ip_num <= (NE-1)); - + + wire valid_temp = (dest_ip_num <= (NE-1)); if (TRAFFIC == "HOTSPOT" || TRAFFIC == "CUSTOM") begin - assign valid_dst = ~off_flag & valid_temp; + assign valid_dst = ~off_flag & valid_temp; end else begin - assign valid_dst = valid_temp; + assign valid_dst = valid_temp; end - endgenerate - + endmodule - + /*************************** * pck_size_gen * *************************/ - module pck_size_gen #( parameter NOC_ID=0, - parameter MIN = 2, + parameter MIN = 2, parameter MAX = 5, - parameter PCK_SIZ_SEL="random-discrete", + parameter PCK_SIZ_SEL="random-discrete", parameter DISCRETE_PCK_SIZ_NUM=1 -) -( +)( reset, clk, en, pck_size, rnd_discrete ); - - `NOC_CONF - - input rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1: 0]; - - + `NOC_CONF + input rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1: 0]; input reset, clk, en; output [PCK_SIZw-1 : 0] pck_size; - generate - if(PCK_SIZ_SEL == "random-discrete" ) begin :discrete - if(DISCRETE_PCK_SIZ_NUM==1) begin :single - assign pck_size = rnd_discrete[0].value; - end else begin :multi - reg [PCK_SIZw-1 : 0] rnd,rnd_next; - integer rnd2; - integer k; - always @(*) begin - rnd_next = rnd; - if(en) begin - if(rnd2 < rnd_discrete[0].percentage) rnd_next = rnd_discrete[0].value; - for (k=1;k= rnd_discrete[k-1].percentage && rnd2 < rnd_discrete[k].percentage) rnd_next = rnd_discrete[k].value; - end - end - end//always - - - always @(posedge clk) begin - if(`pronoc_reset) begin - rnd2<= 0; - rnd <= rnd_discrete[0].value; - end else begin - if(en) rnd2<= $urandom_range(99,0); - rnd <= rnd_next; - end - end//always - - assign pck_size = rnd; - end//multi - - end else begin :range - if (MIN == MAX) begin :eq - assign pck_size = MIN; - end else begin :noteq - reg [PCK_SIZw-1 : 0] rnd; - always @(posedge clk) begin - if(`pronoc_reset) rnd = MIN; - else if(en) rnd = $urandom_range(MAX,MIN); - end - assign pck_size = rnd; - end - end - endgenerate + if(PCK_SIZ_SEL == "random-discrete" ) begin :discrete + if(DISCRETE_PCK_SIZ_NUM==1) begin :single + assign pck_size = rnd_discrete[0].value; + end else begin :multi + reg [PCK_SIZw-1 : 0] rnd,rnd_next; + integer rnd2; + integer k; + always @(*) begin + rnd_next = rnd; + if(en) begin + if(rnd2 < rnd_discrete[0].percentage) rnd_next = rnd_discrete[0].value; + for (k=1;k= rnd_discrete[k-1].percentage && rnd2 < rnd_discrete[k].percentage) rnd_next = rnd_discrete[k].value; + end + end + end//always + + always @(posedge clk) begin + if(`pronoc_reset) begin + rnd2<= 0; + rnd <= rnd_discrete[0].value; + end else begin + if(en) rnd2<= $urandom_range(99,0); + rnd <= rnd_next; + end + end//always + assign pck_size = rnd; + end//multi + end else begin :range + if (MIN == MAX) begin :eq + assign pck_size = MIN; + end else begin :noteq + reg [PCK_SIZw-1 : 0] rnd; + always @(posedge clk) begin + if(`pronoc_reset) rnd = MIN; + else if(en) rnd = $urandom_range(MAX,MIN); + end + assign pck_size = rnd; + end + end + endgenerate endmodule - - +/********************** +* hot_spot_dest_gen +************************/ module hot_spot_dest_gen #( - parameter NOC_ID=0, - parameter HOTSPOT_NUM=2 + parameter NOC_ID=0, + parameter HOTSPOT_NUM=2 ) ( - clk, - reset, - en, - hotspot_info, - core_num, - dest_ip_num, - off_flag + clk, + reset, + en, + hotspot_info, + core_num, + dest_ip_num, + off_flag ); - - `NOC_CONF - - input clk,en,reset; - input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; - input [NEw-1 : 0] core_num; - output [NEw-1 : 0] dest_ip_num; - output reg off_flag; - - logic [6 : 0] rnd_reg, hotspot_node; - reg [9 : 0] rnd1000; - always @(posedge clk ) begin - if(en | `pronoc_reset) begin - rnd_reg = $urandom_range(NE-1,0); - if(SELF_LOOP_EN == "NO") while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core - - rnd1000 = $urandom_range(999,0);// generate a random number between 0 & 1000 - end - end - - logic hotspot_flag; - integer i; - - always @(*)begin - off_flag=0; - for (i=0;i= hotspot_info[i-1].percentage && rnd1000 < hotspot_info[i].percentage && core_num !=hotspot_info[i].ip_num) begin - hotspot_flag=1; - hotspot_node=hotspot_info[i].ip_num; - end - end end - - end - - - assign dest_ip_num = (off_flag)? core_num : (hotspot_flag)? hotspot_node : rnd_reg; - - -endmodule + `NOC_CONF + input clk,en,reset; + input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; + input [NEw-1 : 0] core_num; + output [NEw-1 : 0] dest_ip_num; + output reg off_flag; + + logic [6 : 0] rnd_reg, hotspot_node; + reg [9 : 0] rnd1000; + always @(posedge clk ) begin + if(en | `pronoc_reset) begin + rnd_reg = $urandom_range(NE-1,0); + if(SELF_LOOP_EN == 0) while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core + rnd1000 = $urandom_range(999,0);// generate a random number between 0 & 1000 + end + end + logic hotspot_flag; + integer i; + always @(*)begin + off_flag=0; + for (i=0;i= hotspot_info[i-1].percentage && rnd1000 < hotspot_info[i].percentage && core_num !=hotspot_info[i].ip_num) begin + hotspot_flag=1; + hotspot_node=hotspot_info[i].ip_num; + end + end + end + end + assign dest_ip_num = (off_flag)? core_num : (hotspot_flag)? hotspot_node : rnd_reg; +endmodule diff --git a/mpsoc/rtl/src_noc/comb-spec1.v b/mpsoc/rtl/src_noc/comb-spec1.v index fa834d5..803c602 100755 --- a/mpsoc/rtl/src_noc/comb-spec1.v +++ b/mpsoc/rtl/src_noc/comb-spec1.v @@ -34,7 +34,7 @@ module comb_spec1_allocator #( parameter DEBUG_EN = 1, parameter SWA_ARBITER_TYPE = "WRRA", parameter MIN_PCK_SIZE=2, //minimum packet size in flits. The minimum value is 1. - parameter SELF_LOOP_EN = "NO" + parameter SELF_LOOP_EN = 0 )( dest_port_all, masked_ovc_request_all, @@ -60,8 +60,8 @@ module comb_spec1_allocator #( PV = V * P, VV = V * V, PVV = PV * V, - P_1 = (SELF_LOOP_EN=="NO")? P-1 : P, - VP_1 = V * P_1, + P_1 = (SELF_LOOP_EN )? P : P-1, + VP_1 = V * P_1, PP_1 = P_1 * P, PVP_1 = PV * P_1; diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index 925bf71..4795c17 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -36,7 +36,7 @@ module comb_nonspec_allocator # ( //input dest_port_all, // from input port masked_ovc_request_all, - pck_is_single_flit_all, + pck_is_single_flit_all, //output ovc_allocated_all,//to the output port @@ -60,17 +60,16 @@ module comb_nonspec_allocator # ( clk, reset ); - `NOC_CONF localparam - P_1 = (SELF_LOOP_EN == "NO")? P-1 : P, + P_1 = (SELF_LOOP_EN)? P : P-1, PV = V * P, VV = V * V, - VP_1 = V * P_1, + VP_1 = V * P_1, PP_1 = P_1 * P, PVV = PV * V, - PVP_1 = PV * P_1; + PVP_1 = PV * P_1; input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; input [PVV-1 : 0] masked_ovc_request_all; input [PVP_1-1 : 0] dest_port_all; @@ -215,7 +214,7 @@ module comb_nonspec_allocator # ( for(i=0;i< PV;i=i+1) begin :_PV for(j=0;jj) begin @@ -241,7 +240,7 @@ module comb_nonspec_v2_allocator #( parameter FIRST_ARBITER_EXT_P_EN = 1, parameter SWA_ARBITER_TYPE = "WRRA", parameter MIN_PCK_SIZE=2, //minimum packet size in flits. The minimum value is 1. - parameter SELF_LOOP_EN= "NO" + parameter SELF_LOOP_EN= 0 )( //VC allocator //input @@ -274,13 +273,13 @@ module comb_nonspec_v2_allocator #( reset ); localparam - P_1 = (SELF_LOOP_EN == "NO") ? P-1 :P, + P_1 = (SELF_LOOP_EN) ? P : P-1, PV = V * P, VV = V * V, - VP_1 = V * P_1, + VP_1 = V * P_1, PP_1 = P_1 * P, PVV = PV * V, - PVP_1 = PV * P_1; + PVP_1 = PV * P_1; input [PVV-1 : 0] masked_ovc_request_all; input [PVP_1-1 : 0] dest_port_all; @@ -429,7 +428,7 @@ module nonspec_sw_alloc #( parameter FIRST_ARBITER_EXT_P_EN = 1, parameter SWA_ARBITER_TYPE = "WRRA", parameter MIN_PCK_SIZE=2, //minimum packet size in flits. The minimum value is 1. - parameter SELF_LOOP_EN="NO" + parameter SELF_LOOP_EN=0 )( ivc_granted_all, ivc_request_masked_all, @@ -448,9 +447,9 @@ module nonspec_sw_alloc #( ); localparam - P_1 = (SELF_LOOP_EN== "NO") ? P-1 : P, + P_1 = (SELF_LOOP_EN) ? P : P-1, PV = V * P, - VP_1 = V * P_1, + VP_1 = V * P_1, PP_1 = P_1 * P, PVP_1 = PV * P_1, PP = P*P; @@ -478,15 +477,15 @@ module nonspec_sw_alloc #( wire [PP-1 : 0] single_flit_granted_dst_all; // internal wires - wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and + wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter - wire [P-1 : 0] single_flit_pck_local_grant; - wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer + wire [P-1 : 0] single_flit_pck_local_grant; + wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; wire [P_1-1 : 0] second_arbiter_weight_consumed [P-1 : 0]; wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; - wire [P-1 :0] winner_weight_consumed; + wire [P-1 :0] winner_weight_consumed; genvar i,j; generate @@ -495,8 +494,8 @@ module nonspec_sw_alloc #( //assign in/out to the port based wires //output assign ivc_granted_all [(i+1)*V-1 : i*V] = ivc_granted [i]; - assign granted_dest_port_all [(i+1)*P_1-1 : i*P_1] = granted_dest_port[i]; - assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]= first_arbiter_grant[i]; + assign granted_dest_port_all [(i+1)*P_1-1 : i*P_1] = granted_dest_port[i]; + assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V] = first_arbiter_grant[i]; //input assign ivc_masked[i] = ivc_request_masked_all [(i+1)*V-1 : i*V]; assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; @@ -524,10 +523,10 @@ module nonspec_sw_alloc #( ) mux ( .in (dest_port_ivc [i]), .out (dest_port[i]), - .sel(first_arbiter_grant[i]) + .sel(first_arbiter_grant[i]) ); - if(MIN_PCK_SIZE == 1) begin + if(MIN_PCK_SIZE == 1) begin //single_flit req multiplexer assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; onehot_mux_1D #( @@ -540,8 +539,8 @@ module nonspec_sw_alloc #( ); assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; - - if (SELF_LOOP_EN == "NO") begin + + if (SELF_LOOP_EN == 0) begin add_sw_loc_one_hot #( .P(P), .SW_LOC(i) @@ -560,7 +559,7 @@ module nonspec_sw_alloc #( end //second arbiter input/output generate for(j=0;jj) begin assign mux_in[i][(j+1)*Fw-1 : j*Fw]= flit_in_all[(j+1)*Fw-1 : j*Fw]; @@ -142,7 +142,7 @@ module crossbar #( .sel(mux_sel_bin[i]) ); end//binary - if(SELF_LOOP_EN == "NO") begin : nslp + if(SELF_LOOP_EN == 0) begin : nslp add_sw_loc_one_hot #( .P(P), .SW_LOC(i) diff --git a/mpsoc/rtl/src_noc/debug.v b/mpsoc/rtl/src_noc/debug.v index 53b47db..eb994ec 100644 --- a/mpsoc/rtl/src_noc/debug.v +++ b/mpsoc/rtl/src_noc/debug.v @@ -324,13 +324,13 @@ module check_destination_addr #( parameter T4=2, parameter EAw=2, parameter DAw=2, - parameter SELF_LOOP_EN="NO", + parameter SELF_LOOP_EN=0, parameter CAST_TYPE = "UNICAST", parameter NE=8 )( dest_is_valid, dest_e_addr, - current_e_addr + current_e_addr ); input [DAw-1 : 0] dest_e_addr; @@ -338,21 +338,21 @@ module check_destination_addr #( output dest_is_valid; // general rules /* verilator lint_off WIDTH */ - wire valid_dst = (SELF_LOOP_EN == "NO")? dest_e_addr != current_e_addr : 1'b1; + wire valid_dst = (SELF_LOOP_EN == 0)? dest_e_addr != current_e_addr : 1'b1; /* verilator lint_on WIDTH */ wire valid; generate - if(CAST_TYPE != "UNICAST") begin - wire [NE-1 : 0] dest_mcast_all_endp; + if(CAST_TYPE != "UNICAST") begin + wire [NE-1 : 0] dest_mcast_all_endp; mcast_dest_list_decode #( - .NOC_ID(NOC_ID) + .NOC_ID(NOC_ID) ) decode ( .dest_e_addr(dest_e_addr), .dest_o(dest_mcast_all_endp), .row_has_any_dest( ), .is_unicast() ); - //wire valid_dst_multi_r1 = (SELF_LOOP_EN == "NO") ? ~(dest_mcast_all_endp[current_e_addr] == 1'b1) : 1'b1; + //wire valid_dst_multi_r1 = (SELF_LOOP_EN == 0) ? ~(dest_mcast_all_endp[current_e_addr] == 1'b1) : 1'b1; wire valid_dst_multi_r2 = ~(dest_mcast_all_endp == {NE{1'b0}}); // there should be atleast one asserted destination assign dest_is_valid = valid_dst_multi_r2;// & valid_dst_multi_r1 ; end else diff --git a/mpsoc/rtl/src_noc/fattree_route.v b/mpsoc/rtl/src_noc/fattree_route.v index 402908c..41794a6 100644 --- a/mpsoc/rtl/src_noc/fattree_route.v +++ b/mpsoc/rtl/src_noc/fattree_route.v @@ -863,10 +863,10 @@ module fattree_router_addr_decode #( function integer log2; input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 SOUTH) begin :endp - wire [NE/NX-1 : 0] endp_mask [NX-1 : 0]; + wire [NE/NX-1 : 0] endp_mask [NX-1 : 0]; for(i=0; i< NE; i=i+1) begin : endpoints - //Endpoint decoded address + //Endpoint decoded address localparam MCAST_ID = endp_id_to_mcast_id(i), YY = ((i/NL) / NX ), XX = ((i/NL) % NX ), LL = (i % NL), PP = YY*NL + LL; - assign endp_mask [XX] [PP] = dest_mcast_all_endp [i]; + assign endp_mask [XX] [PP] = dest_mcast_all_endp [i]; end for(i=0;i1)? CLASS_MSB : DST_P_MSB, WEIGHT_LSB= MSB_CLASS + 1, WEIGHT_MSB = WEIGHT_LSB + WEIGHTw -1, - /* verilator lint_off WIDTH */ - MSB_W = (SWA_ARBITER_TYPE== "WRRA")? WEIGHT_MSB : MSB_CLASS, - /* verilator lint_on WIDTH */ + MSB_W = (IS_WRRA)? WEIGHT_MSB : MSB_CLASS, BE_LSB = MSB_W + 1, BE_MSB = BE_LSB+ BEw-1, MSB_BE = (BYTE_EN==1)? BE_MSB : MSB_W, //the maximum data width that can be carried out with header flit - /* verilator lint_off WIDTH */ - HDR_MAX_DATw = (PCK_TYPE == "SINGLE_FLIT")? Fpay : Fpay - MSB_BE -1; - /* verilator lint_on WIDTH */ + HDR_MAX_DATw = (IS_SINGLE_FLIT)? Fpay : Fpay - MSB_BE -1; localparam DISTw = (IS_FATTREE | IS_TREE ) ? log2(2*L+1): log2(NR+1), @@ -214,9 +210,7 @@ package pronoc_pkg; } hdr_flit_t; localparam HDR_FLIT_w = $bits(hdr_flit_t); - /* verilator lint_off WIDTH */ - localparam FPAYw = (PCK_TYPE == "SINGLE_FLIT")? Fpay + MSB_BE: Fpay; - /* verilator lint_on WIDTH */ + localparam FPAYw = (IS_SINGLE_FLIT)? Fpay + MSB_BE: Fpay; typedef struct packed { bit hdr_flag; diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index 85a7c1f..37745e2 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -312,8 +312,8 @@ endmodule module smart_bypass_chanels #( parameter NOC_ID=0, - parameter P=5 -) ( + parameter P=5 +) ( ivc_info, iport_info, oport_info, @@ -322,11 +322,11 @@ module smart_bypass_chanels #( smart_chanel_out, smart_req, reset, - clk + clk ); - `NOC_CONF - input reset,clk; + `NOC_CONF + input reset,clk; input smart_chanel_t smart_chanel_new [P-1 : 0]; input smart_chanel_t smart_chanel_in [P-1 : 0]; input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; @@ -345,14 +345,12 @@ module smart_bypass_chanels #( reg [P-1 : 0] rq; genvar i; generate - for (i=0;i 4) begin : local_ports - assign goes_straight_o = 1'b0; // There is not a next router in this case at all + assign goes_straight_o = 1'b0; // There is not a next router in this case at all end else begin :non_local wire [4 : 0 ] destport_one_hot; mesh_tori_decode_dstport decoder( @@ -401,22 +399,22 @@ module check_straight_oport #( assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; end//else end//mesh_tori - else if(IS_RING | IS_LINE) begin :oneD + else if(IS_RING | IS_LINE) begin :oneD if (SS_PORT_LOC == 0 || SS_PORT_LOC > 2) begin : local_ports - assign goes_straight_o = 1'b0; // There is not a next router in this case at all + assign goes_straight_o = 1'b0; // There is not a next router in this case at all end else begin :non_local wire [2: 0 ] destport_one_hot; line_ring_decode_dstport decoder( .dstport_encoded(destport_coded_i), .dstport_one_hot(destport_one_hot) ); - assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; + assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; end //non_local end// oneD //TODO Add fattree & custom -endgenerate -endmodule +endgenerate +endmodule @@ -464,8 +462,8 @@ module smart_validity_check_per_ivc #( input goes_straight, smart_requests_i, smart_ivc_i, - smart_hdr_flit, - //flit + smart_hdr_flit, + //flit flit_hdr_flag_i , flit_tail_flag_i, flit_wr_i, @@ -475,21 +473,21 @@ module smart_validity_check_per_ivc #( assigned_ovc_not_full, ovc_is_assigned, ivc_request, - //ss port status + //ss port status ss_ovc_avalable_in_ss_port, ss_ovc_crossbar_wr, ss_port_link_reg_flit_wr; - //output + //output output - smart_single_flit_pck_o , + smart_single_flit_pck_o, smart_ivc_smart_en_o, smart_credit_o, smart_buff_space_decreased_o, smart_ss_ovc_is_allocated_o, smart_ss_ovc_is_released_o, smart_ivc_num_getting_ovc_grant_o, - smart_ivc_reset_o, - smart_mask_available_ss_ovc_o; + smart_ivc_reset_o, + smart_mask_available_ss_ovc_o; output reg [V-1 : 0] smart_ivc_granted_ovc_num_o; @@ -509,14 +507,10 @@ module smart_validity_check_per_ivc #( wire hdr_flit_condition = ~ovc_locally_requested & ss_ovc_avalable_in_ss_port; wire nonhdr_flit_condition = assigned_to_ss_ovc & assigned_ovc_not_full; wire condition1 = - /* verilator lint_off WIDTH */ - (PCK_TYPE == "SINGLE_FLIT")? hdr_flit_condition : - /* verilator lint_on WIDTH */ + (IS_SINGLE_FLIT)? hdr_flit_condition : (ovc_is_assigned)? nonhdr_flit_condition : hdr_flit_condition; wire condition2; - /* verilator lint_off WIDTH */ - wire non_empty_ivc_condition =(PCK_TYPE == "SINGLE_FLIT")? 1'b0 :ivc_request; - /* verilator lint_on WIDTH */ + wire non_empty_ivc_condition =(IS_SINGLE_FLIT)? 1'b0 :ivc_request; assign condition2=( ADD_PIPREG_AFTER_CROSSBAR == 1)? ~(non_empty_ivc_condition | ss_port_link_reg_flit_wr| ss_ovc_crossbar_wr): @@ -524,9 +518,7 @@ module smart_validity_check_per_ivc #( wire conditions_met = condition1 & condition2; assign smart_ivc_smart_en_o = conditions_met & smart_req_valid; assign smart_single_flit_pck_o = - /* verilator lint_off WIDTH */ - (PCK_TYPE == "SINGLE_FLIT")? 1'b1 : - /* verilator lint_on WIDTH */ + (IS_SINGLE_FLIT)? 1'b1 : (MIN_PCK_SIZE==1)? flit_tail_flag_i & flit_hdr_flag_i : 1'b0; assign smart_buff_space_decreased_o = smart_ivc_smart_en_o & flit_wr_i ; assign smart_ivc_num_getting_ovc_grant_o = smart_buff_space_decreased_o & !ovc_is_assigned & flit_hdr_flag_i; @@ -562,16 +554,16 @@ module smart_allocator_per_iport # ( //output smart_destport_o, smart_lk_destport_o, - smart_ivc_smart_en_o, - smart_credit_o, - smart_buff_space_decreased_o, - smart_ss_ovc_is_allocated_o, + smart_ivc_smart_en_o, + smart_credit_o, + smart_buff_space_decreased_o, + smart_ss_ovc_is_allocated_o, smart_ss_ovc_is_released_o, smart_ivc_num_getting_ovc_grant_o, smart_ivc_reset_o, smart_mask_available_ss_ovc_o, smart_hdr_flit_req_o, - smart_ivc_granted_ovc_num_o, + smart_ivc_granted_ovc_num_o, smart_ivc_single_flit_pck_o, smart_ovc_single_flit_pck_o ); @@ -579,7 +571,7 @@ module smart_allocator_per_iport # ( //general input clk, reset; input [RAw-1 :0] current_r_addr_i; - input [RAw-1: 0] neighbors_r_addr_i [P-1 : 0]; + input [RAw-1: 0] neighbors_r_addr_i [P-1 : 0]; //channels input smart_chanel_t smart_chanel_i; input flit_chanel_t flit_chanel_i; @@ -594,16 +586,16 @@ module smart_allocator_per_iport # ( output [DSTPw-1 : 0] smart_destport_o,smart_lk_destport_o; output smart_hdr_flit_req_o; output [V-1 : 0] - smart_ivc_smart_en_o, - smart_credit_o, + smart_ivc_smart_en_o, + smart_credit_o, smart_buff_space_decreased_o, - smart_ss_ovc_is_allocated_o, + smart_ss_ovc_is_allocated_o, smart_ss_ovc_is_released_o, smart_mask_available_ss_ovc_o, smart_ivc_num_getting_ovc_grant_o, - smart_ivc_reset_o, + smart_ivc_reset_o, smart_ivc_single_flit_pck_o, - smart_ovc_single_flit_pck_o; + smart_ovc_single_flit_pck_o; output [V*V-1 : 0] smart_ivc_granted_ovc_num_o; assign smart_ovc_single_flit_pck_o = smart_ivc_single_flit_pck_o; diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 7fb57c9..4079301 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -282,7 +282,7 @@ module router_top #( $display("ERROR: SMART only works with non-speculative VSA"); $finish; end - if((MIN_PCK_SIZE > 1) &&(PCK_TYPE == "SINGLE_FLIT")) begin + if((MIN_PCK_SIZE > 1) && (IS_SINGLE_FLIT)) begin $display("ERROR: The minimum packet size must be set as one for single-flit packet type NoC"); $finish; end diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 262789d..de60099 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -81,7 +81,7 @@ module router_two_stage #( PV = V * P, VV = V*V, PVV = PV * V, - P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P, + P_1 = (SELF_LOOP_EN )? P : P-1, PP_1 = P_1 * P, PVP_1 = PV * P_1, PFw = P*Fw, @@ -209,7 +209,7 @@ module router_two_stage #( .clk(clk) ); end - if(SELF_LOOP_EN == "NO") begin :nslp + if(SELF_LOOP_EN == 0) begin :nslp add_sw_loc_one_hot #( .P(P), .SW_LOC(i) diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index 6dce726..af1f879 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -256,11 +256,9 @@ module ssa_per_vc #( wire [V-1 : 0] vc_num_in; wire hdr_flg; wire tail_flg; - /* verilator lint_off WIDTH */ assign single_flit_pck = - (PCK_TYPE == "SINGLE_FLIT")? 1'b1 : + (IS_SINGLE_FLIT)? 1'b1 : (MIN_PCK_SIZE==1)? hdr_flg & tail_flg : 1'b0; - /* verilator lint_on WIDTH */ wire condition_1_2_valid; wire [DAw-1 : 0] dest_e_addr_in; extract_header_flit_info #( @@ -478,20 +476,18 @@ module add_ss_port #( ); `NOC_CONF localparam SS_PORT = strieght_port(P,SW_LOC); - localparam DISABLED = P; - localparam P_1 = ( SELF_LOOP_EN=="NO")? P-1 : P; + localparam DISABLED = P; + localparam P_1 = (SELF_LOOP_EN )? P : P-1; input [P_1-1 : 0] destport_in; output [P_1-1 : 0] destport_out; - generate + generate if(SS_PORT == DISABLED) begin :no_ss - assign destport_out = destport_in; + assign destport_out = destport_in; end else begin : ss reg [P_1-1 : 0] destport_temp; - /* verilator lint_off WIDTH */ - if( SELF_LOOP_EN=="YES") begin : slp - /* verilator lint_on WIDTH */ + if( SELF_LOOP_EN) begin : slp always @(*)begin destport_temp=destport_in; if(destport_in=={P_1{1'b0}}) destport_temp[SS_PORT]= 1'b1; diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index c3943fb..ef12b33 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -460,7 +460,7 @@ $display ("\tSSA_EN enabled:%s",SSA_EN); $display ("\tSwitch allocator arbitration type:%s",SWA_ARBITER_TYPE); $display ("\tMinimum supported packet size:%0d flit(s)",MIN_PCK_SIZE); - $display ("\tLoop back is enabled:%s",SELF_LOOP_EN); + $display ("\tLoop back is enabled:%d",SELF_LOOP_EN); $display ("\tNumber of multihop bypass (SMART max):%0d",SMART_MAX); $display ("\tCastying type:%s.",CAST_TYPE); if (CAST_TYPE == "MULTICAST_PARTIAL" || CAST_TYPE == "BROADCAST_PARTIAL")begin diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index 89eda5c..aff93e5 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -99,7 +99,7 @@ module traffic_gen_top #( wire [RAw-1 :0] current_r_addr; /* verilator lint_off WIDTH */ - wire [PCK_SIZw-1 : 0] pck_size_tmp= (PCK_TYPE == "SINGLE_FLIT" )? 1 : pck_size_in; + wire [PCK_SIZw-1 : 0] pck_size_tmp= (IS_SINGLE_FLIT )? 1 : pck_size_in; /* verilator lint_on WIDTH */ always_comb begin @@ -539,16 +539,16 @@ module traffic_gen_top #( /* verilator lint_off WIDTH */ if (CAST_TYPE == "BROADCAST_FULL") begin :bcastf - assign mcast_dst_num_o = (is_unicast) ? 1 : (SELF_LOOP_EN == "NO")? NE-1 : NE; + assign mcast_dst_num_o = (is_unicast) ? 1 : (SELF_LOOP_EN ) ? NE : NE-1; end else if ( CAST_TYPE == "BROADCAST_PARTIAL" ) begin :bcastp - if (SELF_LOOP_EN == "NO") begin + if (SELF_LOOP_EN == 0) begin //check if injector node is included in partial list wire [NEw-1: 0] current_enp_id; endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) decod1 ( .id(current_enp_id), .code(current_e_addr)); assign mcast_dst_num_o = (is_unicast) ? 1 : (MCAST_ENDP_LIST[current_enp_id]== 1'b1)? MCAST_PRTLw-1 : MCAST_PRTLw; end else begin assign mcast_dst_num_o = (is_unicast)? 1 : MCAST_PRTLw; - end + end /* verilator lint_on WIDTH */ end else begin : mcast @@ -595,7 +595,7 @@ module traffic_gen_top #( /* verilator lint_off WIDTH */ if(CAST_TYPE == "UNICAST") begin /* verilator lint_on WIDTH */ - if(flit_out_wr && hdr_flit && dest_e_addr_o [EAw-1 : 0] == current_e_addr && SELF_LOOP_EN == "NO") begin + if(flit_out_wr && hdr_flit && dest_e_addr_o [EAw-1 : 0] == current_e_addr && SELF_LOOP_EN == 0) begin $display("%t: ERROR: The self-loop is not enabled in the router while a packet is injected to the NoC with identical source and destination address in endpoint (%h).: %m",$time, dest_e_addr_o ); $finish; end @@ -608,7 +608,7 @@ module traffic_gen_top #( if((CAST_TYPE == "MULTICAST_FULL") || (CAST_TYPE == "MULTICAST_PARTIAL")) begin /* verilator lint_on WIDTH */ - if(flit_out_wr && hdr_flit && dest_mcast_all_endp1[current_id] == 1'b1 && SELF_LOOP_EN == "NO") begin + if(flit_out_wr && hdr_flit && dest_mcast_all_endp1[current_id] == 1'b1 && SELF_LOOP_EN == 0) begin $display("%t: ERROR: The self-loop is not enabled in the router while a packet is injected to the NoC with identical source and destination address in endpoint %d. destination nodes:0X%h. : %m",$time, current_id,dest_mcast_all_endp1 ); $finish; end @@ -896,7 +896,7 @@ module packet_gen .rd_en(pck_rd), .dout({tmp1,tmp2,pck_timestamp}), .full(timestamp_fifo_full), - .nearly_full(timestamp_fifo_nearly_full), + .nearly_full(timestamp_fifo_nearly_full), .recieve_more_than_0(recieve_more_than_0), .recieve_more_than_1(), .reset(reset), @@ -907,7 +907,7 @@ module packet_gen assign dest_e_addr_o =tmp1; /* verilator lint_off WIDTH */ - assign pck_size_o = (PCK_TYPE == "SINGLE_FLIT" )? 1 : tmp2; + assign pck_size_o = (IS_SINGLE_FLIT )? 1 : tmp2; /* verilator lint_on WIDTH */ assign buffer_empty = ~recieve_more_than_0; diff --git a/mpsoc/rtl/src_noc/tree_route.v b/mpsoc/rtl/src_noc/tree_route.v index 2ba25df..3f8dccc 100644 --- a/mpsoc/rtl/src_noc/tree_route.v +++ b/mpsoc/rtl/src_noc/tree_route.v @@ -298,21 +298,21 @@ module tree_destp_generator #( parameter P=K+1, parameter SW_LOC=0, parameter DSTPw=4, - parameter SELF_LOOP_EN = "NO" + parameter SELF_LOOP_EN = 0 )( dest_port_in_encoded, dest_port_out ); localparam MAX_P = K+1, - P_1 = (SELF_LOOP_EN == "NO")? P-1 : P; - + P_1 = (SELF_LOOP_EN )? P : P-1; + input [DSTPw-1: 0] dest_port_in_encoded; - output [P_1-1 : 0] dest_port_out; + output [P_1-1 : 0] dest_port_out; wire [MAX_P-1 : 0] destport_decoded; - tree_destport_decoder #( + tree_destport_decoder #( .K(K) ) destport_decoder( .destport_encoded_i(dest_port_in_encoded), @@ -320,7 +320,7 @@ module tree_destp_generator #( ); generate - if(SELF_LOOP_EN == "NO") begin : nslp + if(SELF_LOOP_EN == 0) begin : nslp remove_sw_loc_one_hot #( .P(P), .SW_LOC(SW_LOC) @@ -329,7 +329,7 @@ module tree_destp_generator #( .destport_out(dest_port_out[P_1-1 : 0 ]) ); end else begin : slp - assign dest_port_out = destport_decoded; + assign dest_port_out = destport_decoded; end endgenerate endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/wrra.v b/mpsoc/rtl/src_noc/wrra.v index eac38b7..c52af6f 100644 --- a/mpsoc/rtl/src_noc/wrra.v +++ b/mpsoc/rtl/src_noc/wrra.v @@ -241,7 +241,7 @@ module weight_control #( parameter WEIGHTw= 4, parameter WRRA_CONFIG_INDEX=0, parameter P=5, - parameter SELF_LOOP_EN = "NO" + parameter SELF_LOOP_EN = 0 )( sw_is_granted, flit_is_tail, @@ -249,14 +249,14 @@ module weight_control #( granted_dest_port, weight_is_consumed_o, oports_weight, - refresh_w_counter, + refresh_w_counter, clk, - reset -); + reset +); localparam W = WEIGHTw, WP = W * P, - P_1 = (SELF_LOOP_EN=="NO") ? P-1 : P; + P_1 = (SELF_LOOP_EN) ? P : P-1; localparam [W-1 : 0] INIT_WEIGHT = 1; localparam [W-1 : 0] MAX_WEIGHT = {W{1'b1}}-1'b1; localparam @@ -281,7 +281,7 @@ module weight_control #( reg [W-1 : 0] oport_weight [P-1 : 0]; generate - if(SELF_LOOP_EN == "NO") begin : nslp + if(SELF_LOOP_EN == 0) begin : nslp add_sw_loc_one_hot #( .P(P), .SW_LOC(SW_LOC) @@ -421,7 +421,7 @@ module wrra_contention_gen #( parameter P=5, parameter WRRA_CONFIG_INDEX=0, parameter WEIGHTw = 4, // WRRA width - parameter SELF_LOOP_EN ="NO" + parameter SELF_LOOP_EN = 0 )( ovc_is_assigned_all, ivc_request_all, @@ -441,7 +441,7 @@ module wrra_contention_gen #( endfunction // log2 localparam - P_1 = (SELF_LOOP_EN == "NO") ? P-1 : P, + P_1 = (SELF_LOOP_EN) ? P : P-1, PV = P * V, VP_1= V * P_1, PVP_1 = PV * P_1, @@ -528,14 +528,14 @@ module wrra_inputport_destports_sum #( parameter V=4, parameter P=5, parameter SW_LOC=0, - parameter SELF_LOOP_EN = "NO" + parameter SELF_LOOP_EN = 0 )( weight_is_valid, dest_ports, destports_sum ); localparam - P_1 = (SELF_LOOP_EN== "NO")? P - 1 : P, + P_1 = (SELF_LOOP_EN) ? P : P - 1, VP_1 = V * P_1; input [V-1 : 0] weight_is_valid; input [VP_1-1 : 0] dest_ports; @@ -557,8 +557,8 @@ module wrra_inputport_destports_sum #( .or_in(dest_ports_masked), .or_out(sum) ); - - if(SELF_LOOP_EN=="NO") begin : nslp + + if(SELF_LOOP_EN == 0) begin : nslp add_sw_loc_one_hot #( .P(P), .SW_LOC(SW_LOC) diff --git a/mpsoc/rtl/src_openpiton/noc_localparam.v b/mpsoc/rtl/src_openpiton/noc_localparam.v index ce9bfc8..efcc911 100644 --- a/mpsoc/rtl/src_openpiton/noc_localparam.v +++ b/mpsoc/rtl/src_openpiton/noc_localparam.v @@ -32,7 +32,7 @@ localparam FIRST_ARBITER_EXT_P_EN=0; localparam SWA_ARBITER_TYPE="RRA"; localparam WEIGHTw=4; - localparam SELF_LOOP_EN="YES"; + localparam SELF_LOOP_EN=1; localparam AVC_ATOMIC_EN=0; localparam CLASS_SETTING={V{1'b1}}; localparam CVw=(C==0)? V : C * V; diff --git a/mpsoc/rtl/src_openpiton/wrapper.sv b/mpsoc/rtl/src_openpiton/wrapper.sv index 3c9111a..66ac803 100644 --- a/mpsoc/rtl/src_openpiton/wrapper.sv +++ b/mpsoc/rtl/src_openpiton/wrapper.sv @@ -614,12 +614,12 @@ module pronoc_to_piton_wrapper #( .NL(T3), .P(MAX_P), .PLw(PLw), - .DSTPw(DSTPw), + .DSTPw(DSTPw), .SELF_LOOP_EN (SELF_LOOP_EN), .SW_LOC(PORT_NUM) ) decoder ( .destport_one_hot (destport_one_hot), - .dest_port_encoded(dstp_encoded), + .dest_port_encoded(dstp_encoded), .dest_port_out(), .endp_localp_num(endp_p_in), .swap_port_presel(), @@ -637,7 +637,7 @@ module pronoc_to_piton_wrapper #( assign header_flit [ `MSG_OPTIONS_1] = option1; generate - if(Fpay > 64) begin :R_ + if(Fpay > 64) begin :R_ assign header_flit [Fpay - 1 : 64] = head_dat[Fpay + HEAD_DATw -65 :HEAD_DATw]; end endgenerate diff --git a/mpsoc/script/synfull/noc_localparam.v b/mpsoc/script/synfull/noc_localparam.v index 83104ba..6aac87e 100644 --- a/mpsoc/script/synfull/noc_localparam.v +++ b/mpsoc/script/synfull/noc_localparam.v @@ -1,79 +1,73 @@ /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/ /********************************************************************** -** File: noc_localparam.v +** File: noc_localparam.v ** -** Copyright (C) 2014-2019 Alireza Monemi +** Copyright (C) 2014-2019 Alireza Monemi ** -** This file is part of ProNoC 1.9.1 +** This file is part of ProNoC 1.9.1 ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ - - `ifdef NOC_LOCAL_PARAM - - - + + `ifdef NOC_LOCAL_PARAM //NoC parameters - localparam TOPOLOGY="MESH"; - localparam T1=4; - localparam T2=4; - localparam T3=2; - localparam V=1; - localparam B=4; - localparam LB=4; - localparam Fpay=64; - localparam ROUTE_NAME="XY"; - localparam PCK_TYPE="MULTI_FLIT"; - localparam MIN_PCK_SIZE=1; - localparam BYTE_EN=0; - localparam SSA_EN="NO"; - localparam SMART_MAX=0; - localparam CONGESTION_INDEX=3; - localparam ESCAP_VC_MASK=1; - localparam VC_REALLOCATION_TYPE="NONATOMIC"; - localparam COMBINATION_TYPE="COMB_NONSPEC"; - localparam MUX_TYPE="BINARY"; - localparam C=2; - localparam DEBUG_EN=1; - localparam ADD_PIPREG_AFTER_CROSSBAR=1'b1; - localparam FIRST_ARBITER_EXT_P_EN=1; - localparam SWA_ARBITER_TYPE="RRA"; - localparam WEIGHTw=4; - localparam SELF_LOOP_EN="YES"; - localparam AVC_ATOMIC_EN=0; - localparam CVw=(C==0)? V : C * V; - localparam CLASS_SETTING={CVw{1'b1}}; + localparam TOPOLOGY="MESH"; + localparam T1=4; + localparam T2=4; + localparam T3=2; + localparam V=1; + localparam B=4; + localparam LB=4; + localparam Fpay=64; + localparam ROUTE_NAME="XY"; + localparam PCK_TYPE="MULTI_FLIT"; + localparam MIN_PCK_SIZE=1; + localparam BYTE_EN=0; + localparam SSA_EN="NO"; + localparam SMART_MAX=0; + localparam CONGESTION_INDEX=3; + localparam ESCAP_VC_MASK=1; + localparam VC_REALLOCATION_TYPE="NONATOMIC"; + localparam COMBINATION_TYPE="COMB_NONSPEC"; + localparam MUX_TYPE="BINARY"; + localparam C=2; + localparam DEBUG_EN=1; + localparam ADD_PIPREG_AFTER_CROSSBAR=1'b1; + localparam FIRST_ARBITER_EXT_P_EN=1; + localparam SWA_ARBITER_TYPE="RRA"; + localparam WEIGHTw=4; + localparam SELF_LOOP_EN=1; + localparam AVC_ATOMIC_EN=0; + localparam CVw=(C==0)? V : C * V; + localparam CLASS_SETTING={CVw{1'b1}}; localparam CAST_TYPE = "UNICAST"; - localparam MCAST_ENDP_LIST = 'b11110011; -// localparam MCAST_PRTLw=6; - - //simulation parameter - //localparam MAX_RATIO = 1000; - localparam MAX_PCK_NUM = 1000000000; - localparam MAX_PCK_SIZ = 16383; - localparam MAX_SIM_CLKs= 1000000000; - localparam TIMSTMP_FIFO_NUM = 16; - - - - - `endif + localparam MCAST_ENDP_LIST = 'b11110011; +// localparam MCAST_PRTLw=6; + + //simulation parameter + //localparam MAX_RATIO = 1000; + localparam MAX_PCK_NUM = 1000000000; + localparam MAX_PCK_SIZ = 16383; + localparam MAX_SIM_CLKs= 1000000000; + localparam TIMSTMP_FIFO_NUM = 16; + +`endif diff --git a/mpsoc/smart-netrace/models/B4_V1_S0 b/mpsoc/smart-netrace/models/B4_V1_S0 index db60b5c..3b9e23c 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S0 +++ b/mpsoc/smart-netrace/models/B4_V1_S0 @@ -4,7 +4,7 @@ $model = bless( { "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "SMART_MAX" => "0", "ESCAP_VC_MASK" => "1'b1", } diff --git a/mpsoc/smart-netrace/models/B4_V1_S2 b/mpsoc/smart-netrace/models/B4_V1_S2 index 8a996e0..893796d 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S2 +++ b/mpsoc/smart-netrace/models/B4_V1_S2 @@ -4,7 +4,7 @@ $model = bless( { "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "SMART_MAX" => "2", "ESCAP_VC_MASK" => "1'b1", } diff --git a/mpsoc/smart-netrace/models/B4_V1_S4 b/mpsoc/smart-netrace/models/B4_V1_S4 index f9f2e0b..87959c4 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S4 +++ b/mpsoc/smart-netrace/models/B4_V1_S4 @@ -4,7 +4,7 @@ $model = bless( { "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "SMART_MAX" => "4", "ESCAP_VC_MASK" => "1'b1", } diff --git a/mpsoc/smart-netrace/models/B4_V1_S7 b/mpsoc/smart-netrace/models/B4_V1_S7 index a13f851..c624e39 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S7 +++ b/mpsoc/smart-netrace/models/B4_V1_S7 @@ -4,7 +4,7 @@ $model = bless( { "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", - "SELF_LOOP_EN" => "\"YES\"", + "SELF_LOOP_EN" => "1", "SMART_MAX" => "7", "ESCAP_VC_MASK" => "1'b1", } diff --git a/mpsoc/smart-netrace/src/deafult_noc_param b/mpsoc/smart-netrace/src/deafult_noc_param index e884438..02ae6d9 100644 --- a/mpsoc/smart-netrace/src/deafult_noc_param +++ b/mpsoc/smart-netrace/src/deafult_noc_param @@ -28,7 +28,7 @@ $model = bless( { "AVC_ATOMIC_EN" => "0", "CLASS_SETTING" => "{V{1'b1}}", "SMART_MAX" => "0", -"SELF_LOOP_EN" => "\"NO\"", +"SELF_LOOP_EN" => "0", "MAX_PCK_NUM " => " 1000000000", "MAX_PCK_SIZ " => " 16383" , "MAX_SIM_CLKs" => " 1000000000", diff --git a/mpsoc/src_verilator/netrace_lib.h b/mpsoc/src_verilator/netrace_lib.h index 016e3ef..f1f33a2 100644 --- a/mpsoc/src_verilator/netrace_lib.h +++ b/mpsoc/src_verilator/netrace_lib.h @@ -48,74 +48,74 @@ unsigned int read_done=0; typedef struct queue_node queue_node_t; struct queue_node { - nt_packet_t* packet; - unsigned long long int cycle; + nt_packet_t* packet; + unsigned long long int cycle; }; unsigned long long int calc_packet_timing( nt_packet_t* packet ) { - - int n_hops = abs( packet->src - packet->dst ); - if( n_hops <= 0 ) n_hops = 1; - return 3*n_hops; + + int n_hops = abs( packet->src - packet->dst ); + if( n_hops <= 0 ) n_hops = 1; + return 3*n_hops; } void netrace_init( char * tracefile){ - int i=0; - nt_open_trfile( tracefile ); - if( ignore_dependencies ) { - nt_disable_dependencies(); - printf("\tDependencies is turned off in tracking cleared packets list\n"); - } - if( reader_throttling ) { - printf("\treader throttling is enabled\n"); - } - nt_print_trheader(); - header = nt_get_trheader(); - nt_seek_region( &header->regions[start_region] ); - for(i = 0; i < start_region; i++ ) { - nt_cycle += header->regions[i].num_cycles; - } - if(nt_cycle){ - printf("\tThe simulation start at region %u and %llu cycle\n",start_region,nt_cycle); - nt_start_cycle=nt_cycle; - } - - waiting = (queue_t**) malloc( NE * sizeof(queue_t*) ); - inject = (queue_t**) malloc( NE * sizeof(queue_t*) ); - traverse = (queue_t**) malloc( NE * sizeof(queue_t*) ); - if( (waiting == NULL) || (inject == NULL) || (traverse == NULL) ) { - printf( "ERROR: malloc fail queues\n" ); - exit(0); - } - - for( i = 0; i < NE; ++i ) { - waiting[i] = queue_new(); - inject[i] = queue_new(); - traverse[i] = queue_new(); - } - - - if( !reader_throttling ) { - trace_packet = nt_read_packet(); - } else if( !ignore_dependencies ) { - nt_init_self_throttling(); - } - - MIN_PACKET_SIZE = (8*8)/Fpay; - MAX_PACKET_SIZE = (64*8)/Fpay; - AVG_PACKET_SIZE=(MIN_PACKET_SIZE+MAX_PACKET_SIZE)/2;// average packet size - int p=(MAX_PACKET_SIZE-MIN_PACKET_SIZE)+1; - rsv_size_array = (unsigned int*) calloc ( p , sizeof(int)); - if (rsv_size_array==NULL){ - fprintf(stderr,"ERROR: cannot allocate (%d x int) memory for rsv_size_array. \n",p); - exit(1); - } - - - if(verbosity==1) printf("\e[?25l"); //To hide the cursor: + int i=0; + nt_open_trfile( tracefile ); + if( ignore_dependencies ) { + nt_disable_dependencies(); + printf("\tDependencies is turned off in tracking cleared packets list\n"); + } + if( reader_throttling ) { + printf("\treader throttling is enabled\n"); + } + nt_print_trheader(); + header = nt_get_trheader(); + nt_seek_region( &header->regions[start_region] ); + for(i = 0; i < start_region; i++ ) { + nt_cycle += header->regions[i].num_cycles; + } + if(nt_cycle){ + printf("\tThe simulation start at region %u and %llu cycle\n",start_region,nt_cycle); + nt_start_cycle=nt_cycle; + } + + waiting = (queue_t**) malloc( NE * sizeof(queue_t*) ); + inject = (queue_t**) malloc( NE * sizeof(queue_t*) ); + traverse = (queue_t**) malloc( NE * sizeof(queue_t*) ); + if( (waiting == NULL) || (inject == NULL) || (traverse == NULL) ) { + printf( "ERROR: malloc fail queues\n" ); + exit(0); + } + + for( i = 0; i < NE; ++i ) { + waiting[i] = queue_new(); + inject[i] = queue_new(); + traverse[i] = queue_new(); + } + + + if( !reader_throttling ) { + trace_packet = nt_read_packet(); + } else if( !ignore_dependencies ) { + nt_init_self_throttling(); + } + + MIN_PACKET_SIZE = (8*8)/Fpay; + MAX_PACKET_SIZE = (64*8)/Fpay; + AVG_PACKET_SIZE=(MIN_PACKET_SIZE+MAX_PACKET_SIZE)/2;// average packet size + int p=(MAX_PACKET_SIZE-MIN_PACKET_SIZE)+1; + rsv_size_array = (unsigned int*) calloc ( p , sizeof(int)); + if (rsv_size_array==NULL){ + fprintf(stderr,"ERROR: cannot allocate (%d x int) memory for rsv_size_array. \n",p); + exit(1); + } + + + if(verbosity==1) printf("\e[?25l"); //To hide the cursor: } @@ -123,265 +123,265 @@ void netrace_init( char * tracefile){ void netrace_eval(unsigned int eval_num){ - int i; - unsigned int pronoc_src_id,pronoc_dst_id; - - if((reset==reset_active_high) || (count_en==0)) return; - - if((( nt_cycle > header->num_cycles) || (read_done==1 )) && nt_packets_left==0 ) simulation_done=1; - - // Reset packets remaining check - nt_packets_left = 0; - - // Get packets for this cycle - if((end_sim_pck_num == 0 ) || (end_sim_pck_num > nt_total_rd_pck )){ - if( reader_throttling ) { - nt_packet_list_t* list; - for( list = nt_get_cleared_packets_list(); list != NULL; list = list->next ) { - if( list->node_packet != NULL ) { - trace_packet = list->node_packet; - queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) ); - new_node->packet = trace_packet; - new_node->cycle = (trace_packet->cycle > nt_cycle) ? trace_packet->cycle : nt_cycle; - pronoc_src_id=traffic_model_mapping[trace_packet->src]; - queue_push( inject[pronoc_src_id], new_node, new_node->cycle ); - nt_total_rd_pck++; - } else { - printf( "ERROR: Malformed packet list" ); - exit(-1); - } - } - nt_empty_cleared_packets_list(); - } else { - while( (trace_packet != NULL) && (trace_packet->cycle == nt_cycle) ) { - // Place in appropriate queue - queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) ); - new_node->packet = trace_packet; - new_node->cycle = (trace_packet->cycle > nt_cycle) ? trace_packet->cycle : nt_cycle; - pronoc_src_id=traffic_model_mapping[trace_packet->src]; - if( ignore_dependencies || nt_dependencies_cleared( trace_packet ) ) { - // Add to inject queue - queue_push( inject[pronoc_src_id], new_node, new_node->cycle ); - nt_total_rd_pck++; - } else { - // Add to waiting queue - queue_push( waiting[pronoc_src_id], new_node, new_node->cycle ); - nt_total_rd_pck++; - } - // Get another packet from trace - trace_packet = nt_read_packet(); - } - if( (trace_packet != NULL) && (trace_packet->cycle < nt_cycle) ) { - // Error check: Crash and burn - printf( "ERROR: Invalid trace_packet cycle time: %llu, current cycle: %llu\n", trace_packet->cycle, nt_cycle ); - exit(-1); - } - } - }else {//if ~end_sim_pck_num - read_done=1; - } - - if(eval_numnum_nodes; - for( i = 0; i < NE; ++i ) { - nt_packets_left |= !queue_empty( inject[i] ); - //TODO define sent vc policy - int sent_vc = 0; - - if(pck_inj[i]->pck_injct_in_pck_wr){ - //the wr_pck should be asserted only for single cycle - pck_inj[i]->pck_injct_in_pck_wr = 0; - continue; - } - - pck_inj[i]->pck_injct_in_pck_wr = 0; - if((pck_inj[i]->pck_injct_out_ready & (0x1<packet; - if( (packet != NULL) && (temp_node->cycle <= nt_cycle) ) { - - if(verbosity>1) { - printf( "Inject: %llu ", nt_cycle ); - nt_print_packet( packet ); - } - temp_node = (queue_node_t*) queue_pop_front( inject[i] ); - temp_node->cycle = nt_cycle;//injection time - pronoc_dst_id = traffic_model_mapping[packet->dst]; - queue_push( traverse[pronoc_dst_id ], temp_node, temp_node->cycle ); - long int ptr_addr = reinterpret_cast (temp_node); - int flit_num = (nt_get_packet_size(packet)* 8) / Fpay; - if(flit_num< pck_inj[i]->min_pck_size) flit_num = pck_inj[i]->min_pck_size; - - if(IS_SELF_LOOP_EN ==0){ - if(pronoc_dst_id == i ){ - fprintf(stderr,"ERROR: ProNoC is not configured with self-loop enable and Netrace aims to inject\n a " - "packet with identical source and destination address. Enable the SELF_LOOP parameter\n" - "in ProNoC and rebuild the simulation model\n"); - exit(1); - } - } - unsigned int sent_class =0; - pck_inj[i]->pck_injct_in_data = ptr_addr; - pck_inj[i]->pck_injct_in_size = flit_num; - pck_inj[i]->pck_injct_in_endp_addr = endp_addr_encoder(pronoc_dst_id); - pck_inj[i]->pck_injct_in_class_num = sent_class; - pck_inj[i]->pck_injct_in_init_weight = 1; - pck_inj[i]->pck_injct_in_vc = 0x1<pck_injct_in_pck_wr = 1; - total_sent_pck_num++; - - #if (C>1) - sent_stat[i][sent_class].pck_num ++; - sent_stat[i][sent_class].flit_num +=flit_num; - #else - sent_stat[i].pck_num ++; - sent_stat[i].flit_num +=flit_num; - #endif - } - } - } + int i; + unsigned int pronoc_src_id,pronoc_dst_id; + + if((reset==reset_active_high) || (count_en==0)) return; + + if((( nt_cycle > header->num_cycles) || (read_done==1 )) && nt_packets_left==0 ) simulation_done=1; + + // Reset packets remaining check + nt_packets_left = 0; + + // Get packets for this cycle + if((end_sim_pck_num == 0 ) || (end_sim_pck_num > nt_total_rd_pck )){ + if( reader_throttling ) { + nt_packet_list_t* list; + for( list = nt_get_cleared_packets_list(); list != NULL; list = list->next ) { + if( list->node_packet != NULL ) { + trace_packet = list->node_packet; + queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) ); + new_node->packet = trace_packet; + new_node->cycle = (trace_packet->cycle > nt_cycle) ? trace_packet->cycle : nt_cycle; + pronoc_src_id=traffic_model_mapping[trace_packet->src]; + queue_push( inject[pronoc_src_id], new_node, new_node->cycle ); + nt_total_rd_pck++; + } else { + printf( "ERROR: Malformed packet list" ); + exit(-1); + } + } + nt_empty_cleared_packets_list(); + } else { + while( (trace_packet != NULL) && (trace_packet->cycle == nt_cycle) ) { + // Place in appropriate queue + queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) ); + new_node->packet = trace_packet; + new_node->cycle = (trace_packet->cycle > nt_cycle) ? trace_packet->cycle : nt_cycle; + pronoc_src_id=traffic_model_mapping[trace_packet->src]; + if( ignore_dependencies || nt_dependencies_cleared( trace_packet ) ) { + // Add to inject queue + queue_push( inject[pronoc_src_id], new_node, new_node->cycle ); + nt_total_rd_pck++; + } else { + // Add to waiting queue + queue_push( waiting[pronoc_src_id], new_node, new_node->cycle ); + nt_total_rd_pck++; + } + // Get another packet from trace + trace_packet = nt_read_packet(); + } + if( (trace_packet != NULL) && (trace_packet->cycle < nt_cycle) ) { + // Error check: Crash and burn + printf( "ERROR: Invalid trace_packet cycle time: %llu, current cycle: %llu\n", trace_packet->cycle, nt_cycle ); + exit(-1); + } + } + }else {//if ~end_sim_pck_num + read_done=1; + } + + if(eval_numnum_nodes; + for( i = 0; i < NE; ++i ) { + nt_packets_left |= !queue_empty( inject[i] ); + //TODO define sent vc policy + int sent_vc = 0; + + if(pck_inj[i]->pck_injct_in_pck_wr){ + //the wr_pck should be asserted only for single cycle + pck_inj[i]->pck_injct_in_pck_wr = 0; + continue; + } + + pck_inj[i]->pck_injct_in_pck_wr = 0; + if((pck_inj[i]->pck_injct_out_ready & (0x1<packet; + if( (packet != NULL) && (temp_node->cycle <= nt_cycle) ) { + + if(verbosity>1) { + printf( "Inject: %llu ", nt_cycle ); + nt_print_packet( packet ); + } + temp_node = (queue_node_t*) queue_pop_front( inject[i] ); + temp_node->cycle = nt_cycle;//injection time + pronoc_dst_id = traffic_model_mapping[packet->dst]; + queue_push( traverse[pronoc_dst_id ], temp_node, temp_node->cycle ); + long int ptr_addr = reinterpret_cast (temp_node); + int flit_num = (nt_get_packet_size(packet)* 8) / Fpay; + if(flit_num< pck_inj[i]->min_pck_size) flit_num = pck_inj[i]->min_pck_size; + + if(SELF_LOOP_EN == 0){ + if(pronoc_dst_id == i ){ + fprintf(stderr,"ERROR: ProNoC is not configured with self-loop enable and Netrace aims to inject\n a " + "packet with identical source and destination address. Enable the SELF_LOOP parameter\n" + "in ProNoC and rebuild the simulation model\n"); + exit(1); + } + } + unsigned int sent_class =0; + pck_inj[i]->pck_injct_in_data = ptr_addr; + pck_inj[i]->pck_injct_in_size = flit_num; + pck_inj[i]->pck_injct_in_endp_addr = endp_addr_encoder(pronoc_dst_id); + pck_inj[i]->pck_injct_in_class_num = sent_class; + pck_inj[i]->pck_injct_in_init_weight = 1; + pck_inj[i]->pck_injct_in_vc = 0x1<pck_injct_in_pck_wr = 1; + total_sent_pck_num++; + + #if (C>1) + sent_stat[i][sent_class].pck_num ++; + sent_stat[i][sent_class].flit_num +=flit_num; + #else + sent_stat[i].pck_num ++; + sent_stat[i].flit_num +=flit_num; + #endif + } + } + } /* - // Step all network components, Eject where possible - for( i = 0; i < header->num_nodes; ++i ) { - nt_packets_left |= !queue_empty( traverse[i] ); - queue_node_t* temp_node = (queue_node_t*) queue_peek_front( traverse[i] ); - if( temp_node != NULL ) { - packet = temp_node->packet; - if( (packet != NULL) && (temp_node->cycle <= nt_cycle) ) { - printf( "Eject: %llu ", nt_cycle ); - nt_print_packet( packet ); - nt_clear_dependencies_free_packet( packet ); - temp_node = (queue_node_t*) queue_pop_front( traverse[i] ); - free( temp_node ); - } - } - } + // Step all network components, Eject where possible + for( i = 0; i < header->num_nodes; ++i ) { + nt_packets_left |= !queue_empty( traverse[i] ); + queue_node_t* temp_node = (queue_node_t*) queue_peek_front( traverse[i] ); + if( temp_node != NULL ) { + packet = temp_node->packet; + if( (packet != NULL) && (temp_node->cycle <= nt_cycle) ) { + printf( "Eject: %llu ", nt_cycle ); + nt_print_packet( packet ); + nt_clear_dependencies_free_packet( packet ); + temp_node = (queue_node_t*) queue_pop_front( traverse[i] ); + free( temp_node ); + } + } + } */ - // Step all network components, Eject where possible - for( i = 0; i < NE; ++i ) { - nt_packets_left |= !queue_empty( traverse[i] ); - //check which pck injector got a packet - if(pck_inj[i]->pck_injct_out_pck_wr==0) continue; - //we have got a packet - //printf( "data=%lx\n",pck_inj[i]->pck_injct_out_data); - - queue_node_t* temp_node = (queue_node_t*) pck_inj[i]->pck_injct_out_data; - if( temp_node != NULL ) { - packet = temp_node->packet; - if( packet != NULL){ - if(verbosity>1) { - printf( "Eject: %llu ", nt_cycle ); - nt_print_packet( packet ); - } - // remove from traverse - nt_clear_dependencies_free_packet( packet ); - queue_remove( traverse[i], temp_node ); - unsigned long long int clk_num_h2t= (nt_cycle - temp_node->cycle)/netrace_speed_up; - unsigned int clk_num_h2h= clk_num_h2t - pck_inj[i]->pck_injct_out_h2t_delay; - /* - printf("clk_num_h2t (%llu) h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); - if(clk_num_h2t < pck_inj[i]->pck_injct_out_h2t_delay){ - fprintf(stderr, "ERROR:clk_num_h2t (%llu) is smaller than injector h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); - exit(1); - } - */ - - pronoc_src_id=traffic_model_mapping[packet->src]; - total_rsv_pck_num++; - update_statistic_at_ejection ( - i,// core_num - clk_num_h2h, // clk_num_h2h, - (unsigned int) clk_num_h2t, // clk_num_h2t, - pck_inj[i]->pck_injct_out_distance, // distance, - pck_inj[i]->pck_injct_out_class_num,// class_num, - pronoc_src_id,// unsigned int src - pck_inj[i]->pck_injct_out_size - ); - - free( temp_node ); - - } - } - } - // Check for cleared dependences... or not - if( !reader_throttling ) { - for( i = 0; i < NE; ++i ) { - nt_packets_left |= !queue_empty( waiting[i] ); - node_t* temp = waiting[i]->head; - while( temp != NULL ) { - queue_node_t* temp_node = (queue_node_t*) temp->elem; - packet = temp_node->packet; - temp = temp->next; - if( nt_dependencies_cleared( packet ) ) { - // remove from waiting - queue_remove( waiting[i], temp_node ); - // add to inject - queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) ); - new_node->packet = packet; - new_node->cycle = nt_cycle + L2_LATENCY; - queue_push( inject[i], new_node, new_node->cycle ); - free( temp_node ); - } - } - } - } - nt_cycle++; + // Step all network components, Eject where possible + for( i = 0; i < NE; ++i ) { + nt_packets_left |= !queue_empty( traverse[i] ); + //check which pck injector got a packet + if(pck_inj[i]->pck_injct_out_pck_wr==0) continue; + //we have got a packet + //printf( "data=%lx\n",pck_inj[i]->pck_injct_out_data); + + queue_node_t* temp_node = (queue_node_t*) pck_inj[i]->pck_injct_out_data; + if( temp_node != NULL ) { + packet = temp_node->packet; + if( packet != NULL){ + if(verbosity>1) { + printf( "Eject: %llu ", nt_cycle ); + nt_print_packet( packet ); + } + // remove from traverse + nt_clear_dependencies_free_packet( packet ); + queue_remove( traverse[i], temp_node ); + unsigned long long int clk_num_h2t= (nt_cycle - temp_node->cycle)/netrace_speed_up; + unsigned int clk_num_h2h= clk_num_h2t - pck_inj[i]->pck_injct_out_h2t_delay; + /* + printf("clk_num_h2t (%llu) h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); + if(clk_num_h2t < pck_inj[i]->pck_injct_out_h2t_delay){ + fprintf(stderr, "ERROR:clk_num_h2t (%llu) is smaller than injector h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); + exit(1); + } + */ + + pronoc_src_id=traffic_model_mapping[packet->src]; + total_rsv_pck_num++; + update_statistic_at_ejection ( + i,// core_num + clk_num_h2h, // clk_num_h2h, + (unsigned int) clk_num_h2t, // clk_num_h2t, + pck_inj[i]->pck_injct_out_distance, // distance, + pck_inj[i]->pck_injct_out_class_num,// class_num, + pronoc_src_id,// unsigned int src + pck_inj[i]->pck_injct_out_size + ); + + free( temp_node ); + + } + } + } + // Check for cleared dependences... or not + if( !reader_throttling ) { + for( i = 0; i < NE; ++i ) { + nt_packets_left |= !queue_empty( waiting[i] ); + node_t* temp = waiting[i]->head; + while( temp != NULL ) { + queue_node_t* temp_node = (queue_node_t*) temp->elem; + packet = temp_node->packet; + temp = temp->next; + if( nt_dependencies_cleared( packet ) ) { + // remove from waiting + queue_remove( waiting[i], temp_node ); + // add to inject + queue_node_t* new_node = (queue_node_t*) nt_checked_malloc( sizeof(queue_node_t) ); + new_node->packet = packet; + new_node->cycle = nt_cycle + L2_LATENCY; + queue_push( inject[i], new_node, new_node->cycle ); + free( temp_node ); + } + } + } + } + nt_cycle++; } void netrace_posedge_event(){ - unsigned int i; - clk = 1; // Toggle clock - update_all_router_stat(); - for(i=0;idest_e_addr); - if((strcmp (SELF_LOOP_EN,"NO")==0)) DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,core_num); + if(SELF_LOOP_EN==0) DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,core_num); DEST_ADDR_IS_ZERO(a,traffic[core_num]->dest_e_addr); //rnd = rand() & ~(0x1<dest_e_addr); DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,0); - if((strcmp (SELF_LOOP_EN,"NO")==0)) DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,self_node_addr); + if(SELF_LOOP_EN==0) DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,self_node_addr); //rnd = rand() & ~((0x1<<(self_node_addr+1))|0x1); // generate a random multicast destination. remove the current node flag and unicast_flag from destination list //rnd &= ((1<<(MCAST_PRTLw+1)) -1); //printf("rnd=%d\n",rnd); @@ -425,7 +425,7 @@ void pck_dst_gen ( unsigned int core_num, unsigned char * inject_en) { unsigned int rnd = rand() % 100; // 0~99 if(rnd >= mcast.ratio){ //send a unicast packet - if((strcmp (SELF_LOOP_EN,"NO")==0) && dest_id==core_num){ + if(SELF_LOOP_EN==0 && dest_id==core_num){ *inject_en=0; return; } @@ -1259,7 +1259,7 @@ void print_parameter (){ printf ("\tSSA_EN enabled:%s \n",SSA_EN); printf ("\tSwitch allocator arbitration type:%s \n",SWA_ARBITER_TYPE); printf ("\tMinimum supported packet size:%d flit(s) \n",MIN_PCK_SIZE); - printf ("\tLoop back is enabled:%s \n",SELF_LOOP_EN); + printf ("\tLoop back is enabled:%d \n",SELF_LOOP_EN); printf ("\tNumber of multihop bypass (SMART max):%d \n",SMART_MAX); printf ("\tCastying type:%s.\n",CAST_TYPE); if (IS_MCAST_PARTIAL){ diff --git a/mpsoc/src_verilator/simulator.h b/mpsoc/src_verilator/simulator.h index ddffd98..ddf36ef 100644 --- a/mpsoc/src_verilator/simulator.h +++ b/mpsoc/src_verilator/simulator.h @@ -1,51 +1,51 @@ #ifndef SIMULATOR_H - #define SIMULATOR_H + #define SIMULATOR_H #if (__cplusplus > 201103L) //"C++11\n"; - void* operator new(std::size_t size, std::align_val_t align) { - #if defined(_WIN32) || defined(__CYGWIN__) - auto ptr = _aligned_malloc(size, static_cast(align)); - #else - auto ptr = aligned_alloc(static_cast(align), size); - #endif - - if (!ptr) - throw std::bad_alloc{}; - /* - std::cout << "new: " << size << ", align: " - << static_cast(align) - << ", ptr: " << ptr << '\n'; - */ - return ptr; - - } - - void operator delete(void* ptr, std::size_t size, std::align_val_t align) noexcept { - /* - std::cout << "delete: " << size << ", align: " - << static_cast(align) - << ", ptr : " << ptr << '\n'; - */ - #if defined(_WIN32) || defined(__CYGWIN__) - _aligned_free(ptr); - #else - free(ptr); - #endif - } - - void operator delete(void* ptr, std::align_val_t align) noexcept { - /* std::cout << "delete: align: " - << static_cast(align) - << ", ptr : " << ptr << '\n'; - */ - #if defined(_WIN32) || defined(__CYGWIN__) - _aligned_free(ptr); - #else - free(ptr); - #endif - } + void* operator new(std::size_t size, std::align_val_t align) { + #if defined(_WIN32) || defined(__CYGWIN__) + auto ptr = _aligned_malloc(size, static_cast(align)); + #else + auto ptr = aligned_alloc(static_cast(align), size); + #endif + + if (!ptr) + throw std::bad_alloc{}; + /* + std::cout << "new: " << size << ", align: " + << static_cast(align) + << ", ptr: " << ptr << '\n'; + */ + return ptr; + + } + + void operator delete(void* ptr, std::size_t size, std::align_val_t align) noexcept { + /* + std::cout << "delete: " << size << ", align: " + << static_cast(align) + << ", ptr : " << ptr << '\n'; + */ + #if defined(_WIN32) || defined(__CYGWIN__) + _aligned_free(ptr); + #else + free(ptr); + #endif + } + + void operator delete(void* ptr, std::align_val_t align) noexcept { + /* std::cout << "delete: align: " + << static_cast(align) + << ", ptr : " << ptr << '\n'; + */ + #if defined(_WIN32) || defined(__CYGWIN__) + _aligned_free(ptr); + #else + free(ptr); + #endif + } #endif @@ -61,8 +61,8 @@ #define SYNFUL 3 //injector type -#define PCK_INJECTOR 0 -#define TRFC_INJECTOR 1 +#define PCK_INJECTOR 0 +#define TRFC_INJECTOR 1 #define STND_DEV_EN 1 @@ -73,44 +73,41 @@ int ENDP_TYPE =TRFC_INJECTOR; int get_router_num (int , int ); - + - #define ideal_port router_top_v__DOT__router__DOT__router_is_ideal - #define active_port router_top_v__DOT__router__DOT__nb_router_active - #define pck_active_port packet_injector_verilator__DOT__endp_is_active - #define traffic_active_port traffic_gen_top__DOT__endp_is_active + #define ideal_port router_top_v__DOT__router__DOT__router_is_ideal + #define active_port router_top_v__DOT__router__DOT__nb_router_active + #define pck_active_port packet_injector_verilator__DOT__endp_is_active + #define traffic_active_port traffic_gen_top__DOT__endp_is_active - #define CHAN_SIZE sizeof(router1[0]->chan_in[0]) + #define CHAN_SIZE sizeof(router1[0]->chan_in[0]) - #define conect_r2r(T1,r1,p1,T2,r2,p2) \ - memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE ) + #define conect_r2r(T1,r1,p1,T2,r2,p2) \ + memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE ) -// router_is_active[get_router_num(T1,r1)] |=(( router##T1 [r1]-> ideal_port!=0) | (router##T2 [r2]-> active_port[p2]==1)) +// router_is_active[get_router_num(T1,r1)] |=(( router##T1 [r1]-> ideal_port!=0) | (router##T2 [r2]-> active_port[p2]==1)) - #define connect_r2gnd(T,r,p)\ - memset(&router##T [r]->chan_in [p],0x00,CHAN_SIZE); + #define connect_r2gnd(T,r,p)\ + memset(&router##T [r]->chan_in [p],0x00,CHAN_SIZE); - #define connect_r2e(T,r,p,e) \ - void * addr1, * addr2;\ - addr1=(ENDP_TYPE == PCK_INJECTOR)? &pck_inj[e]->chan_out : &traffic[e]->chan_out;\ - addr2=(ENDP_TYPE == PCK_INJECTOR)? &pck_inj[e]->chan_in : &traffic[e]->chan_in;\ - memcpy(&router##T [r]->chan_in[p], addr1, CHAN_SIZE );\ - memcpy(addr2, &router##T [r]->chan_out[p], CHAN_SIZE ) + #define connect_r2e(T,r,p,e) \ + void * addr1, * addr2;\ + addr1=(ENDP_TYPE == PCK_INJECTOR)? &pck_inj[e]->chan_out : &traffic[e]->chan_out;\ + addr2=(ENDP_TYPE == PCK_INJECTOR)? &pck_inj[e]->chan_in : &traffic[e]->chan_in;\ + memcpy(&router##T [r]->chan_in[p], addr1, CHAN_SIZE );\ + memcpy(addr2, &router##T [r]->chan_out[p], CHAN_SIZE ) -// router_is_active[get_router_num(T,r)] |= (ENDP_TYPE == PCK_INJECTOR)? \ - (( router##T [r]-> ideal_port!=0) | (pck_inj[e]->pck_active_port==1)):\ - (( router##T [r]-> ideal_port!=0) | (traffic[e]->traffic_active_port==1)) +// router_is_active[get_router_num(T,r)] |= (ENDP_TYPE == PCK_INJECTOR)? \ + (( router##T [r]-> ideal_port!=0) | (pck_inj[e]->pck_active_port==1)):\ + (( router##T [r]-> ideal_port!=0) | (traffic[e]->traffic_active_port==1)) - - - -#define IS_SELF_LOOP_EN (strcmp(SELF_LOOP_EN ,"YES")==0) +#define IS_SELF_LOOP_EN SELF_LOOP_EN #define IS_UNICAST (strcmp(CAST_TYPE,"UNICAST")==0) #define IS_MCAST_FULL (strcmp(CAST_TYPE,"MULTICAST_FULL")==0) #define IS_MCAST_PARTIAL (strcmp(CAST_TYPE,"MULTICAST_PARTIAL")==0) @@ -123,7 +120,7 @@ int get_router_num (int , int ); int reset,clk; -Vtraffic *traffic[NE]; // for synthetic and trace traffic pattern +Vtraffic *traffic[NE]; // for synthetic and trace traffic pattern Vpck_inj *pck_inj[NE]; // for netrace @@ -147,38 +144,38 @@ unsigned int random_var[NE] = {100}; typedef struct statistic_struct { - unsigned int pck_num; - unsigned int flit_num; - unsigned int worst_latency; - unsigned int min_latency; - double sum_clk_h2h; - double sum_clk_h2t; - double sum_clk_per_hop; + unsigned int pck_num; + unsigned int flit_num; + unsigned int worst_latency; + unsigned int min_latency; + double sum_clk_h2h; + double sum_clk_h2t; + double sum_clk_per_hop; #if (STND_DEV_EN) - double sum_clk_pow2; + double sum_clk_pow2; #endif } statistic_t; typedef struct avg_st_struct { - double avg_latency_per_hop; - double avg_latency_flit; - double avg_latency_pck; - double avg_throughput; - double avg_pck_siz; + double avg_latency_per_hop; + double avg_latency_flit; + double avg_latency_pck; + double avg_throughput; + double avg_pck_siz; #if (STND_DEV_EN) - double std_dev; + double std_dev; #endif } avg_st_t; #define BYPASS_LSB 7 -#define FLIT_IN_WR_FLG (1<<6) -#define PCK_IN_WR_FLG (1<<5) -#define FLIT_OUT_WR_FLG (1<<4) -#define PCK_OUT_WR_FLG (1<<3) -#define FLIT_IN_BYPASSED (1<<2) +#define FLIT_IN_WR_FLG (1<<6) +#define PCK_IN_WR_FLG (1<<5) +#define FLIT_OUT_WR_FLG (1<<4) +#define PCK_OUT_WR_FLG (1<<3) +#define FLIT_IN_BYPASSED (1<<2) #define ACTIVE_HIGH_RST (1<<1) #define EMPTY_FLG (1<<0) @@ -186,13 +183,13 @@ typedef struct avg_st_struct { typedef struct router_st_struct { - unsigned int pck_num_in; - unsigned int flit_num_in; - unsigned int pck_num_out; - unsigned int flit_num_out; - unsigned int flit_num_in_bypassed; - unsigned int flit_num_in_buffered; - unsigned int bypass_counter [SMART_NUM+1 ] ; + unsigned int pck_num_in; + unsigned int flit_num_in; + unsigned int pck_num_out; + unsigned int flit_num_out; + unsigned int flit_num_in_bypassed; + unsigned int flit_num_in_buffered; + unsigned int bypass_counter [SMART_NUM+1 ] ; } router_st_t; alignas(64) router_st_t router_stat [NR][MAX_P]; @@ -200,24 +197,24 @@ router_st_t router_stat_accum [NR]; #if (C>1) - statistic_t sent_stat [NE][C]; - statistic_t rsvd_stat [NE][C]; + statistic_t sent_stat [NE][C]; + statistic_t rsvd_stat [NE][C]; #else - statistic_t sent_stat [NE]; - statistic_t rsvd_stat [NE]; + statistic_t sent_stat [NE]; + statistic_t rsvd_stat [NE]; #endif - statistic_t endp_to_endp [NE][NE]; + statistic_t endp_to_endp [NE][NE]; typedef struct mcast_struct { - int ratio; - int min; - int max; + int ratio; + int min; + int max; }mcast_t; -void update_statistic_at_ejection ( int , unsigned int, unsigned int, unsigned int, unsigned int, unsigned int ,unsigned int); -void update_noc_statistic ( int); +void update_statistic_at_ejection ( int , unsigned int, unsigned int, unsigned int, unsigned int, unsigned int ,unsigned int); +void update_noc_statistic ( int); unsigned char pck_class_in_gen(unsigned int); unsigned int pck_dst_gen_task_graph ( unsigned int, unsigned char *); void print_statistic (void); @@ -253,7 +250,7 @@ void update_traffic_injector_st (unsigned int ); #include "netrace_lib.h" #include "synful_wrapper.h" -#define RATIO_INIT 2 +#define RATIO_INIT 2 #define DISABLE -1 #define MY_VL_SETBIT_W(data,bit) (data[VL_BITWORD_I(bit)] |= (VL_UL(1) << VL_BITBIT_I(bit))) @@ -278,12 +275,12 @@ unsigned int saved_time = 0; unsigned int sum_clk_h2h=0; unsigned int sum_clk_h2t=0; -double sum_clk_per_hop=0; +double sum_clk_per_hop=0; const int CC=(C==0)? 1 : C; unsigned int total_rsv_pck_num_per_class[CC]={0}; unsigned int sum_clk_h2h_per_class[CC]={0}; unsigned int sum_clk_h2t_per_class[CC]={0}; -double sum_clk_per_hop_per_class[CC]={0}; +double sum_clk_per_hop_per_class[CC]={0}; unsigned int clk_counter,ideal_rsv_cnt; unsigned int count_en; @@ -311,64 +308,64 @@ mcast_t mcast; #if (STND_DEV_EN) - //#include - double sqroot (double s){ - int i; - double root = s/3; - if (s<=0) return 0; - for(i=0;i<32;i++) root = (root +s/root)/2; - return root; - } - - double sum_clk_pow2=0; - double sum_clk_pow2_per_class[C]; - double standard_dev( double , unsigned int, double); + //#include + double sqroot (double s){ + int i; + double root = s/3; + if (s<=0) return 0; + for(i=0;i<32;i++) root = (root +s/root)/2; + return root; + } + + double sum_clk_pow2=0; + double sum_clk_pow2_per_class[C]; + double standard_dev( double , unsigned int, double); #endif - // set data[bit] to 1 - #define VL_BIT_SET_I(data, bit) data |= (VL_UL(1) << VL_BITBIT_I(bit)) - #define VL_BIT_SET_Q(data, bit) data |= (1ULL << VL_BITBIT_Q(bit)) - #define VL_BIT_SET_E(data, bit) data |= (VL_EUL(1) << VL_BITBIT_E(bit)) - #define VL_BIT_SET_W(data, bit) (data)[VL_BITWORD_E(bit)] |= (VL_EUL(1) << VL_BITBIT_E(bit)) - - // set data[bit] to 0 - #define VL_BIT_CLR_I(data, bit) data &= ~(VL_UL(1) << VL_BITBIT_I(bit)) - #define VL_BIT_CLR_Q(data, bit) data &= ~(1ULL << VL_BITBIT_Q(bit)) - #define VL_BIT_CLR_E(data, bit) data &= ~ (VL_EUL(1) << VL_BITBIT_E(bit)) - #define VL_BIT_CLR_W(data, bit) (data)[VL_BITWORD_E(bit)] &= ~ (VL_EUL(1) << VL_BITBIT_E(bit)) - - - #if (DAw<=VL_IDATASIZE) - #define DEST_ADDR_BIT_SET(data, bit) VL_BIT_SET_I(data, bit) - #define DEST_ADDR_BIT_CLR(data, bit) VL_BIT_CLR_I(data, bit) - #define DEST_ADDR_ASSIGN_RAND(data) data = rand() & ((1< @@ -19,162 +19,162 @@ extern queue_t** synful_inject; void synful_init(char * fname, bool ss_exit, int seed,unsigned int max_clk, unsigned int max_pck){ - //std::cout << "Initiating synful with: " << fname << "random seed:" << seed << std::endl; + //std::cout << "Initiating synful with: " << fname << "random seed:" << seed << std::endl; synful_model_init(fname, ss_exit,seed,max_clk, max_pck, traffic_model_mapping ); - synful_inject = (queue_t**) malloc( NE * sizeof(queue_t*) ); - synful_traverse = (queue_t**) malloc( NE * sizeof(queue_t*) ); - - if(synful_inject == NULL || synful_traverse == NULL ) { - printf( "ERROR: malloc fail queues\n" ); - exit(0); - } - for(int i = 0; i < NE; ++i ) { - synful_inject[i] = queue_new(); - synful_traverse[i] = queue_new(); - } + synful_inject = (queue_t**) malloc( NE * sizeof(queue_t*) ); + synful_traverse = (queue_t**) malloc( NE * sizeof(queue_t*) ); + + if(synful_inject == NULL || synful_traverse == NULL ) { + printf( "ERROR: malloc fail queues\n" ); + exit(0); + } + for(int i = 0; i < NE; ++i ) { + synful_inject[i] = queue_new(); + synful_traverse[i] = queue_new(); + } } void synful_final_report(){ - int i; + int i; - if(verbosity==1) printf("\e[?25h");//To re-enable the cursor: - printf("\nSynful simulation results-------------------\n" - "\tSimulation clock cycles: %llu\n" - ,synful_cycle); - print_statistic_new (synful_cycle); + if(verbosity==1) printf("\e[?25h");//To re-enable the cursor: + printf("\nSynful simulation results-------------------\n" + "\tSimulation clock cycles: %llu\n" + ,synful_cycle); + print_statistic_new (synful_cycle); } void synful_eval( ){ - int i; - unsigned int pronoc_src_id,pronoc_dst_id; - - if((reset==reset_active_high) || (count_en==0)) return; - - if((( synful_cycle > sim_end_clk_num) || (total_sent_pck_num>= end_sim_pck_num )) && synful_packets_left==0 ) simulation_done=1; - - // Reset packets remaining check - synful_packets_left = 0; - - synful_run_one_cycle (); - - - // Inject where possible (max one per node) - for( i = 0; i < NE; ++i ) { - synful_packets_left |= !queue_empty( synful_inject[i] ); - - //TODO define sent vc policy - int sent_vc = 0; - - if(pck_inj[i]->pck_injct_in_pck_wr){ - //the wr_pck should be asserted only for single cycle - pck_inj[i]->pck_injct_in_pck_wr = 0; - continue; - } - - pck_inj[i]->pck_injct_in_pck_wr = 0; - if((pck_inj[i]->pck_injct_out_ready & (0x1<1) { - printf( "Inject: %llu ", synful_cycle ); - synful_print_packet( temp_node ); - } - temp_node = (pronoc_pck_t*) queue_pop_front( synful_inject[i] ); - - pronoc_dst_id = traffic_model_mapping[temp_node->dest]; - queue_push( synful_traverse[pronoc_dst_id], temp_node, synful_cycle ); - int flit_num = temp_node->packetSize / synful_flitw ; - if (flit_num*synful_flitw !=temp_node->packetSize) flit_num++; - if (flit_num < pck_inj[i]->min_pck_size) flit_num = pck_inj[i]->min_pck_size; - - if(IS_SELF_LOOP_EN ==0){ - if(pronoc_dst_id == i ){ - fprintf(stderr,"ERROR: ProNoC is not configured with self-loop enable and Netrace aims to inject\n a " - "packet with identical source and destination address. Enable the SELF_LOOP parameter\n" - "in ProNoC and rebuild the simulation model\n"); - exit(1); - } - } - - unsigned int sent_class =0; - long int ptr_addr = reinterpret_cast (temp_node); - pck_inj[i]->pck_injct_in_data = ptr_addr; - pck_inj[i]->pck_injct_in_size = flit_num; - pck_inj[i]->pck_injct_in_endp_addr = endp_addr_encoder(pronoc_dst_id); - pck_inj[i]->pck_injct_in_class_num = sent_class; - pck_inj[i]->pck_injct_in_init_weight = 1; - pck_inj[i]->pck_injct_in_vc = 0x1<pck_injct_in_pck_wr = 1; - total_sent_pck_num++; - - #if (C>1) - sent_stat[i][sent_class].pck_num ++; - sent_stat[i][sent_class].flit_num +=flit_num; - #else - sent_stat[i].pck_num ++; - sent_stat[i].flit_num +=flit_num; - #endif - }//temp!=NULL - }//inject - - - - // Step all network components, Eject where possible - for( i = 0; i < NE; ++i ) { - synful_packets_left |= !queue_empty( synful_traverse[i] ); - //check which pck injector got a packet - if(pck_inj[i]->pck_injct_out_pck_wr==0) continue; - //we have got a packet - //printf( "data=%lx\n",pck_inj[i]->pck_injct_out_data); - - pronoc_pck_t* temp_node = (pronoc_pck_t*) pck_inj[i]->pck_injct_out_data; - if( temp_node != NULL ) { - if(verbosity>1) { - printf( "Eject: %llu ", synful_cycle ); - synful_print_packet(temp_node); - } - //send it to synful - synful_Eject (temp_node); - - // remove from traverse - - queue_remove( synful_traverse[i], temp_node ); - unsigned long long int clk_num_h2t= (synful_cycle - temp_node->cycle); - unsigned int clk_num_h2h= clk_num_h2t - pck_inj[i]->pck_injct_out_h2t_delay; - /* - printf("clk_num_h2t (%llu) h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); - if(clk_num_h2t < pck_inj[i]->pck_injct_out_h2t_delay){ - fprintf(stderr, "ERROR:clk_num_h2t (%llu) is smaller than injector h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); - exit(1); - } - */ - pronoc_src_id=traffic_model_mapping[temp_node->source]; - update_statistic_at_ejection ( - i,// core_num - clk_num_h2h, // clk_num_h2h, - (unsigned int) clk_num_h2t, // clk_num_h2t, - pck_inj[i]->pck_injct_out_distance, // distance, - pck_inj[i]->pck_injct_out_class_num,// class_num, - pronoc_src_id, //temp_node->source - pck_inj[i]->pck_injct_out_size - ); - - free( temp_node ); - - }//emp_node != NULL - }//for - - synful_cycle++; - - //std::cout << synful_cycle << std::endl; + int i; + unsigned int pronoc_src_id,pronoc_dst_id; + + if((reset==reset_active_high) || (count_en==0)) return; + + if((( synful_cycle > sim_end_clk_num) || (total_sent_pck_num>= end_sim_pck_num )) && synful_packets_left==0 ) simulation_done=1; + + // Reset packets remaining check + synful_packets_left = 0; + + synful_run_one_cycle (); + + + // Inject where possible (max one per node) + for( i = 0; i < NE; ++i ) { + synful_packets_left |= !queue_empty( synful_inject[i] ); + + //TODO define sent vc policy + int sent_vc = 0; + + if(pck_inj[i]->pck_injct_in_pck_wr){ + //the wr_pck should be asserted only for single cycle + pck_inj[i]->pck_injct_in_pck_wr = 0; + continue; + } + + pck_inj[i]->pck_injct_in_pck_wr = 0; + if((pck_inj[i]->pck_injct_out_ready & (0x1<1) { + printf( "Inject: %llu ", synful_cycle ); + synful_print_packet( temp_node ); + } + temp_node = (pronoc_pck_t*) queue_pop_front( synful_inject[i] ); + + pronoc_dst_id = traffic_model_mapping[temp_node->dest]; + queue_push( synful_traverse[pronoc_dst_id], temp_node, synful_cycle ); + int flit_num = temp_node->packetSize / synful_flitw ; + if (flit_num*synful_flitw !=temp_node->packetSize) flit_num++; + if (flit_num < pck_inj[i]->min_pck_size) flit_num = pck_inj[i]->min_pck_size; + + if(SELF_LOOP_EN ==0){ + if(pronoc_dst_id == i ){ + fprintf(stderr,"ERROR: ProNoC is not configured with self-loop enable and Netrace aims to inject\n a " + "packet with identical source and destination address. Enable the SELF_LOOP parameter\n" + "in ProNoC and rebuild the simulation model\n"); + exit(1); + } + } + + unsigned int sent_class =0; + long int ptr_addr = reinterpret_cast (temp_node); + pck_inj[i]->pck_injct_in_data = ptr_addr; + pck_inj[i]->pck_injct_in_size = flit_num; + pck_inj[i]->pck_injct_in_endp_addr = endp_addr_encoder(pronoc_dst_id); + pck_inj[i]->pck_injct_in_class_num = sent_class; + pck_inj[i]->pck_injct_in_init_weight = 1; + pck_inj[i]->pck_injct_in_vc = 0x1<pck_injct_in_pck_wr = 1; + total_sent_pck_num++; + + #if (C>1) + sent_stat[i][sent_class].pck_num ++; + sent_stat[i][sent_class].flit_num +=flit_num; + #else + sent_stat[i].pck_num ++; + sent_stat[i].flit_num +=flit_num; + #endif + }//temp!=NULL + }//inject + + + + // Step all network components, Eject where possible + for( i = 0; i < NE; ++i ) { + synful_packets_left |= !queue_empty( synful_traverse[i] ); + //check which pck injector got a packet + if(pck_inj[i]->pck_injct_out_pck_wr==0) continue; + //we have got a packet + //printf( "data=%lx\n",pck_inj[i]->pck_injct_out_data); + + pronoc_pck_t* temp_node = (pronoc_pck_t*) pck_inj[i]->pck_injct_out_data; + if( temp_node != NULL ) { + if(verbosity>1) { + printf( "Eject: %llu ", synful_cycle ); + synful_print_packet(temp_node); + } + //send it to synful + synful_Eject (temp_node); + + // remove from traverse + + queue_remove( synful_traverse[i], temp_node ); + unsigned long long int clk_num_h2t= (synful_cycle - temp_node->cycle); + unsigned int clk_num_h2h= clk_num_h2t - pck_inj[i]->pck_injct_out_h2t_delay; + /* + printf("clk_num_h2t (%llu) h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); + if(clk_num_h2t < pck_inj[i]->pck_injct_out_h2t_delay){ + fprintf(stderr, "ERROR:clk_num_h2t (%llu) is smaller than injector h2t_delay(%u)\n", clk_num_h2t , pck_inj[i]->pck_injct_out_h2t_delay); + exit(1); + } + */ + pronoc_src_id=traffic_model_mapping[temp_node->source]; + update_statistic_at_ejection ( + i,// core_num + clk_num_h2h, // clk_num_h2h, + (unsigned int) clk_num_h2t, // clk_num_h2t, + pck_inj[i]->pck_injct_out_distance, // distance, + pck_inj[i]->pck_injct_out_class_num,// class_num, + pronoc_src_id, //temp_node->source + pck_inj[i]->pck_injct_out_size + ); + + free( temp_node ); + + }//emp_node != NULL + }//for + + synful_cycle++; + + //std::cout << synful_cycle << std::endl; } @@ -183,22 +183,22 @@ void synful_eval( ){ void synful_negedge_event( ){ - int i; - clk = 0; - topology_connect_all_nodes (); - //connect_clk_reset_start_all(); - sim_eval_all(); + int i; + clk = 0; + topology_connect_all_nodes (); + //connect_clk_reset_start_all(); + sim_eval_all(); } void synful_posedge_event(){ - unsigned int i; - clk = 1; // Toggle clock - update_all_router_stat(); - synful_eval(); - //connect_clk_reset_start_all(); - sim_eval_all(); - //print total sent packet each 1024 clock cycles - if(verbosity==1) if(synful_cycle&0x3FF) printf("\rTotal sent packet: %9d", total_sent_pck_num); + unsigned int i; + clk = 1; // Toggle clock + update_all_router_stat(); + synful_eval(); + //connect_clk_reset_start_all(); + sim_eval_all(); + //print total sent packet each 1024 clock cycles + if(verbosity==1) if(synful_cycle&0x3FF) printf("\rTotal sent packet: %9d", total_sent_pck_num); } diff --git a/mpsoc/src_verilator/traffic_synthetic.h b/mpsoc/src_verilator/traffic_synthetic.h index baf8875..c1883cb 100755 --- a/mpsoc/src_verilator/traffic_synthetic.h +++ b/mpsoc/src_verilator/traffic_synthetic.h @@ -15,147 +15,146 @@ extern unsigned char NEw; int custom_traffic_table[NE]; typedef struct HOTSPOT_NODE { - int ip_num; - char send_enable; - int percentage; // x10 + int ip_num; + char send_enable; + int percentage; // x10 } hotspot_st; hotspot_st * hotspots; - + unsigned int pck_dst_gen_1D (unsigned int, unsigned char *); // number, b:bit location W: number width log2(num) int getBit(int num, int b, int W) { - while(b<0) b+=W; - b%=W; - return (num >> b) & 0x1; + while(b<0) b+=W; + b%=W; + return (num >> b) & 0x1; } // number; b:bit location; W: number width log2(num); v: 1 assert the bit, 0 deassert the bit; void setBit(int *num, int b, int W, int v) { while(b<0) b+=W; - b%=W; + b%=W; int mask = 1 << b; //printf("b=%d\n", b); - if (v == 0)*num = *num & ~mask; // assert bit + if (v == 0)*num = *num & ~mask; // assert bit else *num = *num | mask; // deassert bit - } - + unsigned int get_rnd_ip (unsigned int core_num){ - unsigned int rnd=rand()%NE; - if(IS_SELF_LOOP_EN) return rnd; - //make sure its not same as sender core - while (rnd==core_num) rnd=rand()%NE; - return rnd; + unsigned int rnd=rand()%NE; + if(SELF_LOOP_EN) return rnd; + //make sure its not same as sender core + while (rnd==core_num) rnd=rand()%NE; + return rnd; } #if (defined (IS_MESH) || defined (IS_TORUS) || defined (IS_LINE) || defined (IS_RING) ) unsigned int pck_dst_gen_2D (unsigned int core_num, unsigned char * inject_en){ - //for mesh-tori - unsigned int current_l,current_x, current_y; - unsigned int dest_l,dest_x,dest_y; - mesh_tori_addrencod_sep(core_num,¤t_x,¤t_y,¤t_l); - * inject_en=1; - unsigned int rnd=0; - unsigned int rnd100=0; - unsigned int max_percent=100/HOTSPOT_NUM; - int i; - - if((strcmp (TRAFFIC,"RANDOM")==0) || (strcmp (TRAFFIC,"random")==0)){ - //get a random IP core - return endp_addr_encoder(get_rnd_ip(core_num)); - } - - if ((strcmp(TRAFFIC,"HOTSPOT")==0) || (strcmp (TRAFFIC,"hot spot")==0)){ - unsigned int rnd1000=0; - rnd=get_rnd_ip(core_num); - - rnd1000=rand()%1000; // generate a random number between 0 & 1000 - for (i=0;i>1; - mcast_list_array[i*4+2] = (ch & 0x4)>>2; - mcast_list_array[i*4+3] = (ch & 0x8)>>3; - } - }else if(bin){ - for(i=0; i< size; i++) { - unsigned int ch ; - u[0] = t[i]; - sscanf(u , "%x", &ch); - ch&=0xf; - mcast_list_array[i ] = ch; - } - - } - - for (i=0;i>1; + mcast_list_array[i*4+2] = (ch & 0x4)>>2; + mcast_list_array[i*4+3] = (ch & 0x8)>>3; + } + }else if(bin){ + for(i=0; i< size; i++) { + unsigned int ch ; + u[0] = t[i]; + sscanf(u , "%x", &ch); + ch&=0xf; + mcast_list_array[i ] = ch; + } + + } + + for (i=0;i Date: Thu, 29 May 2025 15:38:03 +0200 Subject: [PATCH 031/107] Replace SSA_EN string parameter (YES/NO) with binary (1/0) --- .../Altera/configurations/line4_smart3 | 2 +- .../Altera/configurations/mesh_3x3_v2_ssa | 2 +- .../FPGA-kc07/src/deafult_noc_param | 2 +- .../VCS/configurations/line4_smart3 | 2 +- .../VCS/configurations/mesh_3x3_v2_ssa | 6 +-- mpsoc/Integration_test/deafult_noc_param | 2 +- .../failed-model/mesh_4x4_openpiton_mcast_f | 2 +- .../general/fmesh_1x1_openpiton | 2 +- .../general/fmesh_2x2_openpiton | 2 +- .../general/fmesh_8x8_openpiton | 2 +- .../configurations/general/mesh_2x2_openpiton | 2 +- .../configurations/general/mesh_3x3_v2_ssa | 2 +- .../configurations/general/mesh_4x4_smart3 | 2 +- .../configurations/general/mesh_4x4_v1_B15 | 2 +- .../configurations/general/mesh_8x8_ssa_xy | 2 +- .../configurations/line-ring/line2_openpiton | 2 +- .../configurations/line-ring/line4_smart3 | 2 +- .../configurations/line-ring/line_4_v1_B15 | 2 +- .../configurations/line-ring/line_8x8_ssa_xy | 2 +- mpsoc/perl_gui/lib/emulate/tt.EML | 2 +- mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC | 2 +- mpsoc/perl_gui/lib/multi_nocs/test.phy | 8 ++-- mpsoc/perl_gui/lib/multi_nocs/tt.phy | 8 ++-- mpsoc/perl_gui/lib/netwmaker/custom1.NWM | 2 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 4 +- mpsoc/perl_gui/lib/perl/network_maker.pl | 2 +- mpsoc/perl_gui/lib/soc/mor1k_tile.SOC | 2 +- mpsoc/rtl/arch/flit_buffer_reg_bas.v | 5 +-- mpsoc/rtl/arch/iport_reg_base.sv | 2 +- mpsoc/rtl/src_emulate/rtl/noc_emulator.vold | 14 +++---- mpsoc/rtl/src_noc/crossbar.v | 14 +++---- mpsoc/rtl/src_noc/flit_buffer.sv | 38 ++++++------------- mpsoc/rtl/src_noc/header_flit.sv | 4 +- mpsoc/rtl/src_noc/inout_ports.sv | 6 +-- mpsoc/rtl/src_noc/input_ports.sv | 7 ++-- mpsoc/rtl/src_noc/mesh_torus.sv | 20 +++++----- mpsoc/rtl/src_noc/noc_localparam.v | 2 +- mpsoc/rtl/src_noc/router_top.sv | 5 +-- mpsoc/rtl/src_noc/topology_localparam.v | 4 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 2 +- mpsoc/rtl/src_openpiton/noc_localparam.v | 2 +- mpsoc/script/parameter.sh | 28 +++++--------- mpsoc/script/synfull/noc_localparam.v | 2 +- mpsoc/smart-netrace/src/deafult_noc_param | 2 +- mpsoc/src_c/jtag/jtag_libusb/out | 2 +- mpsoc/src_verilator/simulator.cpp | 2 +- 46 files changed, 98 insertions(+), 135 deletions(-) diff --git a/mpsoc/Integration_test/Altera/configurations/line4_smart3 b/mpsoc/Integration_test/Altera/configurations/line4_smart3 index ca6769d..548c123 100644 --- a/mpsoc/Integration_test/Altera/configurations/line4_smart3 +++ b/mpsoc/Integration_test/Altera/configurations/line4_smart3 @@ -9,7 +9,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"NO\"", + "SSA_EN" => "0", "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } diff --git a/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa index 6838566..fae94ef 100644 --- a/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa +++ b/mpsoc/Integration_test/Altera/configurations/mesh_3x3_v2_ssa @@ -3,7 +3,7 @@ $model = bless( { "T1" => "3", "T2" => "3", "SELF_LOOP_EN" => "1", - "SSA_EN"=> "\"YES\"", + "SSA_EN"=> "1", "LB" => 16, "DEBUG_EN" => "0", "MIN_PCK_SIZE" => "1", diff --git a/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param b/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param index af5b865..d95b510 100644 --- a/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param +++ b/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param @@ -12,7 +12,7 @@ $model = bless( { "PCK_TYPE" => " \"MULTI_FLIT\"", "MIN_PCK_SIZE" => "2", "BYTE_EN" => "0", -"SSA_EN" => "\"NO\"", +"SSA_EN" => "0", "CONGESTION_INDEX" => "3", "ESCAP_VC_MASK" => "2'b01", "VC_REALLOCATION_TYPE" => "\"NONATOMIC\"", diff --git a/mpsoc/Integration_test/VCS/configurations/line4_smart3 b/mpsoc/Integration_test/VCS/configurations/line4_smart3 index ca6769d..548c123 100644 --- a/mpsoc/Integration_test/VCS/configurations/line4_smart3 +++ b/mpsoc/Integration_test/VCS/configurations/line4_smart3 @@ -9,7 +9,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"NO\"", + "SSA_EN" => "0", "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } diff --git a/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa index 4722917..fae94ef 100644 --- a/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa +++ b/mpsoc/Integration_test/VCS/configurations/mesh_3x3_v2_ssa @@ -3,9 +3,9 @@ $model = bless( { "T1" => "3", "T2" => "3", "SELF_LOOP_EN" => "1", - "SSA_EN"=> "\"YES\"", + "SSA_EN"=> "1", "LB" => 16, - "DEBUG_EN" => "0", - "MIN_PCK_SIZE" => "1", + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/deafult_noc_param b/mpsoc/Integration_test/deafult_noc_param index fdbe82b..131a0e5 100644 --- a/mpsoc/Integration_test/deafult_noc_param +++ b/mpsoc/Integration_test/deafult_noc_param @@ -12,7 +12,7 @@ $model = bless({ "PCK_TYPE" => " \"MULTI_FLIT\"", "MIN_PCK_SIZE" => "2", "BYTE_EN" => "0", - "SSA_EN" => "\"NO\"", + "SSA_EN" => "0", "CONGESTION_INDEX" => "3", "ESCAP_VC_MASK" => "2'b01", "VC_REALLOCATION_TYPE" => "\"NONATOMIC\"", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f b/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f index 805d174..3b7ab6a 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f +++ b/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/mesh_4x4_openpiton_mcast_f @@ -7,7 +7,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", "SELF_LOOP_EN" => "1", "CAST_TYPE" => "\"MULTICAST_FULL\"", } diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton index 4c45a74..f80a7c7 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_1x1_openpiton @@ -8,7 +8,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", "SELF_LOOP_EN" => "1", "MIN_PCK_SIZE" => "1" } diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton index 4b300a9..449f321 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_2x2_openpiton @@ -8,7 +8,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton index 9de1472..37c19a2 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_openpiton @@ -8,7 +8,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton index 7d92b59..4b61b2e 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_2x2_openpiton @@ -7,7 +7,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa index fc507e6..1383775 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_3x3_v2_ssa @@ -3,7 +3,7 @@ $model = bless( { "T1" => "3", "T2" => "3", "SELF_LOOP_EN" => "1", - "SSA_EN"=> "\"YES\"", + "SSA_EN"=> "1", "LB" => 16, "DEBUG_EN" => "0", "MIN_PCK_SIZE" => "1", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 index fc638f6..ad8749e 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 @@ -9,7 +9,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"NO\"", + "SSA_EN" => "0", "SELF_LOOP_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 index f3d2143..a07a491 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_v1_B15 @@ -7,7 +7,7 @@ $model = bless( { "B" => "15", "LB" => "15", "Fpay" => "64", - "SSA_EN" => "\"NO\"", + "SSA_EN" => "0", "SELF_LOOP_EN" => "0", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_ssa_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_ssa_xy index 7e36145..02cf843 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_ssa_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_ssa_xy @@ -1,5 +1,5 @@ $model = bless( { 'noc_param'=> { - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton index 7814b63..a0c250a 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line2_openpiton @@ -7,7 +7,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 index ca6769d..548c123 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line4_smart3 @@ -9,7 +9,7 @@ $model = bless( { "B" => "4", "LB" => "16", "Fpay" => "64", - "SSA_EN" => "\"NO\"", + "SSA_EN" => "0", "SELF_LOOP_EN" => "1", "MCAST_ENDP_LIST" => "'b11", } diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 index 7bb248a..5d00709 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4_v1_B15 @@ -8,7 +8,7 @@ $model = bless( { "B" => "15", "LB" => "15", "Fpay" => "64", - "SSA_EN" => "\"NO\"", + "SSA_EN" => "0", "SELF_LOOP_EN" => "0", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8x8_ssa_xy b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8x8_ssa_xy index 436ec4b..5312f79 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8x8_ssa_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8x8_ssa_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"LINE\"", - "SSA_EN" => "\"YES\"", + "SSA_EN" => "1", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/emulate/tt.EML b/mpsoc/perl_gui/lib/emulate/tt.EML index 385d254..2ae815a 100644 --- a/mpsoc/perl_gui/lib/emulate/tt.EML +++ b/mpsoc/perl_gui/lib/emulate/tt.EML @@ -21,7 +21,7 @@ $emulate = bless( { 'noc_param' => { 'AVC_ATOMIC_EN' => 0, 'LB' => '4', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'DEBUG_EN' => '0', 'B' => '4', 'COMBINATION_TYPE' => '"COMB_NONSPEC"', diff --git a/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC b/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC index dcc529a..d1a97f0 100644 --- a/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC +++ b/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC @@ -607,7 +607,7 @@ $mpsoc = bless( { 'WEIGHTw' => '4', 'AVC_ATOMIC_EN' => 0, 'B' => '4', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'ADD_PIPREG_AFTER_CROSSBAR' => '1\'b0', 'MCAST_ENDP_LIST' => '\'hf', 'T2' => '2', diff --git a/mpsoc/perl_gui/lib/multi_nocs/test.phy b/mpsoc/perl_gui/lib/multi_nocs/test.phy index be4db0a..1873cc8 100644 --- a/mpsoc/perl_gui/lib/multi_nocs/test.phy +++ b/mpsoc/perl_gui/lib/multi_nocs/test.phy @@ -29,7 +29,7 @@ $phy = bless( { 'AVC_ATOMIC_EN' => 0, 'WEIGHTw' => '4', 'PCK_TYPE' => '"MULTI_FLIT"', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'Fpay' => '32', 'FIRST_ARBITER_EXT_P_EN' => 1, 'CAST_TYPE' => '"UNICAST"', @@ -59,7 +59,7 @@ $phy = bless( { 'COMBINATION_TYPE' => '"COMB_NONSPEC"', 'FIRST_ARBITER_EXT_P_EN' => 1, 'Fpay' => '32', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'ROUTE_NAME' => '"XY"', 'T2' => '3', 'TOPOLOGY' => '"MESH"', @@ -248,7 +248,7 @@ $phy = bless( { 'T1' => '2', 'ROUTE_NAME' => '"XY"', 'Fpay' => '32', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'FIRST_ARBITER_EXT_P_EN' => 1, 'COMBINATION_TYPE' => '"COMB_NONSPEC"', 'WEIGHTw' => '4', @@ -292,7 +292,7 @@ $phy = bless( { 'ROUTE_NAME' => '"XY"', 'CAST_TYPE' => '"UNICAST"', 'FIRST_ARBITER_EXT_P_EN' => 1, - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'Fpay' => '32', 'PCK_TYPE' => '"MULTI_FLIT"', 'COMBINATION_TYPE' => '"COMB_NONSPEC"', diff --git a/mpsoc/perl_gui/lib/multi_nocs/tt.phy b/mpsoc/perl_gui/lib/multi_nocs/tt.phy index 50a3bc4..b6f0872 100644 --- a/mpsoc/perl_gui/lib/multi_nocs/tt.phy +++ b/mpsoc/perl_gui/lib/multi_nocs/tt.phy @@ -43,7 +43,7 @@ $phy = bless( { 'WEIGHTw' => '4', 'SWA_ARBITER_TYPE' => '"RRA"', 'MIN_PCK_SIZE' => '2', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'TOPOLOGY' => '"MESH"', 'PCK_TYPE' => '"MULTI_FLIT"' }, @@ -208,7 +208,7 @@ $phy = bless( { 'VC_REALLOCATION_TYPE' => '"NONATOMIC"', 'TOPOLOGY' => '"MESH"', 'PCK_TYPE' => '"MULTI_FLIT"', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'MIN_PCK_SIZE' => '2', 'SWA_ARBITER_TYPE' => '"RRA"' }, @@ -240,7 +240,7 @@ $phy = bless( { 'ROUTE_NAME' => '"XY"', 'ESCAP_VC_MASK' => '2\'b01', 'B' => '4', - 'SSA_EN' => '"NO"', + 'SSA_EN' => '0', 'PCK_TYPE' => '"MULTI_FLIT"', 'TOPOLOGY' => '"MESH"', 'SWA_ARBITER_TYPE' => '"RRA"', @@ -306,7 +306,7 @@ $phy = bless( { }, { 'param_name' => 'SSA_EN', - 'value' => '"NO"' + 'value' => 0 }, { 'param_name' => 'SWA_ARBITER_TYPE ', diff --git a/mpsoc/perl_gui/lib/netwmaker/custom1.NWM b/mpsoc/perl_gui/lib/netwmaker/custom1.NWM index caa3d56..cbbb6ec 100644 --- a/mpsoc/perl_gui/lib/netwmaker/custom1.NWM +++ b/mpsoc/perl_gui/lib/netwmaker/custom1.NWM @@ -318,7 +318,7 @@ $nwmaker = bless( { 'value' => '{CVw{1\'b1}}' }, { - 'value' => '"NO"', + 'value' => 0, 'param_name' => 'SSA_EN' }, { diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index c87e64d..99b4a53 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -868,8 +868,8 @@ sub noc_config{ #SSA $label='SSA Enable'; $param='SSA_EN'; - $default='"NO"'; - $content='"YES","NO"'; + $default='0'; + $content='0,1'; $type='Combo-box'; $info="Enable single cycle latency on packets traversing in the same direction using static straight allocator (SSA)"; diff --git a/mpsoc/perl_gui/lib/perl/network_maker.pl b/mpsoc/perl_gui/lib/perl/network_maker.pl index ffaf2c4..8c556a0 100644 --- a/mpsoc/perl_gui/lib/perl/network_maker.pl +++ b/mpsoc/perl_gui/lib/perl/network_maker.pl @@ -39,7 +39,7 @@ sub network_maker_main { {param_name=> "ADD_PIPREG_AFTER_CROSSBAR", value=>0}, {param_name=> "CVw", value=>"(C==0)? V : C * V"}, {param_name=> "CLASS_SETTING ", value=>"{CVw{1\'b1}}"}, - {param_name=> "SSA_EN", value=>'"NO"'}, + {param_name=> "SSA_EN", value=>'0'}, {param_name=> "SWA_ARBITER_TYPE ", value=>'"RRA"'}, {param_name=> "WEIGHTw ", value=>7}, {param_name=> "MIN_PCK_SIZE", value=>2}, diff --git a/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC b/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC index 0c9f513..ae99c39 100644 --- a/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC +++ b/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC @@ -1574,7 +1574,7 @@ For XILINX FPGAs define it as "XILINX_JTAG_WB". In this case, the UART uses BSCA 'value' => '32' }, 'SSA_EN' => { - 'value' => '"NO"' + 'value' => '0' }, 'WEIGHTw' => { 'value' => '4' diff --git a/mpsoc/rtl/arch/flit_buffer_reg_bas.v b/mpsoc/rtl/arch/flit_buffer_reg_bas.v index 65d9323..012c183 100644 --- a/mpsoc/rtl/arch/flit_buffer_reg_bas.v +++ b/mpsoc/rtl/arch/flit_buffer_reg_bas.v @@ -16,9 +16,8 @@ module flit_buffer_reg_base #( parameter DEBUG_EN = 1, parameter C=1, parameter DSTPw=4, - parameter SSA_EN="YES", // "YES" , "NO" + parameter SSA_EN=1, // 1,0 parameter CAST_TYPE="UNI_CAST" - )( din, vc_num_wr, @@ -138,7 +137,7 @@ module flit_buffer_reg_base #( flit_buffer #( .V(V), .B(B), - .SSA_EN("NO"),// should be "NO" even if SSA is enabled + .SSA_EN(0),// should be 0 even if SSA is enabled .Fw(Fw), .PCK_TYPE(PCK_TYPE), .CAST_TYPE(CAST_TYPE), diff --git a/mpsoc/rtl/arch/iport_reg_base.sv b/mpsoc/rtl/arch/iport_reg_base.sv index 591b718..b9e2b16 100644 --- a/mpsoc/rtl/arch/iport_reg_base.sv +++ b/mpsoc/rtl/arch/iport_reg_base.sv @@ -61,7 +61,7 @@ module iport_reg_base #( parameter [CVw-1: 0] CLASS_SETTING = {CVw{1'b1}}, // shows how each class can use VCs parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000, // mask scape vc, valid only for full adaptive parameter DSTPw = P-1, - parameter SSA_EN="YES", // "YES" , "NO" + parameter SSA_EN=1, // 1: enable SSA, 0: disable SSA parameter SWA_ARBITER_TYPE ="RRA",// "RRA","WRRA" parameter WEIGHTw=4, parameter WRRA_CONFIG_INDEX=0, diff --git a/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold b/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold index 446c68f..2a67880 100755 --- a/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold +++ b/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold @@ -9,14 +9,14 @@ module noc_emulator #( //NoC parameters - parameter V = 1, - parameter B = 4, + parameter V = 1, + parameter B = 4, parameter T1 = 4, parameter T2 = 4, parameter T3 = 1, parameter TOPOLOGY = "MESH", parameter ROUTE_NAME = "XY", - parameter C = 4, + parameter C = 4, parameter Fpay = 32, parameter MUX_TYPE = "BINARY", parameter VC_REALLOCATION_TYPE = "NONATOMIC", @@ -27,13 +27,13 @@ module noc_emulator #( parameter AVC_ATOMIC_EN = 1, parameter ADD_PIPREG_AFTER_CROSSBAR = 0, parameter CVw=(C==0)? V : C * V, - parameter [CVw-1: 0] CLASS_SETTING = {CVw{1'b1}}, - parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000, - parameter SSA_EN = "NO", + parameter [CVw-1: 0] CLASS_SETTING = {CVw{1'b1}}, + parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000, + parameter SSA_EN = 0, parameter SWA_ARBITER_TYPE = "RRA", parameter WEIGHTw = 4, parameter MIN_PCK_SIZE = 2, - parameter BYTE_EN=0, + parameter BYTE_EN=0, // simulation diff --git a/mpsoc/rtl/src_noc/crossbar.v b/mpsoc/rtl/src_noc/crossbar.v index 7bf73fe..b12c36f 100755 --- a/mpsoc/rtl/src_noc/crossbar.v +++ b/mpsoc/rtl/src_noc/crossbar.v @@ -30,9 +30,9 @@ module crossbar #( parameter TOPOLOGY = "MESH", parameter V = 4, // vc_num_per_port parameter P = 5, // router port num - parameter Fw = 36, - parameter MUX_TYPE="BINARY", //"ONE_HOT" or "BINARY" - parameter SSA_EN="YES", // "YES" , "NO" + parameter Fw = 36, + parameter MUX_TYPE="BINARY", //"ONE_HOT" or "BINARY" + parameter SSA_EN= 1, // 1: enable SSA, 0: disable SSA parameter SELF_LOOP_EN= 0 )( granted_dest_port_all, @@ -96,12 +96,10 @@ module crossbar #( assign mux_in[i][(j+1)*Fw-1 : j*Fw]= flit_in_all[(j+1)*Fw-1 : j*Fw]; assign mux_sel_pre[i][j] = granted_dest_port[j][i]; end - end//for j + end//for j - /* verilator lint_off WIDTH */ - if (SSA_EN =="YES") begin : predict //If no output is granted replace the output port with SS port - /* verilator lint_on WIDTH */ - add_ss_port #( + if (SSA_EN) begin : predict //If no output is granted replace the output port with SS port + add_ss_port #( .NOC_ID(NOC_ID), .SW_LOC(i), .P(P) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index fd6082c..db5f896 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -384,15 +384,11 @@ module flit_buffer $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,B); $finish; end - /* verilator lint_off WIDTH */ - if (sub_rd[i] && (sub_depth[i] == {DEPTHw{1'b0}} && SSA_EN !="YES" ))begin - /* verilator lint_on WIDTH */ + if (sub_rd[i] && (sub_depth[i] == {DEPTHw{1'b0}} && (SSA_EN != 1) ))begin $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time); $finish; end - /* verilator lint_off WIDTH */ - if (sub_rd[i] && !wr[i] && (sub_depth[i] == {DEPTHw{1'b0}} && SSA_EN =="YES" ))begin - /* verilator lint_on WIDTH */ + if (sub_rd[i] && !wr[i] && (sub_depth[i] == {DEPTHw{1'b0}} && (SSA_EN == 1) ))begin $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time); $finish; end @@ -404,15 +400,11 @@ module flit_buffer $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,B); $finish; end - /* verilator lint_off WIDTH */ - if (rd[i] && (depth[i] == {DEPTHw{1'b0}} && SSA_EN !="YES" ))begin - /* verilator lint_on WIDTH */ + if (rd[i] && (depth[i] == {DEPTHw{1'b0}} && (SSA_EN != 1) ))begin $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time); $finish; end - /* verilator lint_off WIDTH */ - if (rd[i] && !wr[i] && (depth[i] == {DEPTHw{1'b0}} && SSA_EN =="YES" ))begin - /* verilator lint_on WIDTH */ + if (rd[i] && !wr[i] && (depth[i] == {DEPTHw{1'b0}} && (SSA_EN == 1)))begin $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time); $finish; end @@ -434,17 +426,16 @@ endmodule module fifo_ram #( parameter DATA_WIDTH = 32, parameter ADDR_WIDTH = 8, - parameter SSA_EN="YES" // "YES" , "NO" + parameter SSA_EN=1 // 1: enable SSA, 0: disable SSA )( - wr_data, + wr_data, wr_addr, rd_addr, wr_en, rd_en, clk, rd_data -); - +); input [DATA_WIDTH-1 : 0] wr_data; input [ADDR_WIDTH-1 : 0] wr_addr; @@ -465,9 +456,7 @@ module fifo_ram #( end generate - /* verilator lint_off WIDTH */ - if(SSA_EN =="YES") begin :predict - /* verilator lint_on WIDTH */ + if(SSA_EN == 1) begin :predict //add bypass reg [DATA_WIDTH-1:0] bypass_reg; reg rd_en_delayed; @@ -485,16 +474,13 @@ module fifo_ram #( endmodule - /********************* - * * fifo_ram_mem_size - * **********************/ module fifo_ram_mem_size #( parameter DATA_WIDTH = 32, parameter MEM_SIZE = 200, - parameter SSA_EN = "YES" // "YES" , "NO" + parameter SSA_EN = 1 // 1: enable SSA, 0: disable SSA ) ( wr_data, wr_addr, @@ -507,7 +493,7 @@ module fifo_ram_mem_size #( function integer log2; input integer number; begin - log2=(number <=1) ? 1: 0; + log2=(number <=1) ? 1: 0; while(2**log2MIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, MAX_PCK = (VC_REALLOCATION_TYPE== "ATOMIC")? 1 : NON_ATOM_PCKS + OVC_ALLOC_MODE,// min packet size is two hence the max packet number in buffer is (B/2) - IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN=="YES")| SMART_EN)? "YES" : "NO"; - + IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN==1) || (SMART_EN==1))? "YES" : "NO"; - localparam + localparam ELw = log2(T3), Pw = log2(P), - PLw = (TOPOLOGY == "FMESH") ? Pw : ELw, + PLw = (IS_FMESH) ? Pw : ELw, VPLw= V * PLw, PRAw= P * RAw; /* verilator lint_on WIDTH */ diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 3680da3..12c8c42 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -37,7 +37,7 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( parameter ROUTE_TYPE = "FULL_ADAPTIVE", // "FULL_ADAPTIVE", "PAR_ADAPTIVE" parameter V = 4, parameter DSTPw=4, - parameter SSA_EN ="NO", + parameter SSA_EN = 0, parameter PPSw=4, parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000 // mask scape vc, valid only for full adaptive )( @@ -179,7 +179,7 @@ endmodule module mesh_tori_dspt_clear_gen #( - parameter SSA_EN="YES", + parameter SSA_EN = 1, parameter DSTPw =4, parameter SW_LOC=0 )( @@ -195,29 +195,27 @@ module mesh_tori_dspt_clear_gen #( input ssa_ivc_num_getting_ovc_grant; localparam - LOCAL = 3'd0, - EAST = 3'd1, + LOCAL = 3'd0, + EAST = 3'd1, WEST = 3'd3; generate - /* verilator lint_off WIDTH */ - if ( SSA_EN=="YES" ) begin :predict_if - /* verilator lint_on WIDTH */ + if ( SSA_EN==1 ) begin :predict_if if (SW_LOC == LOCAL ) begin :local_if assign destport_clear= (ivc_num_getting_ovc_grant)?{2'b00,sel,~sel} :{DSTPw{1'b0}}; end else if (SW_LOC == EAST || SW_LOC == WEST ) begin :xdir_if assign destport_clear = (ivc_num_getting_ovc_grant)? {2'b00,sel,~sel} : (ssa_ivc_num_getting_ovc_grant)? 4'b0001: //clear b - 4'b0000; + 4'b0000; end else begin : ydir_if assign destport_clear = (ivc_num_getting_ovc_grant)? {2'b00,sel,~sel} : (ssa_ivc_num_getting_ovc_grant)? 4'b0010: //clear a - 4'b0000; + 4'b0000; end end else begin :nopredict_if assign destport_clear = (ivc_num_getting_ovc_grant )? {2'b00,sel,~sel} :{DSTPw{1'b0}}; - end// nopredict_if + end// nopredict_if endgenerate endmodule @@ -1366,7 +1364,7 @@ module mesh_torus_dynamic_portsel_control #( parameter ROUTE_TYPE = "FULL_ADAPTIVE", // "FULL_ADAPTIVE", "PAR_ADAPTIVE" parameter V = 4, parameter DSTPw=4, - parameter SSA_EN ="NO", + parameter SSA_EN = 0, // 1: SSA enabled, 0: SSA disabled parameter PPSw=4, parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000 // mask scape vc, valid only for full adaptive )( diff --git a/mpsoc/rtl/src_noc/noc_localparam.v b/mpsoc/rtl/src_noc/noc_localparam.v index 0b33954..97aa607 100644 --- a/mpsoc/rtl/src_noc/noc_localparam.v +++ b/mpsoc/rtl/src_noc/noc_localparam.v @@ -94,7 +94,7 @@ // Select one of "UNICAST","MULTICAST_PARTIAL","MULTICAST_FULL","BROADCAST_PARTIAL","BROADCAST_FULL" localparam MCAST_ENDP_LIST=32'hf; - localparam SSA_EN="NO"; + localparam SSA_EN=0; //SSA_EN : Enable single cycle latency on packets traversing in the same direction using // static straight allocator (SSA) diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 4079301..8226a8b 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -274,7 +274,7 @@ module router_top #( `ifdef SIMULATION /* verilator lint_off WIDTH */ initial begin - if((SSA_EN=="YES") &&(SMART_EN==1'b1))begin + if((SSA_EN==1) && (SMART_EN==1))begin $display("ERROR: Only one of the SMART or SAA can be enabled at the same time"); $finish; end @@ -286,11 +286,10 @@ module router_top #( $display("ERROR: The minimum packet size must be set as one for single-flit packet type NoC"); $finish; end - if(((SSA_EN=="YES") ||(SMART_EN==1'b1)) && CAST_TYPE!="UNICAST") begin + if(((SSA_EN==1) || (SMART_EN==1)) && CAST_TYPE!="UNICAST") begin $display("ERROR: SMART or SAA do not support muticast/braodcast packets"); $finish; end - end /* verilator lint_on WIDTH */ generate diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index ef12b33..1a7dcbd 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -457,10 +457,10 @@ $display ("\tAVC_ATOMIC_EN:%0d", AVC_ATOMIC_EN); $display ("\tCongestion Index:%0d",CONGESTION_INDEX); $display ("\tADD_PIPREG_AFTER_CROSSBAR:%0d",ADD_PIPREG_AFTER_CROSSBAR); - $display ("\tSSA_EN enabled:%s",SSA_EN); + $display ("\tSSA_EN enabled:%0d",SSA_EN); $display ("\tSwitch allocator arbitration type:%s",SWA_ARBITER_TYPE); $display ("\tMinimum supported packet size:%0d flit(s)",MIN_PCK_SIZE); - $display ("\tLoop back is enabled:%d",SELF_LOOP_EN); + $display ("\tLoop back is enabled:%0d",SELF_LOOP_EN); $display ("\tNumber of multihop bypass (SMART max):%0d",SMART_MAX); $display ("\tCastying type:%s.",CAST_TYPE); if (CAST_TYPE == "MULTICAST_PARTIAL" || CAST_TYPE == "BROADCAST_PARTIAL")begin diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index aff93e5..95c6dc8 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -382,7 +382,7 @@ module traffic_gen_top #( assign ovc_wr_in = (flit_out_wr ) ? wr_vc : {V{1'b0}}; /* verilator lint_off WIDTH */ - //assign wr_vc_is_full = (SSA_EN=="NO")? | ( full_vc & wr_vc) : | (nearly_full_vc & wr_vc); + //assign wr_vc_is_full = (SSA_EN==0)? | ( full_vc & wr_vc) : | (nearly_full_vc & wr_vc); assign wr_vc_is_full = | ( full_vc & wr_vc); /* verilator lint_on WIDTH */ diff --git a/mpsoc/rtl/src_openpiton/noc_localparam.v b/mpsoc/rtl/src_openpiton/noc_localparam.v index efcc911..2f736f4 100644 --- a/mpsoc/rtl/src_openpiton/noc_localparam.v +++ b/mpsoc/rtl/src_openpiton/noc_localparam.v @@ -20,7 +20,7 @@ localparam BYTE_EN=0; localparam CAST_TYPE="UNICAST"; localparam MCAST_ENDP_LIST=10'h3ff; - localparam SSA_EN="YES"; + localparam SSA_EN=1; localparam SMART_MAX=0; localparam CONGESTION_INDEX=3; localparam ESCAP_VC_MASK=1'b1; diff --git a/mpsoc/script/parameter.sh b/mpsoc/script/parameter.sh index 414d85c..262210a 100755 --- a/mpsoc/script/parameter.sh +++ b/mpsoc/script/parameter.sh @@ -30,7 +30,7 @@ CORE_NUM(){ CLASS_SETTING="{CVw{1'b1}}" - SSA_EN="NO" # "YES","NO" + SSA_EN=0 # 1,0 SWA_ARBITER_TYPE="RRA" # "RRA" ,"WRRA" WEIGHTw=4 @@ -41,8 +41,6 @@ CORE_NUM(){ C1_p=0 C2_p=0 C3_p=0 - - # Simulation parameters: AVG_LATENCY_METRIC="HEAD_2_TAIL" @@ -58,15 +56,11 @@ CORE_NUM(){ HOTSPOT_CORE_4=$(CORE_NUM 3 3) HOTSPOT_CORE_5=$(CORE_NUM 2 2) - - - MAX_PCK_NUM=128000 MAX_SIM_CLKs=100000 MAX_PCK_SIZ=10 # maximum flit number in a single packet TIMSTMP_FIFO_NUM=64 - ESCAP_VC_MASK="1" # mask escape vc DEBUG_EN=1 @@ -76,8 +70,6 @@ CORE_NUM(){ # 2: packets are routed to the ports connected to the routers with less active ivc requests # 3: packets are routed to the ports connected to the routers with less active ivc requests that are not granted - - # Simulation C file constant: PACKET_SIZE=2 # packet size in flit. Minimum is 2 @@ -101,7 +93,7 @@ generate_parameter_v (){ printf " parameter VC_REALLOCATION_TYPE=\"$VC_REALLOCATION_TYPE\";\n" >> parameter.v printf " parameter COMBINATION_TYPE=\"$COMBINATION_TYPE\";\n" >> parameter.v printf " parameter FIRST_ARBITER_EXT_P_EN=$FIRST_ARBITER_EXT_P_EN;\n" >> parameter.v - + printf " parameter ROUTE_NAME=\"$ROUTE_NAME\";\n" >> parameter.v printf " parameter CONGESTION_INDEX=$CONGESTION_INDEX;\n" >> parameter.v printf " parameter C0_p=$C0_p;\n" >> parameter.v @@ -130,11 +122,10 @@ generate_parameter_v (){ printf " parameter CVw=(C==0)? V : C * V;\n" >> parameter.v printf " parameter [CVw-1: 0] CLASS_SETTING = $CLASS_SETTING;\n">> parameter.v printf " parameter [V-1 : 0] ESCAP_VC_MASK=$ESCAP_VC_MASK;\n" >> parameter.v - printf " parameter SSA_EN= \"$SSA_EN\";\n">> parameter.v + printf " parameter SSA_EN= $SSA_EN;\n">> parameter.v printf " parameter SWA_ARBITER_TYPE=\"$SWA_ARBITER_TYPE\";\n">> parameter.v - printf " parameter WEIGHTw=$WEIGHTw;\n">> parameter.v - printf " \n\n \`endif " >> parameter.v - + printf " parameter WEIGHTw=$WEIGHTw;\n">> parameter.v + printf " \n\n \`endif " >> parameter.v } @@ -180,9 +171,8 @@ generate_parameter_h (){ printf "\t #define CVw (C==0)? V : C * V\n" >> parameter.h printf "\t #define CLASS_SETTING \"$CLASS_SETTING\"\n">> parameter.h printf "\t #define ESCAP_VC_MASK $ESCAP_VC_MASK\n">> parameter.h - printf "\t #define SSA_EN \"$SSA_EN\"\n" >> parameter.h - printf "\t #define SWA_ARBITER_TYPE \"$SWA_ARBITER_TYPE\"\n">> parameter.h - printf "\t #define WEIGHTw=$WEIGHTw\n">> parameter.h - printf " \n\n #endif " >> parameter.h - + printf "\t #define SSA_EN $SSA_EN\n" >> parameter.h + printf "\t #define SWA_ARBITER_TYPE \"$SWA_ARBITER_TYPE\"\n">> parameter.h + printf "\t #define WEIGHTw=$WEIGHTw\n">> parameter.h + printf " \n\n #endif " >> parameter.h } diff --git a/mpsoc/script/synfull/noc_localparam.v b/mpsoc/script/synfull/noc_localparam.v index 6aac87e..a62a140 100644 --- a/mpsoc/script/synfull/noc_localparam.v +++ b/mpsoc/script/synfull/noc_localparam.v @@ -42,7 +42,7 @@ localparam PCK_TYPE="MULTI_FLIT"; localparam MIN_PCK_SIZE=1; localparam BYTE_EN=0; - localparam SSA_EN="NO"; + localparam SSA_EN=0; localparam SMART_MAX=0; localparam CONGESTION_INDEX=3; localparam ESCAP_VC_MASK=1; diff --git a/mpsoc/smart-netrace/src/deafult_noc_param b/mpsoc/smart-netrace/src/deafult_noc_param index 02ae6d9..1affbb5 100644 --- a/mpsoc/smart-netrace/src/deafult_noc_param +++ b/mpsoc/smart-netrace/src/deafult_noc_param @@ -12,7 +12,7 @@ $model = bless( { "PCK_TYPE" => " \"MULTI_FLIT\"", "MIN_PCK_SIZE" => "2", "BYTE_EN" => "0", -"SSA_EN" => "\"NO\"", +"SSA_EN" => "0", "CONGESTION_INDEX" => "3", "ESCAP_VC_MASK" => "2'b01", "VC_REALLOCATION_TYPE" => "\"NONATOMIC\"", diff --git a/mpsoc/src_c/jtag/jtag_libusb/out b/mpsoc/src_c/jtag/jtag_libusb/out index 906c100..e051380 100644 --- a/mpsoc/src_c/jtag/jtag_libusb/out +++ b/mpsoc/src_c/jtag/jtag_libusb/out @@ -13,7 +13,7 @@ Router parameters: AVC_ATOMIC_EN:0 Congestion Index:3 ADD_PIPREG_AFTER_CROSSBAR:0 - SSA_EN enabled:NO + SSA_EN enabled:0 Switch allocator arbitration type:RRA Simulation parameters diff --git a/mpsoc/src_verilator/simulator.cpp b/mpsoc/src_verilator/simulator.cpp index df970b6..3451cda 100755 --- a/mpsoc/src_verilator/simulator.cpp +++ b/mpsoc/src_verilator/simulator.cpp @@ -1256,7 +1256,7 @@ void print_parameter (){ printf ("\tAVC_ATOMIC_EN:%d \n", AVC_ATOMIC_EN); printf ("\tCongestion Index:%d \n",CONGESTION_INDEX); printf ("\tADD_PIPREG_AFTER_CROSSBAR:%d\n",ADD_PIPREG_AFTER_CROSSBAR); - printf ("\tSSA_EN enabled:%s \n",SSA_EN); + printf ("\tSSA_EN enabled: %d \n",SSA_EN); printf ("\tSwitch allocator arbitration type:%s \n",SWA_ARBITER_TYPE); printf ("\tMinimum supported packet size:%d flit(s) \n",MIN_PCK_SIZE); printf ("\tLoop back is enabled:%d \n",SELF_LOOP_EN); From a9574ee4283580d95206fe9de21753e2c68e230c Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 29 May 2025 17:50:31 +0200 Subject: [PATCH 032/107] fix some vcs linting warnings --- .gitignore | 1 + mpsoc/Integration_test/VCS/run.sh | 52 ++++++++++++++---------- mpsoc/rtl/main_comp.v | 8 ++-- mpsoc/rtl/src_noc/debug.v | 22 +++++----- mpsoc/rtl/src_noc/flit_buffer.sv | 26 ++++-------- mpsoc/rtl/src_noc/input_ports.sv | 4 +- mpsoc/rtl/src_noc/output_ports.sv | 18 ++++---- mpsoc/rtl/src_noc/topology_localparam.v | 8 ++-- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 2 +- mpsoc/rtl/src_synfull/synfull_top.sv | 4 +- 10 files changed, 73 insertions(+), 72 deletions(-) diff --git a/.gitignore b/.gitignore index 82889d0..9f85900 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ mpsoc_work/ mpsoc/rtl/src_openpiton/nocs mpsoc/Integration_test/synthetic_sim/result_logs/* mpsoc/Integration_test/Altera/result_logs/* +mpsoc/Integration_test/VCS/result_logs/* diff --git a/mpsoc/Integration_test/VCS/run.sh b/mpsoc/Integration_test/VCS/run.sh index 170d6c1..97ecf5e 100644 --- a/mpsoc/Integration_test/VCS/run.sh +++ b/mpsoc/Integration_test/VCS/run.sh @@ -6,9 +6,11 @@ SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) # Source the environment variables conf_dir="${SCRPT_DIR_PATH}/configurations" log_dir="${SCRPT_DIR_PATH}/result_logs" -work="${PRONOC_WORK}/verify/vcs" +work="${log_dir}/work" file_list="${SCRPT_DIR_PATH}/src/file_list.f" +export VCS_ARCH_OVERRIDE=linux + mkdir -p $work mkdir -p $log_dir @@ -17,31 +19,37 @@ VCS_WORK_LIB=work VCS_COMMON_ARGS=" -full64 -notice -nc -kdb -timescale=1ps/1ps -sverilog -debug_access +vcs+lic+wait " VCS_ANALYZE_ARGS=" +lint=all,noVCDE,noVNGS,noPCTIO-L,noPCTIO +systemverilogext+.sv -work $VCS_WORK_LIB +warn=all " - vcs_lint () { conf=$1 - if [[ -z "$conf" ]]; then - echo "No configuration provided" - exit 1 - fi - if [[ ! -f "${SCRPT_DIR_PATH}/configurations/$conf" ]]; then - echo "Configuration file ${SCRPT_DIR_PATH}/configurations/$conf does not exist" + conf_file="${conf_dir}/$conf" + log_file="${log_dir}/${conf}.log" + + if [[ ! -f "$conf_file" ]]; then + echo "Configuration file $conf_file does not exist" exit 1 fi - if [[ ! -d "${SCRPT_DIR_PATH}/result_logs" ]]; then - mkdir -p "${SCRPT_DIR_PATH}/result_logs" - fi - conf_file="${SCRPT_DIR_PATH}/configurations/$conf" - log_file="${log_work}/$conf" - - - perl ${SCRPT_DIR_PATH}/src/param_gen.pl $conf_file - - vcs $VCS_COMMON_ARGS $VCS_ANALYZE_ARGS -f $file_list -lint - - -} + perl "${SCRPT_DIR_PATH}/src/param_gen.pl" "$conf_file" + vcs $VCS_COMMON_ARGS $VCS_ANALYZE_ARGS \ + -f "$file_list" \ + -top noc_top \ + -o "$work/simv" \ + -Mdir="$work/csrc" +} -vcs_lint line4_smart3 +for f in "$conf_dir"/*; do + [[ -d "$f" ]] && continue + conf=$(basename "$f") + echo "▶️ Compiling configuration: $conf" + vcs_lint "$conf" > "$log_dir/${conf}.log" 2>&1 + if [[ $? -ne 0 ]]; then + echo "❌ Compilation failed for $conf (check $log_dir/${conf}.log)" + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + exit 1 + else + echo "✅ Compilation successful for $conf" + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + fi + +done diff --git a/mpsoc/rtl/main_comp.v b/mpsoc/rtl/main_comp.v index e837e17..bfa882f 100755 --- a/mpsoc/rtl/main_comp.v +++ b/mpsoc/rtl/main_comp.v @@ -360,7 +360,7 @@ module accumulator #( genvar i; generate for (i=0; i0 )begin - $display("%t ERROR: a header flit is received in an active IVC %m",$time); + $display("%t ERROR: a header flit is received in an active IVC %m",$time); $finish; end if((~hdr_passed & vc_num_tail_wr & ~single_flit_pck )>0 ) begin - $display("%t ERROR: a tail flit is received in an inactive IVC %m",$time); + $display("%t ERROR: a tail flit is received in an inactive IVC %m",$time); $finish; - end + end if ((~hdr_passed & vc_num_bdy_wr )>0)begin - $display("%t ERROR: a body flit is received in an inactive IVC %m",$time); + $display("%t ERROR: a body flit is received in an inactive IVC %m",$time); $finish; end /* verilator lint_off WIDTH */ diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index db5f896..0574bb7 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -548,7 +548,7 @@ endmodule module fwft_fifo #( parameter DATA_WIDTH = 2, parameter MAX_DEPTH = 2, - parameter IGNORE_SAME_LOC_RD_WR_WARNING="YES" // "YES" , "NO" + parameter IGNORE_SAME_LOC_RD_WR_WARNING=1 // 1 : "YES", 0: "NO" ) ( input [DATA_WIDTH-1:0] din, // Data in input wr_en, // Write enable @@ -676,18 +676,15 @@ module fwft_fifo #( $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); $finish; end - /* verilator lint_off WIDTH */ - if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin + if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == 0) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin + if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - /* verilator lint_on WIDTH */ end // always @ (posedge clk) - `endif//SIMULATION endmodule @@ -702,7 +699,7 @@ endmodule module fwft_fifo_with_output_clear #( parameter DATA_WIDTH = 2, parameter MAX_DEPTH = 2, - parameter IGNORE_SAME_LOC_RD_WR_WARNING="NO" // "YES" , "NO" + parameter IGNORE_SAME_LOC_RD_WR_WARNING=0 // 1 : "YES", 0: "NO" ) ( din, // Data in wr_en, // Write enable @@ -851,16 +848,14 @@ module fwft_fifo_with_output_clear #( $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); $finish; end - /* verilator lint_off WIDTH */ - if (rd_en && !recieve_more_than_0 && IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin + if (rd_en && !recieve_more_than_0 && (IGNORE_SAME_LOC_RD_WR_WARNING == 0)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - if (rd_en && ~wr_en && !recieve_more_than_0 && IGNORE_SAME_LOC_RD_WR_WARNING == "YES") begin + if (rd_en && ~wr_en && !recieve_more_than_0 && (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - /* verilator lint_on WIDTH */ end// ~reset end // always @ (posedge clk) `endif // SIMULATION @@ -872,7 +867,7 @@ fwft_fifo_bram module fwft_fifo_bram #( parameter DATA_WIDTH = 2, parameter MAX_DEPTH = 2, - parameter IGNORE_SAME_LOC_RD_WR_WARNING="YES" // "YES" , "NO" + parameter IGNORE_SAME_LOC_RD_WR_WARNING=1 // 1 : "YES" , 0: "NO" ) ( input [DATA_WIDTH-1:0] din, // Data in input wr_en, // Write enable @@ -962,23 +957,20 @@ module fwft_fifo_bram #( assign recieve_more_than_0 = ~ empty; assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); - `ifdef SIMULATION always @(posedge clk) begin if (wr_en & ~rd_en & full) begin $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); $finish; end - /* verilator lint_off WIDTH */ - if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin + if (rd_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == 0)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin + if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - /* verilator lint_on WIDTH */ end // always `endif // SIMULATION diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index a2035b5..71125d7 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -239,7 +239,7 @@ module input_queue_per_port #( OFFSET = (PORT_B%MIN_PCK_SIZE)? 1 :0, NON_ATOM_PCKS = (PORT_B>MIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, MAX_PCK = (VC_REALLOCATION_TYPE== "ATOMIC")? 1 : NON_ATOM_PCKS + OVC_ALLOC_MODE,// min packet size is two hence the max packet number in buffer is (B/2) - IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN==1) || (SMART_EN==1))? "YES" : "NO"; + IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN==1) || (SMART_EN==1))? 1 : 0; localparam ELw = log2(T3), @@ -376,7 +376,7 @@ module input_queue_per_port #( always @ (*)begin iport_weight_next = iport_weight; - if(hdr_flit_wr != {V{1'b0}}) iport_weight_next = (weight_in=={WEIGHTw{1'b0}})? 1 : weight_in; // the minimum weight is 1 + if(hdr_flit_wr != {V{1'b0}}) iport_weight_next = (weight_in=={WEIGHTw{1'b0}})? WEIGHT_INIT : weight_in; // the minimum weight is 1 end diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index 3fe6a29..ccce90e 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -628,7 +628,7 @@ module check_ovc #( ); localparam PV = V * P, - PVV = PV * V, + PVV = PV * V, P_1 = (SELF_LOOP_EN )? P : P-1, PVP_1 = PV * P_1; @@ -645,8 +645,8 @@ module check_ovc #( genvar i; generate for(i=0; i0 && ovc_num[i] >0 && (ovc_num[i] & ovc_status)==0) $display ("%t :Error: OVC status%d missmatch:%b & %b, %m ",$time,i,ovc_num[i] , ovc_status); diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 1a7dcbd..100c376 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -360,18 +360,18 @@ end end end - endfunction + endfunction function automatic integer mcast_partial_width; input [NE-1 : 0] p; - integer i; + integer i; begin mcast_partial_width=0; for (i=0;i Date: Sun, 1 Jun 2025 23:36:56 +0200 Subject: [PATCH 033/107] add histogram to NoC simulator --- mpsoc/src_verilator/histogram.h | 110 +++++++++++++++++++++++++++ mpsoc/src_verilator/netrace_lib.h | 7 -- mpsoc/src_verilator/simulator.cpp | 39 ++-------- mpsoc/src_verilator/simulator.h | 6 +- mpsoc/src_verilator/synful_wrapper.h | 6 +- 5 files changed, 123 insertions(+), 45 deletions(-) create mode 100644 mpsoc/src_verilator/histogram.h diff --git a/mpsoc/src_verilator/histogram.h b/mpsoc/src_verilator/histogram.h new file mode 100644 index 0000000..9a36356 --- /dev/null +++ b/mpsoc/src_verilator/histogram.h @@ -0,0 +1,110 @@ +#ifndef HISTOGRAM_H + #define HISTOGRAM_H +#include +#include +#include + +typedef struct { + int id; // Histogram ID + int value; // Histogram value + int* count; // Pointer to count +} Entry; + +Entry* histogram = NULL; +size_t histogram_size = 0; +size_t histogram_capacity = 0; + +void record(int id,int number) { + // Search for the number + for (size_t i = 0; i < histogram_size; i++) { + if (histogram[i].value == number && histogram[i].id == id) { + (*(histogram[i].count)) += 1; + return; + } + } + + // Not found — add a new entry + if (histogram_size == histogram_capacity) { + histogram_capacity = histogram_capacity == 0 ? 8 : histogram_capacity * 2; + histogram = (Entry*) realloc(histogram, histogram_capacity * sizeof(Entry)); + if (!histogram) { + perror("realloc failed"); + exit(1); + } + } + histogram[histogram_size].id = id; + histogram[histogram_size].value = number; + histogram[histogram_size].count = (int*) malloc(sizeof(int)); + if (!histogram[histogram_size].count) { + perror("malloc failed"); + exit(1); + } + *(histogram[histogram_size].count) = 1; + histogram_size++; +} + +int compare_entries(const void* a, const void* b) { + const Entry* ea = (const Entry*)a; + const Entry* eb = (const Entry*)b; + return (ea->value - eb->value); +} + +void print_histogram(int id, const char* title1, const char* title2) { + // Count how many entries match the histogram ID + size_t count = 0; + for (size_t i = 0; i < histogram_size; i++) { + if (histogram[i].id == id) { + count++; + } + } + + if (count == 0) { + printf("Histogram ID %d not found.\n", id); + return; + } + + // Copy matching entries into a temporary array + Entry* temp = (Entry*) malloc(count * sizeof(Entry)); + if (!temp) { + perror("malloc failed"); + exit(1); + } + + size_t idx = 0; + for (size_t i = 0; i < histogram_size; i++) { + if (histogram[i].id == id) { + temp[idx++] = histogram[i]; + } + } + + // Sort the array by value + qsort(temp, count, sizeof(Entry), compare_entries); + + // Print header + printf("%s", title1); + for (size_t i = 0; i < count; i++) { + printf("%d,", temp[i].value); + } + + // Print counts + printf("%s", title2); + for (size_t i = 0; i < count; i++) { + printf("%d,", *(temp[i].count)); + } + + free(temp); +} + +void cleanup_histogram() { + for (size_t i = 0; i < histogram_size; i++) { + free(histogram[i].count); + } + free(histogram); + histogram = NULL; + histogram_size = 0; + histogram_capacity = 0; +} + + + +#endif // HISTOGRAM_H diff --git a/mpsoc/src_verilator/netrace_lib.h b/mpsoc/src_verilator/netrace_lib.h index f1f33a2..6eb74fc 100644 --- a/mpsoc/src_verilator/netrace_lib.h +++ b/mpsoc/src_verilator/netrace_lib.h @@ -108,13 +108,6 @@ void netrace_init( char * tracefile){ MAX_PACKET_SIZE = (64*8)/Fpay; AVG_PACKET_SIZE=(MIN_PACKET_SIZE+MAX_PACKET_SIZE)/2;// average packet size int p=(MAX_PACKET_SIZE-MIN_PACKET_SIZE)+1; - rsv_size_array = (unsigned int*) calloc ( p , sizeof(int)); - if (rsv_size_array==NULL){ - fprintf(stderr,"ERROR: cannot allocate (%d x int) memory for rsv_size_array. \n",p); - exit(1); - } - - if(verbosity==1) printf("\e[?25l"); //To hide the cursor: } diff --git a/mpsoc/src_verilator/simulator.cpp b/mpsoc/src_verilator/simulator.cpp index 3451cda..bc74bf1 100755 --- a/mpsoc/src_verilator/simulator.cpp +++ b/mpsoc/src_verilator/simulator.cpp @@ -25,7 +25,6 @@ int main(int argc, char** argv) { for(i=0;ipck_number>0) total_active_endp = total_active_endp +1; printf("\nsimulation results-------------------\n"); printf("\tSimulation clock cycles:%d\n",clk_counter); - printf("\n\tTotal received packet in different size:\n"); - printf("\tflit_size,"); - for (i=0;i<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);i++){ - if(rsv_size_array[i]>0) printf("%u,",i+ MIN_PACKET_SIZE); - } - printf("\n\t#pck,"); - for (i=0;i<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);i++){ - if(rsv_size_array[i]>0) printf("%u,",rsv_size_array[i]); - } - printf("\n"); -// printf(" total received flits:%d\n",total_rsv_flit_number); -// printf(" total sent flits:%d\n",total_sent_flit_number); print_statistic_new (clk_counter); } @@ -916,6 +890,7 @@ void sim_final_all (void){ if(ENDP_TYPE == PCK_INJECTOR) for(i=0;ifinal(); else for(i=0;ifinal(); //noc->final(); + cleanup_histogram(); } void connect_clk_reset_start_all(void){ @@ -1065,12 +1040,7 @@ void update_statistic_at_ejection ( unsigned int src, unsigned int pck_size ){ - if(ENDP_TYPE == TRFC_INJECTOR) { - if( traffic[core_num]->pck_size_o >= MIN_PACKET_SIZE && traffic[core_num]->pck_size_o <=MAX_PACKET_SIZE){ - if(rsv_size_array!=NULL) rsv_size_array[traffic[core_num]->pck_size_o-MIN_PACKET_SIZE]++; - } - } - if(verbosity==0 && ( TRAFFIC_TYPE == NETRACE || TRAFFIC_TYPE ==SYNFUL)) if((total_rsv_pck_num & 0X1FFFF )==0 ) printf(" Packets recived total=%u\n",total_rsv_pck_num); + record (PACK_SIZE_HISTO, pck_size); unsigned int latency = (strcmp (AVG_LATENCY_METRIC,"HEAD_2_TAIL")==0)? clk_num_h2t : clk_num_h2h; #if(C>1) update_rsvd_st ( &rsvd_stat[core_num][class_num], clk_num_h2h, clk_num_h2t, latency, distance,pck_size); @@ -1159,6 +1129,9 @@ void merge_statistic (statistic_t * merge_stat, statistic_t stat_in){ void print_statistic_new (unsigned long int total_clk){ int i; + printf("\n\tTotal received packet in different sizes:\n"); + print_histogram(PACK_SIZE_HISTO,"\tflit_size,","\n\t#pck,"); + printf("\n"); print_router_st(); print_endp_to_endp_st("pck_num"); print_endp_to_endp_st("flit_num"); diff --git a/mpsoc/src_verilator/simulator.h b/mpsoc/src_verilator/simulator.h index ddf36ef..896a307 100644 --- a/mpsoc/src_verilator/simulator.h +++ b/mpsoc/src_verilator/simulator.h @@ -134,7 +134,6 @@ unsigned int sim_end_clk_num; unsigned long int nt_tr_list_pck=0; int netrace_speed_up =1; -unsigned int * rsv_size_array; int AVG_PACKET_SIZE=5; int MIN_PACKET_SIZE=5; int MAX_PACKET_SIZE=5; @@ -238,7 +237,6 @@ void update_hotspot(char * ); void update_mcast_traffic(char * str); void initial_threads (void); void print_statistic_new (unsigned long int); -void allocate_rsv_pck_counters (void); void update_all_router_stat(void); void print_router_st(void); void print_endp_to_endp_st(const char *); @@ -250,6 +248,10 @@ void update_traffic_injector_st (unsigned int ); #include "netrace_lib.h" #include "synful_wrapper.h" +#define PACK_SIZE_HISTO 0 + +#include "histogram.h" + #define RATIO_INIT 2 #define DISABLE -1 #define MY_VL_SETBIT_W(data,bit) (data[VL_BITWORD_I(bit)] |= (VL_UL(1) << VL_BITBIT_I(bit))) diff --git a/mpsoc/src_verilator/synful_wrapper.h b/mpsoc/src_verilator/synful_wrapper.h index 40dc236..214a4d2 100644 --- a/mpsoc/src_verilator/synful_wrapper.h +++ b/mpsoc/src_verilator/synful_wrapper.h @@ -22,10 +22,10 @@ void synful_init(char * fname, bool ss_exit, int seed,unsigned int max_clk, unsi //std::cout << "Initiating synful with: " << fname << "random seed:" << seed << std::endl; synful_model_init(fname, ss_exit,seed,max_clk, max_pck, traffic_model_mapping ); - synful_inject = (queue_t**) malloc( NE * sizeof(queue_t*) ); - synful_traverse = (queue_t**) malloc( NE * sizeof(queue_t*) ); + synful_inject = (queue_t**) malloc( NE * sizeof(queue_t*) ); + synful_traverse = (queue_t**) malloc( NE * sizeof(queue_t*) ); - if(synful_inject == NULL || synful_traverse == NULL ) { + if(synful_inject == NULL || synful_traverse == NULL ) { printf( "ERROR: malloc fail queues\n" ); exit(0); } From 1bb3edf395b1810d567ce7022ed87264cdc45a7d Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 2 Jun 2025 18:41:33 +0200 Subject: [PATCH 034/107] fix linting --- mpsoc/rtl/src_noc/router_top.sv | 79 ++++++++++++++-------------- mpsoc/rtl/src_noc/traffic_gen_top.sv | 2 +- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 8226a8b..cc40e15 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -76,30 +76,29 @@ module router_top #( current_r_addr = router_config_in.router_addr; current_r_id = 0; current_r_id [NRw-1 : 0] = router_config_in.router_id; + for( int k=0; k Date: Tue, 3 Jun 2025 14:50:07 +0200 Subject: [PATCH 035/107] set Reset as synchronous by default --- .../Altera/golden_ref/report.csv | 10 +-- mpsoc/Integration_test/Altera/run.sh | 2 +- mpsoc/Integration_test/Altera/src/compare.pl | 76 +++++++++++++++++++ mpsoc/Integration_test/Altera/src/extract.prl | 27 ++++++- mpsoc/clean.sh | 2 - mpsoc/rtl/pronoc_def.v | 6 +- 6 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 mpsoc/Integration_test/Altera/src/compare.pl delete mode 100755 mpsoc/clean.sh diff --git a/mpsoc/Integration_test/Altera/golden_ref/report.csv b/mpsoc/Integration_test/Altera/golden_ref/report.csv index 4a748b5..a9a9cab 100644 --- a/mpsoc/Integration_test/Altera/golden_ref/report.csv +++ b/mpsoc/Integration_test/Altera/golden_ref/report.csv @@ -1,5 +1,5 @@ -File| ALMs:partiallyorcompletelyused| MemoryALUTs| Totalblockmemorybits| M9Kblocks| Dedicatedlogicregisters| CombinationalALUTs| Logicutilization| Maxfrequency -line4_smart3| 1435,18050(8%)| 0,18050(0%)| 5808,2939904(<1%)| 20,319(6%)| 1426,36100(4%)| 1696,36100(5%)| 2460,36100(7%)| 159.64,159.64MHz -mesh_3x3_v2_ssa| 9674,18050(54%)| 0,18050(0%)| 16320,2939904(<1%)| 33,319(10%)| 9856,36100(27%)| 12903,36100(36%)| 15846,36100(44%)| 131.65,131.65MHz -mesh_4x4_2cycle_mcast_f| 12617,18050(70%)| 0,18050(0%)| 33792,2939904(1%)| 128,319(40%)| 8913,36100(25%)| 18343,36100(51%)| 22303,36100(62%)| 139.63,139.63MHz -mesh_4x4_2cycle_xy_v2| 11348,18050(63%)| 0,18050(0%)| 17408,2939904(<1%)| 64,319(20%)| 9732,36100(27%)| 15546,36100(43%)| 18852,36100(52%)| 146.35,146.35MHz +File| ALMs:partiallyorcompletelyused| MemoryALUTs| Warnings| Totalblockmemorybits| M9Kblocks| Dedicatedlogicregisters| CombinationalALUTs| Logicutilization| Maxfrequency +line4_smart3| 1588,18050(9%)| 0,18050(0%)| 140| 5808,2939904(<1%)| 20,319(6%)| 1430,36100(4%)| 2009,36100(6%)| 2787,36100(8%)| 194.33,194.33MHz +mesh_3x3_v2_ssa| 10679,18050(59%)| 0,18050(0%)| 408| 16320,2939904(<1%)| 33,319(10%)| 9864,36100(27%)| 13916,36100(39%)| 17659,36100(49%)| 133.87,133.87MHz +mesh_4x4_2cycle_mcast_f| 13711,18050(76%)| 0,18050(0%)| 729| 33792,2939904(1%)| 128,319(40%)| 8821,36100(24%)| 19404,36100(54%)| 24517,36100(68%)| 145.33,145.33MHz +mesh_4x4_2cycle_xy_v2| 12562,18050(70%)| 0,18050(0%)| 652| 17408,2939904(<1%)| 64,319(20%)| 9716,36100(27%)| 17106,36100(47%)| 21089,36100(58%)| 153.52,153.52MHz diff --git a/mpsoc/Integration_test/Altera/run.sh b/mpsoc/Integration_test/Altera/run.sh index dd89310..2c04070 100755 --- a/mpsoc/Integration_test/Altera/run.sh +++ b/mpsoc/Integration_test/Altera/run.sh @@ -182,5 +182,5 @@ done report_all_configurations -meld "$golden_dir/report.csv" "$log_dir/report.csv" & +perl ${SCRPT_DIR_PATH}/src/compare.pl "$golden_dir/report.csv" "$log_dir/report.csv" echo "All configurations processed. Results are in $log_dir/report.csv" diff --git a/mpsoc/Integration_test/Altera/src/compare.pl b/mpsoc/Integration_test/Altera/src/compare.pl new file mode 100644 index 0000000..3ac795a --- /dev/null +++ b/mpsoc/Integration_test/Altera/src/compare.pl @@ -0,0 +1,76 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Data::Dumper; + +# Usage: perl compare_results.pl file1.txt file2.txt + +my ($file1, $file2) = @ARGV; +die "Usage: $0 file1 file2\n" unless $file1 && $file2; + + +# Parse files normally +my %data1 = parse_file($file1); +my %data2 = parse_file($file2); + +foreach my $design (sort keys %data2) { + my @fields = sort keys %{$data2{$design}}; + print "=== $design ===\n"; + for my $i (@fields) { + my $v1 = $data1{$design}{$i}// 'N/A'; + my $v2 = $data2{$design}{$i}// 'N/A'; + my $delta = + ($v1 eq '0' && $v2 eq '0') ? 0: + ($v1 eq 'N/A' && $v2 eq 'N/A') ? 'N/A' : + ($v1 eq 'N/A' || $v1 eq '0') ? 'N/A' : + ($v2 eq 'N/A' ) ? 'N/A' : + sprintf("%.2f", (($v2 - $v1) / $v1) * 100); + + my $color = ($delta eq 'N/A') ? '' : + (($delta > 0 && $i ne 'Maxfrequency') || ($delta < 0 && $i eq 'Maxfrequency')) ? "\e[31m" : # red for positive + (($delta < 0 && $i ne 'Maxfrequency') || ($delta > 0 && $i eq 'Maxfrequency')) ? "\e[32m" : # green for negative + ""; # default (0) + my $reset = "\e[0m"; + printf "%-25s: %10s -> %10s (%s%s%%%s)\n", $i, $v1, $v2, $color, $delta, $reset; + } + print "\n"; +} + +# Parse and return both field names and data hash +sub parse_file { + my ($fname) = @_; + open my $fh, '<', $fname or die "Cannot open $fname: $!\n"; + + my @fields; + my %results; + + while (<$fh>) { + chomp; + next if /^\s*$/; + if (/^File\|/) { + s/^\s+|\s+$//g; + @fields = split /\|/; + shift @fields; # remove "File" + s/^\s+|\s+$//g for @fields; + next; + } + + my @cols = split /\|/; + s/^\s+|\s+$//g for @cols; + my $name = $cols[0]; + + my @values; + my $num=0; + for my $field (@cols) { + next if($name eq $field); + my ($used) = split /,/, $field; + $results{$name}{$fields[$num]} = $used; + $num++; + } + # print Dumper(\$results{$name}); + } + close $fh; + return (%results); +} + + diff --git a/mpsoc/Integration_test/Altera/src/extract.prl b/mpsoc/Integration_test/Altera/src/extract.prl index a27ee7b..a401c4b 100755 --- a/mpsoc/Integration_test/Altera/src/extract.prl +++ b/mpsoc/Integration_test/Altera/src/extract.prl @@ -22,9 +22,14 @@ my %HWs = ( 'M9K blocks' => ';[[:space:]]*M9K blocks[[:space:]]*;' . $result_reg, ); +my %HIST =( + 'Warnings' => 'Warning[[:space:]]*\(', +); + # Result containers my %freq; my %results; +my %histograms; my $csv = ""; sub extract_results { @@ -37,10 +42,10 @@ sub extract_results { my ($in, $out, $err); $in = 'grep -R "; clk ; ;$" | sort'; run ['bash'], \$in, \$out, \$err, timeout(10) or die "Error running Fmax grep: $?"; - + my $name; for my $line (split "\n", $out) { my ($file) = split '/', $line; - my $name = "${parent}_$file"; + $name = "${parent}_$file"; my @parts = split ':', $line; my @fields = split ';', $parts[1]; @@ -64,7 +69,7 @@ sub extract_results { next unless $line =~ /\.fit\.rpt/; my ($file) = split '/', $line; - my $name = "${parent}_$file"; + $name = "${parent}_$file"; my @fields = split(/\; /, $line); my $value = $fields[2]; @@ -74,6 +79,17 @@ sub extract_results { $results{$metric}{$name} = join(',', @numbers); } } + # -------------------------- + # Count number of warnings/Errors + #--------------------------- + for my $metric (sort keys %HIST) { + my $regex = $HIST{$metric}; + my $grep_cmd = "grep -RE '$regex' | wc -l"; + $out = undef; + run ['bash'], \$grep_cmd, \$out, \$err, timeout(10) or die "Error running grep for $metric: $?"; + $histograms{$metric} = $out; + } + } # Main execution @@ -93,7 +109,10 @@ for my $metric (sort keys %results) { } } -#grep -RE "Warning[[:space:]]*\(" +for my $metric (sort keys %histograms) { + $csv .= "\n$metric |"; + $csv .= " $histograms{$metric}\n"; +} diff --git a/mpsoc/clean.sh b/mpsoc/clean.sh deleted file mode 100755 index 4b53aaa..0000000 --- a/mpsoc/clean.sh +++ /dev/null @@ -1,2 +0,0 @@ -find . -name '*~' -exec rm {} \; -find . -name '*.o' -exec rm {} \; diff --git a/mpsoc/rtl/pronoc_def.v b/mpsoc/rtl/pronoc_def.v index 06d6984..b07089b 100644 --- a/mpsoc/rtl/pronoc_def.v +++ b/mpsoc/rtl/pronoc_def.v @@ -2,10 +2,10 @@ `define PRONOC_DEF // Reset Configurations - // `define SYNC_RESET_MODE + `define SYNC_RESET_MODE /* - * Reset is asynchronous by default. - * Uncomment this line to enable synchronous reset. + * Reset is synchronous by default. + * comment this line to enable synchronous reset. */ // `define ACTIVE_LOW_RESET_MODE From 49234119fb1bda4f3fb76a183a968e54458c614e Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 5 Jun 2025 16:18:50 +0200 Subject: [PATCH 036/107] support vc_static in intigration test --- .gitignore | 7 +- .../VCS/Golden_ref/line4_smart3.log | 1694 ++ .../VCS/Golden_ref/mesh_3x3_v2_ssa.log | 2322 ++ .../Golden_ref/mesh_4x4_2cycle_mcast_f.log | 2060 ++ .../VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log | 3020 +++ .../VCST/Golden_ref/line4_smart3.log | 559 + .../Golden_ref/line4_smart3_vc_static.txt | 17558 ++++++++++++++++ .../VCST/configurations/line4_smart3 | 16 + mpsoc/Integration_test/VCST/run.sh | 56 + mpsoc/Integration_test/VCST/src/file_list.f | 6 + mpsoc/Integration_test/VCST/src/lint.tcl | 55 + .../Integration_test/VCST/src/lint_rules.tcl | 1420 ++ mpsoc/Integration_test/VCST/src/param_gen.pl | 46 + mpsoc/rtl/src_noc/topology_localparam.v | 10 +- 14 files changed, 28819 insertions(+), 10 deletions(-) create mode 100644 mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log create mode 100644 mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log create mode 100644 mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log create mode 100644 mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log create mode 100644 mpsoc/Integration_test/VCST/Golden_ref/line4_smart3.log create mode 100644 mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt create mode 100644 mpsoc/Integration_test/VCST/configurations/line4_smart3 create mode 100644 mpsoc/Integration_test/VCST/run.sh create mode 100644 mpsoc/Integration_test/VCST/src/file_list.f create mode 100644 mpsoc/Integration_test/VCST/src/lint.tcl create mode 100644 mpsoc/Integration_test/VCST/src/lint_rules.tcl create mode 100644 mpsoc/Integration_test/VCST/src/param_gen.pl diff --git a/.gitignore b/.gitignore index 9f85900..addcd4a 100644 --- a/.gitignore +++ b/.gitignore @@ -50,9 +50,6 @@ mpsoc/remove_cycle/__pycache__ mpsoc_work/ mpsoc/rtl/src_openpiton/nocs -mpsoc/Integration_test/synthetic_sim/result_logs/* -mpsoc/Integration_test/Altera/result_logs/* -mpsoc/Integration_test/VCS/result_logs/* - - +mpsoc/Integration_test/**/work +mpsoc/Integration_test/**/result_logs/* diff --git a/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log b/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log new file mode 100644 index 0000000..d85091a --- /dev/null +++ b/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log @@ -0,0 +1,1694 @@ +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 24. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 25. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 26. +Script Path: /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src +confs_dir: /users/amonemi/ProNoC/mpsoc/Integration_test/synthetic_sim/configurations +Root: /users/amonemi/ProNoC/mpsoc +Parsing design file './../../rtl/src_noc/./pronoc_pkg.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './src/noc_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './../../rtl/src_noc/./topology_localparam.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./topology_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing design file './../../rtl/src_noc/./../main_comp.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../main_comp.v'. +Parsing design file './../../rtl/src_noc/./../arbiter.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../arbiter.v'. +Parsing design file './../../rtl/src_noc/./ovc_list.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ovc_list.sv'. +Parsing design file './../../rtl/src_noc/./ss_allocator.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ss_allocator.sv'. +Parsing design file './../../rtl/src_noc/./route_torus.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_torus.v'. +Parsing design file './../../rtl/src_noc/./header_flit.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./header_flit.sv'. +Parsing design file './../../rtl/src_noc/./noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_route.v'. +Parsing design file './../../rtl/src_noc/./comb_nonspec.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_nonspec.sv'. +Parsing design file './../../rtl/src_noc/./inout_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./inout_ports.sv'. +Parsing design file './../../rtl/src_noc/./wrra.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing design file './../../rtl/src_noc/./input_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./input_ports.sv'. +Parsing design file './../../rtl/src_noc/./tree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./tree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_route.v'. +Parsing design file './../../rtl/src_noc/./comb-spec1.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb-spec1.v'. +Parsing design file './../../rtl/src_noc/./combined_vc_sw_alloc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./combined_vc_sw_alloc.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_routting.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_routting.v'. +Parsing design file './../../rtl/src_noc/./comb_spec2.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_spec2.v'. +Parsing design file './../../rtl/src_noc/./route_mesh.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_mesh.v'. +Parsing design file './../../rtl/src_noc/./router_bypass.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_bypass.sv'. +Parsing design file './../../rtl/src_noc/./traffic_gen_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./traffic_gen_top.sv'. +Parsing design file './../../rtl/src_noc/./congestion_analyzer.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./congestion_analyzer.v'. +Parsing design file './../../rtl/src_noc/./output_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./output_ports.sv'. +Parsing design file './../../rtl/src_noc/./routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./routing.v'. +Parsing design file './../../rtl/src_noc/./router_two_stage.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_two_stage.sv'. +Parsing design file './../../rtl/src_noc/./crossbar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./crossbar.v'. +Parsing design file './../../rtl/src_noc/./flit_buffer.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./flit_buffer.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus.sv'. +Parsing design file './../../rtl/src_noc/./debug.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./debug.v'. +Parsing design file './../../rtl/src_noc/./router_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_top.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./star_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./star_noc.sv'. +Parsing design file './../../rtl/src_noc/./fmesh.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fmesh.sv'. +Parsing design file './../../rtl/src_noc/./packet_injector.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./packet_injector.sv'. +Parsing design file './../../rtl/src_noc/./multicast.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./multicast.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v'. +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing_genvar.v' +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing.v' +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v'. +Parsing design file './../../rtl/src_topology/./common/custom_ni_routing.v' +Parsing design file './../../rtl/src_topology/./common/custom_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./common/custom_noc_top.sv'. +Parsing design file './../../rtl/src_topology/./common/custom_lkh_routing.v' +Top Level Modules: + noc_top + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 16 +pronoc_pkg, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 17 +pronoc_pkg, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 18 +pronoc_pkg, "(TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 21 +pronoc_pkg, "(TOPOLOGY == "MULTI_MESH")" + A left 32-bit expression is compared to a right 80-bit expression. + Comparing 'TOPOLOGY' of type string + with '"MULTI_MESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 27 +pronoc_pkg, "(SWA_ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'SWA_ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 28 +pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" + A left 80-bit expression is compared to a right 88-bit expression. + Comparing 'PCK_TYPE' of type string + with '"SINGLE_FLIT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "DUATO")" + A left 16-bit expression is compared to a right 40-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" + A left 16-bit expression is compared to a right 88-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./output_ports.sv, 128 +output_ports, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 131 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC1")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC1"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 167 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC2")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC2"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 241 +input_queue_per_port, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 241 +input_queue_per_port, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 69 +conventional_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 69 +conventional_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 96 +conventional_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 406 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 423 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::ROUTE_NAME == "NCA_STRAIGHT_UP")" + A left 16-bit expression is compared to a right 120-bit expression. + Comparing 'pronoc_pkg::ROUTE_NAME' of type string + with '"NCA_STRAIGHT_UP"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1026 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 638 +mesh_torus_conventional_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 727 +mesh_torus_conventional_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1138 +destp_generator, "(TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1166 +destp_generator, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 721 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 747 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA_CLASSIC")" + A left 24-bit expression is compared to a right 96-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA_CLASSIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 146 +mesh_torus_deterministic_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 146 +mesh_torus_deterministic_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 368 +mesh_torus_next_router_addr_predictor, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 368 +mesh_torus_next_router_addr_predictor, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + +TimeScale is 1 ns / 1 ps + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "BROADCAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"BROADCAST_PARTIAL"' of type string. + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 328 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 332 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 352 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 356 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./pronoc_pkg.sv, 300 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 1-bit LHS target: + Source info: hetero_ovc_unary = ((HETERO_VC == 0) ? {V {1'b1}} : ((HETERO_VC + == 1) ? ((1 << VC_CONFIG_TABLE[router_id][0]) - 1) : ((1 << + VC_CONFIG_TABLE[router_id][router_ ... + Expression: hetero_ovc_unary + + +Lint-[UI] Unused input +./../../rtl/src_noc/./router_bypass.sv, 175 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 555 + Following is an unused input. + Source info: ssa_granted_ovc_num + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 675 +credit_release_gen, "(counter == CREDIT_NUM)" + A left 5-bit expression is compared to a right 32-bit expression. + Comparing 'counter' of type reg [(W - 1):0] + with 'CREDIT_NUM' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 64 +check_flit_chanel_type_is_in_order, "(PCK_TYPE == "SINGLE_FLIT")" + A left 80-bit expression is compared to a right 88-bit expression. + Comparing 'PCK_TYPE' of type string + with '"SINGLE_FLIT"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./debug.v, 33 + Continuous assignment width mismatch + 1 bits (lhs) versus 32 bits (rhs). + Source info: assign vc_num_hdr_wr = ((hdr_flg_in & flit_in_wr) ? vc_num_in : + 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./debug.v, 34 + Continuous assignment width mismatch + 1 bits (lhs) versus 32 bits (rhs). + Source info: assign vc_num_tail_wr = ((tail_flg_in & flit_in_wr) ? vc_num_in + : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./debug.v, 35 + Continuous assignment width mismatch + 1 bits (lhs) versus 32 bits (rhs). + Source info: assign vc_num_bdy_wr = ((({hdr_flg_in, tail_flg_in} == 2'b0) && + flit_in_wr) ? vc_num_in : 0); + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 83 +"router_chan_out[(0 - 1)][pronoc_pkg::FORWARD]" + The select index is out of declared bounds : [3:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 79 +"router_chan_out[(3 + 1)][pronoc_pkg::BACKWARD]" + The select index is out of declared bounds : [3:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 116 + Following is an unused input. + Source info: spec_ovc_num_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 118 + Following is an unused input. + Source info: spec_first_arbiter_granted_ivc_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 120 + Following is an unused input. + Source info: spec_granted_dest_port_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 88 + Following is an unused input. + Source info: crossbar_flit_out_wr_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 351 + Following is an unused input. + Source info: ovc_status + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 352 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 353 + Following is an unused input. + Source info: credit_decreased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 354 + Following is an unused input. + Source info: credit_increased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 355 + Following is an unused input. + Source info: congestion_in_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 464 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 467 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 468 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 471 + Following is an unused input. + Source info: ivc_num_getting_ovc_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 965 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 966 + Following is an unused input. + Source info: ivc_request_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 967 + Following is an unused input. + Source info: ivc_num_getting_sw_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./router_bypass.sv, 329 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./router_bypass.sv, 329 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 61 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 61 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 63 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./debug.v, 560 + Following is an unused input. + Source info: dest_e_addr_in + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 574 +check_pck_size, "(vc_num_in == i)" + A left 1-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with 'i' of type integer. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 574 +check_pck_size, "(vc_num_in == 0)" + A left 1-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '0' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 590 +check_pck_size, "(vc_num_in == 0)" + A left 1-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '0' of type int. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 80 + Following is an unused input. + Source info: multiple_dest + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 81 + Following is an unused input. + Source info: sub_rd_ptr_ld + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 80 + Following is an unused input. + Source info: multiple_dest + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 81 + Following is an unused input. + Source info: sub_rd_ptr_ld + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 222 + Following is an unused input. + Source info: sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 223 + Following is an unused input. + Source info: any_ivc_sw_request_granted + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 224 + Following is an unused input. + Source info: lk_dest_not_registered + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 639 + Following is an unused input. + Source info: reset + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 1 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[0] = (ovc_is_assigned_all[0] ? + assigned_ovc_num_all[(((0 + 1) * V) - 1):(0 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 1 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[1] = (ovc_is_assigned_all[1] ? + assigned_ovc_num_all[(((1 + 1) * V) - 1):(1 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 1 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[2] = (ovc_is_assigned_all[2] ? + assigned_ovc_num_all[(((2 + 1) * V) - 1):(2 * V)] : 0); + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./../main_comp.v, 378 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 3-bit LHS target: + Source info: sum = 0; + Expression: sum + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 460 + Following is an unused input. + Source info: pck_is_single_flit_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus_routting.v, 631 + Following is an unused input. + Source info: current_y + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus_routting.v, 633 + Following is an unused input. + Source info: dest_y + + +Lint-[UI] Unused input +./../../rtl/src_noc/./../main_comp.v, 259 + Following is an unused input. + Source info: one_hot_code + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 680 +fwft_fifo, "(IGNORE_SAME_LOC_RD_WR_WARNING == "NO")" + A left 24-bit expression is compared to a right 16-bit expression. + Comparing 'IGNORE_SAME_LOC_RD_WR_WARNING' of type string + with '"NO"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./flit_buffer.sv, 631 + Continuous assignment width mismatch + 4 bits (lhs) versus 32 bits (rhs). + Source info: assign mwb2.depth_2 = (depth - 2); + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./debug.v, 116 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./debug.v, 118 + Following is an unused input. + Source info: vc_num_in + + +Lint-[UI] Unused input +./../../rtl/src_noc/./debug.v, 118 + Following is an unused input. + Source info: flit_is_tail + + +Lint-[UI] Unused input +./../../rtl/src_noc/./debug.v, 118 + Following is an unused input. + Source info: ivc_num_getting_sw_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./../arbiter.v, 49 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./../arbiter.v, 50 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 634 + Following is an unused input. + Source info: vc_weight_is_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 717 + Following is an unused input. + Source info: weight_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1137 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1138 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 324 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./../arbiter.v, 101 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./../arbiter.v, 102 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./../arbiter.v, 103 + Following is an unused input. + Source info: priority_en + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1306 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus_routting.v, 362 + Following is an unused input. + Source info: current_y + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus_routting.v, 631 + Following is an unused input. + Source info: current_y + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus_routting.v, 633 + Following is an unused input. + Source info: dest_y + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 680 +fwft_fifo, "(IGNORE_SAME_LOC_RD_WR_WARNING == "NO")" + A left 24-bit expression is compared to a right 16-bit expression. + Comparing 'IGNORE_SAME_LOC_RD_WR_WARNING' of type string + with '"NO"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./flit_buffer.sv, 631 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign mwb2.depth_2 = (depth - 2); + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1137 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1138 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1137 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1138 + Following is an unused input. + Source info: port_pre_sel + +Starting vcs inline pass... + +43 modules and 0 UDP read. +Generating code for _VCSgd_reYIK +Generating code for _VCSgd_bQrwm +recompiling package pronoc_pkg +Generating code for _VCSgd_UU20K +recompiling module pronoc_register +Generating code for _VCSgd_Afg9y +Generating code for _VCSgd_dP5iL +Generating code for _VCSgd_sGFGA +recompiling module one_hot_demux +Generating code for _VCSgd_PFE93 +recompiling module custom_or +Generating code for _VCSgd_rxxii +recompiling module one_hot_to_bin +Generating code for _VCSgd_z7NBD +recompiling module binary_mux +Generating code for _VCSgd_VK6Ru +recompiling module accumulator +Generating code for _VCSgd_jLwrn +recompiling module extract_header_flit_info +Generating code for _VCSgd_Ly3qd +recompiling module header_flit_update_lk_route_ovc +Generating code for _VCSgd_ECtRV +recompiling module noc_top +Generating code for _VCSgd_qubHr +recompiling module comb_nonspec_allocator +Generating code for _VCSgd_wLDGV +recompiling module swa_output_port_arbiter +Generating code for _VCSgd_AW5ic +recompiling module inout_ports +Generating code for _VCSgd_xNBkF +recompiling module vc_alloc_request_gen +Generating code for _VCSgd_bzyYs +recompiling module input_ports +Generating code for _VCSgd_at0sD +recompiling module input_queue_per_port +Generating code for _VCSgd_vPvg3 +Generating code for _VCSgd_TypBP +Generating code for _VCSgd_pnIHZ +recompiling module combined_vc_sw_alloc +Generating code for _VCSgd_L5RSt +recompiling module mesh_torus_look_ahead_routing +Generating code for _VCSgd_sa7gf +recompiling module reduction_or +Generating code for _VCSgd_msGQv +recompiling module onehot_mux_2D +Generating code for _VCSgd_wje7W +recompiling module onehot_mux_1D +Generating code for _VCSgd_etkVB +Generating code for _VCSgd_ER2NJ +Generating code for _VCSgd_UfJB9 +recompiling module header_flit_info +Generating code for _VCSgd_Qu4wI +recompiling module smart_chanel_check +Generating code for _VCSgd_PggHf +recompiling module smart_forward_ivc_info +Generating code for _VCSgd_mJ8QU +recompiling module smart_bypass_chanels +Generating code for _VCSgd_SEDnz +recompiling module smart_validity_check_per_ivc +Generating code for _VCSgd_zs0vT +recompiling module smart_allocator_per_iport +Generating code for _VCSgd_g0Zy4 +Generating code for _VCSgd_D8VMz +recompiling module smart_credit_manage +Generating code for _VCSgd_InS4s +recompiling module output_ports +Generating code for _VCSgd_pAQwF +recompiling module credit_monitor_per_ovc +Generating code for _VCSgd_UPPPJ +recompiling module oport_ovc_sig_gen +Generating code for _VCSgd_iMQv0 +recompiling module full_ovc_predictor +Generating code for _VCSgd_QrHZM +recompiling module conventional_routing +Generating code for _VCSgd_Nx31A +recompiling module router_two_stage +Generating code for _VCSgd_QCD2e +recompiling module credit_release_gen +Generating code for _VCSgd_yaiFc +recompiling module flit_buffer +Generating code for _VCSgd_bcmYE +recompiling module fwft_fifo +Generating code for _VCSgd_JPLQY +Generating code for _VCSgd_uCyx2 +recompiling module mesh_tori_endp_addr_decode +Generating code for _VCSgd_YhjUR +recompiling module check_flit_chanel_type_is_in_order +Generating code for _VCSgd_fH8fL +recompiling module debug_mesh_tori_route_ckeck +Generating code for _VCSgd_C3wbF +recompiling module check_pck_size +Generating code for _VCSgd_sIT4b +recompiling module router_top +Generating code for _VCSgd_J4kZy +recompiling module mesh_torus_noc_top +All of 43 modules done +make: Warning: File 'filelist.hsopt.llvm2_0.objs' has modification time 55 s in the future +make: warning: Clock skew detected. Your build may be incomplete. +make: Warning: File 'filelist.cu' has modification time 47 s in the future +make[1]: Warning: File 'filelist.cu' has modification time 47 s in the future +rm -f _cuarc*.so _csrc*.so pre_vcsobj_*.so share_vcsobj_*.so +make[1]: warning: Clock skew detected. Your build may be incomplete. +make[1]: Warning: File 'filelist.cu' has modification time 47 s in the future +make[1]: warning: Clock skew detected. Your build may be incomplete. +if [ -x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv ]; then chmod a-x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv; fi +g++ -o /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv -no-pie -rdynamic -Wl,-rpath='$ORIGIN'/simv.daidir -Wl,-rpath=./simv.daidir -Wl,-rpath=/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -L/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -Wl,-rpath-link=./ -Wl,--no-as-needed objs/amcQw_d.o _1494812_archive_1.so _prev_archive_1.so SIM_l.o rmapats_mop.o rmapats.o rmar.o rmar_nd.o rmar_llvm_0_1.o rmar_llvm_0_0.o -lnuma -lvirsim -lerrorinf -lsnpsmalloc -lvfs -lvcsnew -lsimprofile -luclinative /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_tls.o -Wl,-whole-archive -lvcsucli -Wl,-no-whole-archive _vcs_pli_stub_.o /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_save_restore_new.o /eda/synopsys/2022-23/RHELx86/VERDI_2022.06-SP2/share/PLI/VCS/LINUX64/pli.a -ldl -lc -lm -lpthread -ldl +/users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv up to date +make: warning: Clock skew detected. Your build may be incomplete. +Verdi KDB elaboration done and the database successfully generated: 0 error(s), 0 warning(s) diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log new file mode 100644 index 0000000..026af74 --- /dev/null +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log @@ -0,0 +1,2322 @@ +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 24. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 25. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 26. +Script Path: /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src +confs_dir: /users/amonemi/ProNoC/mpsoc/Integration_test/synthetic_sim/configurations +Root: /users/amonemi/ProNoC/mpsoc +Parsing design file './../../rtl/src_noc/./pronoc_pkg.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './src/noc_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './../../rtl/src_noc/./topology_localparam.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./topology_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing design file './../../rtl/src_noc/./../main_comp.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../main_comp.v'. +Parsing design file './../../rtl/src_noc/./../arbiter.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../arbiter.v'. +Parsing design file './../../rtl/src_noc/./ovc_list.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ovc_list.sv'. +Parsing design file './../../rtl/src_noc/./ss_allocator.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ss_allocator.sv'. +Parsing design file './../../rtl/src_noc/./route_torus.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_torus.v'. +Parsing design file './../../rtl/src_noc/./header_flit.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./header_flit.sv'. +Parsing design file './../../rtl/src_noc/./noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_route.v'. +Parsing design file './../../rtl/src_noc/./comb_nonspec.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_nonspec.sv'. +Parsing design file './../../rtl/src_noc/./inout_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./inout_ports.sv'. +Parsing design file './../../rtl/src_noc/./wrra.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing design file './../../rtl/src_noc/./input_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./input_ports.sv'. +Parsing design file './../../rtl/src_noc/./tree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./tree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_route.v'. +Parsing design file './../../rtl/src_noc/./comb-spec1.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb-spec1.v'. +Parsing design file './../../rtl/src_noc/./combined_vc_sw_alloc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./combined_vc_sw_alloc.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_routting.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_routting.v'. +Parsing design file './../../rtl/src_noc/./comb_spec2.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_spec2.v'. +Parsing design file './../../rtl/src_noc/./route_mesh.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_mesh.v'. +Parsing design file './../../rtl/src_noc/./router_bypass.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_bypass.sv'. +Parsing design file './../../rtl/src_noc/./traffic_gen_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./traffic_gen_top.sv'. +Parsing design file './../../rtl/src_noc/./congestion_analyzer.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./congestion_analyzer.v'. +Parsing design file './../../rtl/src_noc/./output_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./output_ports.sv'. +Parsing design file './../../rtl/src_noc/./routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./routing.v'. +Parsing design file './../../rtl/src_noc/./router_two_stage.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_two_stage.sv'. +Parsing design file './../../rtl/src_noc/./crossbar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./crossbar.v'. +Parsing design file './../../rtl/src_noc/./flit_buffer.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./flit_buffer.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus.sv'. +Parsing design file './../../rtl/src_noc/./debug.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./debug.v'. +Parsing design file './../../rtl/src_noc/./router_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_top.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./star_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./star_noc.sv'. +Parsing design file './../../rtl/src_noc/./fmesh.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fmesh.sv'. +Parsing design file './../../rtl/src_noc/./packet_injector.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./packet_injector.sv'. +Parsing design file './../../rtl/src_noc/./multicast.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./multicast.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v'. +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing_genvar.v' +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing.v' +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v'. +Parsing design file './../../rtl/src_topology/./common/custom_ni_routing.v' +Parsing design file './../../rtl/src_topology/./common/custom_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./common/custom_noc_top.sv'. +Parsing design file './../../rtl/src_topology/./common/custom_lkh_routing.v' +Top Level Modules: + noc_top + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 16 +pronoc_pkg, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 17 +pronoc_pkg, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 18 +pronoc_pkg, "(TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 21 +pronoc_pkg, "(TOPOLOGY == "MULTI_MESH")" + A left 32-bit expression is compared to a right 80-bit expression. + Comparing 'TOPOLOGY' of type string + with '"MULTI_MESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 27 +pronoc_pkg, "(SWA_ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'SWA_ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 28 +pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" + A left 80-bit expression is compared to a right 88-bit expression. + Comparing 'PCK_TYPE' of type string + with '"SINGLE_FLIT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "DUATO")" + A left 16-bit expression is compared to a right 40-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" + A left 16-bit expression is compared to a right 88-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./output_ports.sv, 128 +output_ports, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 131 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC1")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC1"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 167 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC2")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC2"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 241 +input_queue_per_port, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 241 +input_queue_per_port, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 406 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 423 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::ROUTE_NAME == "NCA_STRAIGHT_UP")" + A left 16-bit expression is compared to a right 120-bit expression. + Comparing 'pronoc_pkg::ROUTE_NAME' of type string + with '"NCA_STRAIGHT_UP"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./ss_allocator.sv, 222 +ssa_per_vc, "(((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK)) != {pronoc_pkg::V {1'b0}})" + A left 32-bit expression is compared to a right 2-bit expression. + Comparing '((1 << V_LOCAL) & (~pronoc_pkg::ESCAP_VC_MASK))' of type bit + [31:0] + with '{pronoc_pkg::V {1'b0}}' of type bit [1:0]. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1138 +destp_generator, "(TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1166 +destp_generator, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 721 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 747 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA_CLASSIC")" + A left 24-bit expression is compared to a right 96-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA_CLASSIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus.sv, 336 +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus.sv, 336 +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus.sv, 336 +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 146 +mesh_torus_deterministic_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 146 +mesh_torus_deterministic_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 368 +mesh_torus_next_router_addr_predictor, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 368 +mesh_torus_next_router_addr_predictor, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 638 +mesh_torus_conventional_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + +TimeScale is 1 ns / 1 ps + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "BROADCAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"BROADCAST_PARTIAL"' of type string. + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 328 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 9-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 332 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 352 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 356 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 9-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./pronoc_pkg.sv, 300 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 2-bit LHS target: + Source info: hetero_ovc_unary = ((HETERO_VC == 0) ? {V {1'b1}} : ((HETERO_VC + == 1) ? ((1 << VC_CONFIG_TABLE[router_id][0]) - 1) : ((1 << + VC_CONFIG_TABLE[router_id][router_ ... + Expression: hetero_ovc_unary + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 555 + Following is an unused input. + Source info: ssa_granted_ovc_num + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 675 +credit_release_gen, "(counter == CREDIT_NUM)" + A left 5-bit expression is compared to a right 32-bit expression. + Comparing 'counter' of type reg [(W - 1):0] + with 'CREDIT_NUM' of type int. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[0].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[0].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[0].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[1].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[1].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[1].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[2].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[2].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[2].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[0].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[0].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[0].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[1].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[1].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[1].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[2].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[2].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[2].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[0].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[0].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[0].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[1].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[1].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[1].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[2].EAST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[2].NORTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[2].WEST_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [8:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 116 + Following is an unused input. + Source info: spec_ovc_num_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 118 + Following is an unused input. + Source info: spec_first_arbiter_granted_ivc_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 120 + Following is an unused input. + Source info: spec_granted_dest_port_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 88 + Following is an unused input. + Source info: crossbar_flit_out_wr_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 351 + Following is an unused input. + Source info: ovc_status + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 352 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 353 + Following is an unused input. + Source info: credit_decreased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 354 + Following is an unused input. + Source info: credit_increased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 355 + Following is an unused input. + Source info: congestion_in_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 464 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 467 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 468 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 471 + Following is an unused input. + Source info: ivc_num_getting_ovc_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 965 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 966 + Following is an unused input. + Source info: ivc_request_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 967 + Following is an unused input. + Source info: ivc_num_getting_sw_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 80 + Following is an unused input. + Source info: multiple_dest + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 81 + Following is an unused input. + Source info: sub_rd_ptr_ld + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 80 + Following is an unused input. + Source info: multiple_dest + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 81 + Following is an unused input. + Source info: sub_rd_ptr_ld + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 222 + Following is an unused input. + Source info: sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./ss_allocator.sv, 364 + Following is an unused input. + Source info: destport_one_hot + + +Lint-[UI] Unused input +./../../rtl/src_noc/./ss_allocator.sv, 365 + Following is an unused input. + Source info: dest_e_addr_in + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 680 +fwft_fifo, "(IGNORE_SAME_LOC_RD_WR_WARNING == "NO")" + A left 24-bit expression is compared to a right 16-bit expression. + Comparing 'IGNORE_SAME_LOC_RD_WR_WARNING' of type string + with '"NO"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./flit_buffer.sv, 631 + Continuous assignment width mismatch + 5 bits (lhs) versus 32 bits (rhs). + Source info: assign mwb2.depth_2 = (depth - 2); + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 634 + Following is an unused input. + Source info: vc_weight_is_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 717 + Following is an unused input. + Source info: weight_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 794 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 794 + Following is an unused input. + Source info: ivc_num_getting_sw_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 794 + Following is an unused input. + Source info: hdr_flg + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 794 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 794 + Following is an unused input. + Source info: ivc_num_getting_sw_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 794 + Following is an unused input. + Source info: hdr_flg + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 324 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 324 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 324 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1213 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1215 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1216 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./ss_allocator.sv, 364 + Following is an unused input. + Source info: destport_one_hot + + +Lint-[UI] Unused input +./../../rtl/src_noc/./ss_allocator.sv, 365 + Following is an unused input. + Source info: dest_e_addr_in + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 680 +fwft_fifo, "(IGNORE_SAME_LOC_RD_WR_WARNING == "NO")" + A left 24-bit expression is compared to a right 16-bit expression. + Comparing 'IGNORE_SAME_LOC_RD_WR_WARNING' of type string + with '"NO"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./flit_buffer.sv, 631 + Continuous assignment width mismatch + 3 bits (lhs) versus 32 bits (rhs). + Source info: assign mwb2.depth_2 = (depth - 2); + +Starting vcs inline pass... + +36 modules and 0 UDP read. +Generating code for _VCSgd_reYIK +Generating code for _VCSgd_bQrwm +recompiling package pronoc_pkg +Generating code for _VCSgd_UU20K +recompiling module pronoc_register +Generating code for _VCSgd_J18WU +Generating code for _VCSgd_t2N4h +Generating code for _VCSgd_dP5iL +Generating code for _VCSgd_sGFGA +recompiling module one_hot_demux +Generating code for _VCSgd_PFE93 +recompiling module custom_or +Generating code for _VCSgd_rxxii +recompiling module one_hot_to_bin +Generating code for _VCSgd_tmkfi +Generating code for _VCSgd_z7NBD +recompiling module binary_mux +Generating code for _VCSgd_iuc87 +recompiling module arbiter +Generating code for _VCSgd_Z8Hg1 +recompiling module arbiter_2_one_hot +Generating code for _VCSgd_nMgKR +recompiling module ss_allocator +Generating code for _VCSgd_PnDZp +recompiling module ssa_per_vc +Generating code for _VCSgd_yqzS6 +Generating code for _VCSgd_jLwrn +recompiling module extract_header_flit_info +Generating code for _VCSgd_Ly3qd +recompiling module header_flit_update_lk_route_ovc +Generating code for _VCSgd_ECtRV +recompiling module noc_top +Generating code for _VCSgd_qubHr +recompiling module comb_nonspec_allocator +Generating code for _VCSgd_dmk1W +recompiling module swa_input_port_arbiter +Generating code for _VCSgd_wLDGV +recompiling module swa_output_port_arbiter +Generating code for _VCSgd_AW5ic +recompiling module inout_ports +Generating code for _VCSgd_xNBkF +recompiling module vc_alloc_request_gen +Generating code for _VCSgd_bzyYs +recompiling module input_ports +Generating code for _VCSgd_at0sD +recompiling module input_queue_per_port +Generating code for _VCSgd_vPvg3 +Generating code for _VCSgd_TypBP +Generating code for _VCSgd_SQwq4 +Generating code for _VCSgd_hJjVQ +Generating code for _VCSgd_sPxW2 +recompiling module destp_generator +Generating code for _VCSgd_k7SJc +Generating code for _VCSgd_g9A6z +Generating code for _VCSgd_DJdxW +Generating code for _VCSgd_r6P8n +Generating code for _VCSgd_pnIHZ +recompiling module combined_vc_sw_alloc +Generating code for _VCSgd_L5RSt +recompiling module mesh_torus_look_ahead_routing +Generating code for _VCSgd_ihbcT +recompiling module onehot_mux_1D +Generating code for _VCSgd_wje7W +Generating code for _VCSgd_ZzZJM +Generating code for _VCSgd_Dh26b +Generating code for _VCSgd_etkVB +Generating code for _VCSgd_ER2NJ +Generating code for _VCSgd_UfJB9 +recompiling module header_flit_info +Generating code for _VCSgd_InS4s +recompiling module output_ports +Generating code for _VCSgd_IhnxI +recompiling module credit_monitor_per_ovc +Generating code for _VCSgd_pAQwF +Generating code for _VCSgd_UPPPJ +recompiling module oport_ovc_sig_gen +Generating code for _VCSgd_iMQv0 +recompiling module full_ovc_predictor +Generating code for _VCSgd_Nx31A +recompiling module router_two_stage +Generating code for _VCSgd_QCD2e +recompiling module credit_release_gen +Generating code for _VCSgd_yaiFc +recompiling module flit_buffer +Generating code for _VCSgd_bcmYE +recompiling module fwft_fifo +Generating code for _VCSgd_JPLQY +Generating code for _VCSgd_jHVFt +recompiling module mesh_torus_destp_decoder +Generating code for _VCSgd_sIT4b +recompiling module router_top +Generating code for _VCSgd_J4kZy +recompiling module mesh_torus_noc_top +All of 36 modules done +make: Warning: File 'filelist.hsopt.llvm2_0.objs' has modification time 55 s in the future +make: warning: Clock skew detected. Your build may be incomplete. +make: Warning: File 'filelist.cu' has modification time 54 s in the future +make[1]: Warning: File 'filelist.cu' has modification time 54 s in the future +rm -f _cuarc*.so _csrc*.so pre_vcsobj_*.so share_vcsobj_*.so +make[1]: warning: Clock skew detected. Your build may be incomplete. +make[1]: Warning: File 'filelist.cu' has modification time 54 s in the future +make[1]: warning: Clock skew detected. Your build may be incomplete. +if [ -x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv ]; then chmod a-x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv; fi +g++ -o /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv -no-pie -rdynamic -Wl,-rpath='$ORIGIN'/simv.daidir -Wl,-rpath=./simv.daidir -Wl,-rpath=/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -L/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -Wl,-rpath-link=./ -Wl,--no-as-needed objs/amcQw_d.o _1507254_archive_1.so _prev_archive_1.so SIM_l.o rmapats_mop.o rmapats.o rmar.o rmar_nd.o rmar_llvm_0_1.o rmar_llvm_0_0.o -lnuma -lvirsim -lerrorinf -lsnpsmalloc -lvfs -lvcsnew -lsimprofile -luclinative /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_tls.o -Wl,-whole-archive -lvcsucli -Wl,-no-whole-archive _vcs_pli_stub_.o /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_save_restore_new.o /eda/synopsys/2022-23/RHELx86/VERDI_2022.06-SP2/share/PLI/VCS/LINUX64/pli.a -ldl -lc -lm -lpthread -ldl +/users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv up to date +make: warning: Clock skew detected. Your build may be incomplete. +Verdi KDB elaboration done and the database successfully generated: 0 error(s), 0 warning(s) diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log new file mode 100644 index 0000000..50f404b --- /dev/null +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log @@ -0,0 +1,2060 @@ +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 24. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 25. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 26. +Script Path: /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src +confs_dir: /users/amonemi/ProNoC/mpsoc/Integration_test/synthetic_sim/configurations +Root: /users/amonemi/ProNoC/mpsoc +Parsing design file './../../rtl/src_noc/./pronoc_pkg.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './src/noc_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './../../rtl/src_noc/./topology_localparam.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./topology_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing design file './../../rtl/src_noc/./../main_comp.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../main_comp.v'. +Parsing design file './../../rtl/src_noc/./../arbiter.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../arbiter.v'. +Parsing design file './../../rtl/src_noc/./ovc_list.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ovc_list.sv'. +Parsing design file './../../rtl/src_noc/./ss_allocator.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ss_allocator.sv'. +Parsing design file './../../rtl/src_noc/./route_torus.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_torus.v'. +Parsing design file './../../rtl/src_noc/./header_flit.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./header_flit.sv'. +Parsing design file './../../rtl/src_noc/./noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_route.v'. +Parsing design file './../../rtl/src_noc/./comb_nonspec.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_nonspec.sv'. +Parsing design file './../../rtl/src_noc/./inout_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./inout_ports.sv'. +Parsing design file './../../rtl/src_noc/./wrra.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing design file './../../rtl/src_noc/./input_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./input_ports.sv'. +Parsing design file './../../rtl/src_noc/./tree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./tree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_route.v'. +Parsing design file './../../rtl/src_noc/./comb-spec1.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb-spec1.v'. +Parsing design file './../../rtl/src_noc/./combined_vc_sw_alloc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./combined_vc_sw_alloc.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_routting.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_routting.v'. +Parsing design file './../../rtl/src_noc/./comb_spec2.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_spec2.v'. +Parsing design file './../../rtl/src_noc/./route_mesh.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_mesh.v'. +Parsing design file './../../rtl/src_noc/./router_bypass.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_bypass.sv'. +Parsing design file './../../rtl/src_noc/./traffic_gen_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./traffic_gen_top.sv'. +Parsing design file './../../rtl/src_noc/./congestion_analyzer.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./congestion_analyzer.v'. +Parsing design file './../../rtl/src_noc/./output_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./output_ports.sv'. +Parsing design file './../../rtl/src_noc/./routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./routing.v'. +Parsing design file './../../rtl/src_noc/./router_two_stage.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_two_stage.sv'. +Parsing design file './../../rtl/src_noc/./crossbar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./crossbar.v'. +Parsing design file './../../rtl/src_noc/./flit_buffer.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./flit_buffer.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus.sv'. +Parsing design file './../../rtl/src_noc/./debug.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./debug.v'. +Parsing design file './../../rtl/src_noc/./router_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_top.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./star_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./star_noc.sv'. +Parsing design file './../../rtl/src_noc/./fmesh.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fmesh.sv'. +Parsing design file './../../rtl/src_noc/./packet_injector.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./packet_injector.sv'. +Parsing design file './../../rtl/src_noc/./multicast.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./multicast.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v'. +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing_genvar.v' +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing.v' +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v'. +Parsing design file './../../rtl/src_topology/./common/custom_ni_routing.v' +Parsing design file './../../rtl/src_topology/./common/custom_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./common/custom_noc_top.sv'. +Parsing design file './../../rtl/src_topology/./common/custom_lkh_routing.v' +Top Level Modules: + noc_top + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 16 +pronoc_pkg, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 17 +pronoc_pkg, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 18 +pronoc_pkg, "(TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 21 +pronoc_pkg, "(TOPOLOGY == "MULTI_MESH")" + A left 32-bit expression is compared to a right 80-bit expression. + Comparing 'TOPOLOGY' of type string + with '"MULTI_MESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 27 +pronoc_pkg, "(SWA_ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'SWA_ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 28 +pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" + A left 80-bit expression is compared to a right 88-bit expression. + Comparing 'PCK_TYPE' of type string + with '"SINGLE_FLIT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "DUATO")" + A left 16-bit expression is compared to a right 40-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" + A left 16-bit expression is compared to a right 88-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 205 +pronoc_pkg, "(CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 246 +pronoc_pkg, "(CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 301 +pronoc_pkg, "(CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 197 +router_two_stage, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 197 +router_two_stage, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 197 +router_two_stage, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 197 +router_two_stage, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 197 +router_two_stage, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./output_ports.sv, 128 +output_ports, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./output_ports.sv, 349 +output_ports, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 131 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC1")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC1"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 167 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC2")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC2"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 241 +input_queue_per_port, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 601 +check_pck_size, "(CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 601 +check_pck_size, "(CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 406 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 406 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 423 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 423 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::ROUTE_NAME == "NCA_STRAIGHT_UP")" + A left 16-bit expression is compared to a right 120-bit expression. + Comparing 'pronoc_pkg::ROUTE_NAME' of type string + with '"NCA_STRAIGHT_UP"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 947 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 667 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 667 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1026 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1026 +input_queue_per_port, "(pronoc_pkg::CAST_TYPE == "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 116 +flit_buffer, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 141 +flit_buffer, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 141 +flit_buffer, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 247 +flit_buffer, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 247 +flit_buffer, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 379 +flit_buffer, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 379 +flit_buffer, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1123 +destp_generator, "(CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 721 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 747 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA_CLASSIC")" + A left 24-bit expression is compared to a right 96-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA_CLASSIC"' of type string. + +TimeScale is 1 ns / 1 ps + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "BROADCAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"BROADCAST_PARTIAL"' of type string. + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 328 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 16-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 356 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 16-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./pronoc_pkg.sv, 300 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 2-bit LHS target: + Source info: hetero_ovc_unary = ((HETERO_VC == 0) ? {V {1'b1}} : ((HETERO_VC + == 1) ? ((1 << VC_CONFIG_TABLE[router_id][0]) - 1) : ((1 << + VC_CONFIG_TABLE[router_id][router_ ... + Expression: hetero_ovc_unary + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 555 + Following is an unused input. + Source info: ssa_granted_ovc_num + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 675 +credit_release_gen, "(counter == CREDIT_NUM)" + A left 3-bit expression is compared to a right 32-bit expression. + Comparing 'counter' of type reg [(W - 1):0] + with 'CREDIT_NUM' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 64 +check_flit_chanel_type_is_in_order, "(PCK_TYPE == "SINGLE_FLIT")" + A left 80-bit expression is compared to a right 88-bit expression. + Comparing 'PCK_TYPE' of type string + with '"SINGLE_FLIT"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./debug.v, 33 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign vc_num_hdr_wr = ((hdr_flg_in & flit_in_wr) ? vc_num_in : + 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./debug.v, 34 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign vc_num_tail_wr = ((tail_flg_in & flit_in_wr) ? vc_num_in + : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./debug.v, 35 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign vc_num_bdy_wr = ((({hdr_flg_in, tail_flg_in} == 2'b0) && + flit_in_wr) ? vc_num_in : 0); + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 309 +debug_mesh_edges, "(current_rx == (T1 - 1))" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '(T1 - 1)' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 311 +debug_mesh_edges, "(current_ry == (T2 - 1))" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_ry' of type wire [(RYw - 1):0] + with '(T2 - 1)' of type int. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_top.sv, 289 +router_top, "(pronoc_pkg::CAST_TYPE != "UNICAST")" + A left 112-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"UNICAST"' of type string. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 116 + Following is an unused input. + Source info: spec_ovc_num_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 118 + Following is an unused input. + Source info: spec_first_arbiter_granted_ivc_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 120 + Following is an unused input. + Source info: spec_granted_dest_port_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 88 + Following is an unused input. + Source info: crossbar_flit_out_wr_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 351 + Following is an unused input. + Source info: ovc_status + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 352 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 353 + Following is an unused input. + Source info: credit_decreased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 354 + Following is an unused input. + Source info: credit_increased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 355 + Following is an unused input. + Source info: congestion_in_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 464 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 467 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 468 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 471 + Following is an unused input. + Source info: ivc_num_getting_ovc_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 965 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 966 + Following is an unused input. + Source info: ivc_request_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 967 + Following is an unused input. + Source info: ivc_num_getting_sw_grant + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 574 +check_pck_size, "(vc_num_in == i)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with 'i' of type integer. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 574 +check_pck_size, "(vc_num_in == 0)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '0' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 590 +check_pck_size, "(vc_num_in == 0)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '0' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 629 +check_pck_size, "(vc_num_in == 0)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '0' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 574 +check_pck_size, "(vc_num_in == 1)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '1' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 590 +check_pck_size, "(vc_num_in == 1)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '1' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 629 +check_pck_size, "(vc_num_in == 1)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '1' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 604 +check_pck_size, "(vc_num_in == 0)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '0' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./debug.v, 604 +check_pck_size, "(vc_num_in == 1)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'vc_num_in' of type wire [(V - 1):0] + with '1' of type int. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./multicast.sv, 477 + Following is an unused input. + Source info: endp_port + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 602 +multicast_chan_in_process, "(pronoc_pkg::CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./multicast.sv, 477 + Following is an unused input. + Source info: endp_port + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 602 +multicast_chan_in_process, "(pronoc_pkg::CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./multicast.sv, 477 + Following is an unused input. + Source info: endp_port + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 602 +multicast_chan_in_process, "(pronoc_pkg::CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./multicast.sv, 477 + Following is an unused input. + Source info: endp_port + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 602 +multicast_chan_in_process, "(pronoc_pkg::CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./multicast.sv, 477 + Following is an unused input. + Source info: endp_port + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 602 +multicast_chan_in_process, "(pronoc_pkg::CAST_TYPE == "MULTICAST_PARTIAL")" + A left 112-bit expression is compared to a right 136-bit expression. + Comparing 'pronoc_pkg::CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 222 + Following is an unused input. + Source info: sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 223 + Following is an unused input. + Source info: any_ivc_sw_request_granted + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 224 + Following is an unused input. + Source info: lk_dest_not_registered + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 639 + Following is an unused input. + Source info: reset + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[0] = (ovc_is_assigned_all[0] ? + assigned_ovc_num_all[(((0 + 1) * V) - 1):(0 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[1] = (ovc_is_assigned_all[1] ? + assigned_ovc_num_all[(((1 + 1) * V) - 1):(1 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[2] = (ovc_is_assigned_all[2] ? + assigned_ovc_num_all[(((2 + 1) * V) - 1):(2 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[3] = (ovc_is_assigned_all[3] ? + assigned_ovc_num_all[(((3 + 1) * V) - 1):(3 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[4] = (ovc_is_assigned_all[4] ? + assigned_ovc_num_all[(((4 + 1) * V) - 1):(4 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[5] = (ovc_is_assigned_all[5] ? + assigned_ovc_num_all[(((5 + 1) * V) - 1):(5 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[6] = (ovc_is_assigned_all[6] ? + assigned_ovc_num_all[(((6 + 1) * V) - 1):(6 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[7] = (ovc_is_assigned_all[7] ? + assigned_ovc_num_all[(((7 + 1) * V) - 1):(7 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[8] = (ovc_is_assigned_all[8] ? + assigned_ovc_num_all[(((8 + 1) * V) - 1):(8 * V)] : 0); + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./output_ports.sv, 648 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign assigned_ovc_num[9] = (ovc_is_assigned_all[9] ? + assigned_ovc_num_all[(((9 + 1) * V) - 1):(9 * V)] : 0); + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 460 + Following is an unused input. + Source info: pck_is_single_flit_all + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./../main_comp.v, 378 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 5-bit LHS target: + Source info: sum = 0; + Expression: sum + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./../main_comp.v, 378 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: sum = 0; + Expression: sum + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 127 +multicast_routing_mesh, "(current_rx > 0)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '0' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 129 +multicast_routing_mesh, "(current_rx < 0)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '0' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 127 +multicast_routing_mesh, "(current_rx > 1)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '1' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 129 +multicast_routing_mesh, "(current_rx < 1)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '1' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 127 +multicast_routing_mesh, "(current_rx > 2)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '2' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 129 +multicast_routing_mesh, "(current_rx < 2)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '2' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 127 +multicast_routing_mesh, "(current_rx > 3)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '3' of type int. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./multicast.sv, 129 +multicast_routing_mesh, "(current_rx < 3)" + A left 2-bit expression is compared to a right 32-bit expression. + Comparing 'current_rx' of type wire [(RXw - 1):0] + with '3' of type int. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1114 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1117 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1118 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1119 + Following is an unused input. + Source info: odd_column + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 855 +fwft_fifo_with_output_clear, "(IGNORE_SAME_LOC_RD_WR_WARNING == "NO")" + A left 24-bit expression is compared to a right 16-bit expression. + Comparing 'IGNORE_SAME_LOC_RD_WR_WARNING' of type bit [23:0] + with '"NO"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./flit_buffer.sv, 797 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign mwb2.depth_2 = (depth - 'd2); + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 634 + Following is an unused input. + Source info: vc_weight_is_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 717 + Following is an unused input. + Source info: weight_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1114 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1117 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1118 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1119 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1114 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1117 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1118 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1119 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1114 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1117 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1118 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1119 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1114 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1117 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1118 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 1119 + Following is an unused input. + Source info: odd_column + +Starting vcs inline pass... + +41 modules and 0 UDP read. +Generating code for _VCSgd_reYIK +Generating code for _VCSgd_bQrwm +recompiling package pronoc_pkg +Generating code for _VCSgd_UU20K +recompiling module pronoc_register +Generating code for _VCSgd_Z5xzz +Generating code for _VCSgd_wJnV0 +Generating code for _VCSgd_sGFGA +recompiling module one_hot_demux +Generating code for _VCSgd_j3CNv +Generating code for _VCSgd_PFE93 +recompiling module custom_or +Generating code for _VCSgd_rxxii +recompiling module one_hot_to_bin +Generating code for _VCSgd_tmkfi +Generating code for _VCSgd_z7NBD +recompiling module binary_mux +Generating code for _VCSgd_qQN2B +recompiling module is_onehot0 +Generating code for _VCSgd_h0Zyk +Generating code for _VCSgd_w7hk8 +recompiling module arbiter +Generating code for _VCSgd_Z8Hg1 +recompiling module arbiter_2_one_hot +Generating code for _VCSgd_jLwrn +recompiling module extract_header_flit_info +Generating code for _VCSgd_Ly3qd +recompiling module header_flit_update_lk_route_ovc +Generating code for _VCSgd_ECtRV +recompiling module noc_top +Generating code for _VCSgd_qubHr +recompiling module comb_nonspec_allocator +Generating code for _VCSgd_dmk1W +recompiling module swa_input_port_arbiter +Generating code for _VCSgd_wLDGV +recompiling module swa_output_port_arbiter +Generating code for _VCSgd_AW5ic +recompiling module inout_ports +Generating code for _VCSgd_xNBkF +recompiling module vc_alloc_request_gen +Generating code for _VCSgd_bzyYs +recompiling module input_ports +Generating code for _VCSgd_at0sD +recompiling module input_queue_per_port +Generating code for _VCSgd_vPvg3 +Generating code for _VCSgd_TypBP +Generating code for _VCSgd_SQwq4 +Generating code for _VCSgd_hJjVQ +Generating code for _VCSgd_sPxW2 +recompiling module destp_generator +Generating code for _VCSgd_k7SJc +Generating code for _VCSgd_g9A6z +Generating code for _VCSgd_DJdxW +Generating code for _VCSgd_r6P8n +Generating code for _VCSgd_pnIHZ +recompiling module combined_vc_sw_alloc +Generating code for _VCSgd_pKUfH +recompiling module add_sw_loc_one_hot +Generating code for _VCSgd_ihbcT +recompiling module onehot_mux_1D +Generating code for _VCSgd_wje7W +Generating code for _VCSgd_ZzZJM +Generating code for _VCSgd_etkVB +Generating code for _VCSgd_ER2NJ +Generating code for _VCSgd_UfJB9 +recompiling module header_flit_info +Generating code for _VCSgd_D067Y +recompiling module port_pre_sel_gen +Generating code for _VCSgd_InS4s +recompiling module output_ports +Generating code for _VCSgd_IhnxI +recompiling module credit_monitor_per_ovc +Generating code for _VCSgd_UPPPJ +recompiling module oport_ovc_sig_gen +Generating code for _VCSgd_iMQv0 +recompiling module full_ovc_predictor +Generating code for _VCSgd_VEJYp +recompiling module check_ovc +Generating code for _VCSgd_Nx31A +recompiling module router_two_stage +Generating code for _VCSgd_QCD2e +recompiling module credit_release_gen +Generating code for _VCSgd_Mtzs7 +recompiling module flit_buffer +Generating code for _VCSgd_EeYFQ +recompiling module fwft_fifo_with_output_clear +Generating code for _VCSgd_YhjUR +recompiling module check_flit_chanel_type_is_in_order +Generating code for _VCSgd_bcNyr +recompiling module debug_mesh_edges +Generating code for _VCSgd_C3wbF +recompiling module check_pck_size +Generating code for _VCSgd_sIT4b +recompiling module router_top +Generating code for _VCSgd_J4kZy +recompiling module mesh_torus_noc_top +Generating code for _VCSgd_hnFVh +recompiling module multicast_routing +Generating code for _VCSgd_zjIbJ +recompiling module multicast_dst_sel +All of 41 modules done +make: Warning: File 'filelist.hsopt.llvm2_0.objs' has modification time 55 s in the future +make: warning: Clock skew detected. Your build may be incomplete. +make: Warning: File 'filelist.cu' has modification time 54 s in the future +make[1]: Warning: File 'filelist.cu' has modification time 54 s in the future +rm -f _cuarc*.so _csrc*.so pre_vcsobj_*.so share_vcsobj_*.so +make[1]: warning: Clock skew detected. Your build may be incomplete. +make[1]: Warning: File 'filelist.cu' has modification time 54 s in the future +make[1]: warning: Clock skew detected. Your build may be incomplete. +if [ -x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv ]; then chmod a-x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv; fi +g++ -o /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv -no-pie -rdynamic -Wl,-rpath='$ORIGIN'/simv.daidir -Wl,-rpath=./simv.daidir -Wl,-rpath=/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -L/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -Wl,-rpath-link=./ -Wl,--no-as-needed objs/amcQw_d.o _1512038_archive_1.so _prev_archive_1.so SIM_l.o rmapats_mop.o rmapats.o rmar.o rmar_nd.o rmar_llvm_0_1.o rmar_llvm_0_0.o -lnuma -lvirsim -lerrorinf -lsnpsmalloc -lvfs -lvcsnew -lsimprofile -luclinative /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_tls.o -Wl,-whole-archive -lvcsucli -Wl,-no-whole-archive _vcs_pli_stub_.o /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_save_restore_new.o /eda/synopsys/2022-23/RHELx86/VERDI_2022.06-SP2/share/PLI/VCS/LINUX64/pli.a -ldl -lc -lm -lpthread -ldl +/users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv up to date +make: warning: Clock skew detected. Your build may be incomplete. +Verdi KDB elaboration done and the database successfully generated: 0 error(s), 0 warning(s) diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log new file mode 100644 index 0000000..b608185 --- /dev/null +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log @@ -0,0 +1,3020 @@ +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 24. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 25. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src/src.pl line 26. +Script Path: /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/src/../../synthetic_sim/src +confs_dir: /users/amonemi/ProNoC/mpsoc/Integration_test/synthetic_sim/configurations +Root: /users/amonemi/ProNoC/mpsoc +Parsing design file './../../rtl/src_noc/./pronoc_pkg.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './src/noc_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing included file './../../rtl/src_noc/./topology_localparam.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./topology_localparam.v'. +Back to file './../../rtl/src_noc/./pronoc_pkg.sv'. +Parsing design file './../../rtl/src_noc/./../main_comp.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../main_comp.v'. +Parsing design file './../../rtl/src_noc/./../arbiter.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./../arbiter.v'. +Parsing design file './../../rtl/src_noc/./ovc_list.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ovc_list.sv'. +Parsing design file './../../rtl/src_noc/./ss_allocator.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./ss_allocator.sv'. +Parsing design file './../../rtl/src_noc/./route_torus.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_torus.v'. +Parsing design file './../../rtl/src_noc/./header_flit.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./header_flit.sv'. +Parsing design file './../../rtl/src_noc/./noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./fattree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fattree_route.v'. +Parsing design file './../../rtl/src_noc/./comb_nonspec.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_nonspec.sv'. +Parsing design file './../../rtl/src_noc/./inout_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./inout_ports.sv'. +Parsing design file './../../rtl/src_noc/./wrra.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./wrra.v'. +Parsing design file './../../rtl/src_noc/./input_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./input_ports.sv'. +Parsing design file './../../rtl/src_noc/./tree_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./tree_route.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./tree_route.v'. +Parsing design file './../../rtl/src_noc/./comb-spec1.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb-spec1.v'. +Parsing design file './../../rtl/src_noc/./combined_vc_sw_alloc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./combined_vc_sw_alloc.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_routting.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_routting.v'. +Parsing design file './../../rtl/src_noc/./comb_spec2.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./comb_spec2.v'. +Parsing design file './../../rtl/src_noc/./route_mesh.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./route_mesh.v'. +Parsing design file './../../rtl/src_noc/./router_bypass.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_bypass.sv'. +Parsing design file './../../rtl/src_noc/./traffic_gen_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./traffic_gen_top.sv'. +Parsing design file './../../rtl/src_noc/./congestion_analyzer.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./congestion_analyzer.v'. +Parsing design file './../../rtl/src_noc/./output_ports.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./output_ports.sv'. +Parsing design file './../../rtl/src_noc/./routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./routing.v'. +Parsing design file './../../rtl/src_noc/./router_two_stage.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_two_stage.sv'. +Parsing design file './../../rtl/src_noc/./crossbar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./crossbar.v'. +Parsing design file './../../rtl/src_noc/./flit_buffer.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./flit_buffer.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus.sv'. +Parsing design file './../../rtl/src_noc/./debug.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./debug.v'. +Parsing design file './../../rtl/src_noc/./router_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./router_top.sv'. +Parsing design file './../../rtl/src_noc/./mesh_torus_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./mesh_torus_noc_top.sv'. +Parsing design file './../../rtl/src_noc/./star_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./star_noc.sv'. +Parsing design file './../../rtl/src_noc/./fmesh.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./fmesh.sv'. +Parsing design file './../../rtl/src_noc/./packet_injector.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./packet_injector.sv'. +Parsing design file './../../rtl/src_noc/./multicast.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_noc/./multicast.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v'. +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc_genvar.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing_genvar.v' +Parsing design file './../../rtl/src_topology/./custom1/custom1_noc.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/custom1_noc.sv'. +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_conventional_routing.v' +Parsing design file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./custom1/Tcustom1Rcustom_look_ahead_routing.v'. +Parsing design file './../../rtl/src_topology/./common/custom_ni_routing.v' +Parsing design file './../../rtl/src_topology/./common/custom_noc_top.sv' +Parsing included file './../../rtl/src_noc/./../pronoc_def.v'. +Back to file './../../rtl/src_topology/./common/custom_noc_top.sv'. +Parsing design file './../../rtl/src_topology/./common/custom_lkh_routing.v' +Top Level Modules: + noc_top + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 16 +pronoc_pkg, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 17 +pronoc_pkg, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 18 +pronoc_pkg, "(TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 21 +pronoc_pkg, "(TOPOLOGY == "MULTI_MESH")" + A left 32-bit expression is compared to a right 80-bit expression. + Comparing 'TOPOLOGY' of type string + with '"MULTI_MESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 27 +pronoc_pkg, "(SWA_ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'SWA_ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 28 +pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" + A left 80-bit expression is compared to a right 88-bit expression. + Comparing 'PCK_TYPE' of type string + with '"SINGLE_FLIT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "DUATO")" + A left 16-bit expression is compared to a right 40-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 143 +pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" + A left 16-bit expression is compared to a right 88-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_DUATO"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 296 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./output_ports.sv, 128 +output_ports, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 131 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC1")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC1"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./combined_vc_sw_alloc.sv, 167 +combined_vc_sw_alloc, "(pronoc_pkg::COMBINATION_TYPE == "COMB_SPEC2")" + A left 96-bit expression is compared to a right 80-bit expression. + Comparing 'pronoc_pkg::COMBINATION_TYPE' of type string + with '"COMB_SPEC2"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./crossbar.v, 115 +crossbar, "(MUX_TYPE == "ONE_HOT")" + A left 48-bit expression is compared to a right 56-bit expression. + Comparing 'MUX_TYPE' of type string + with '"ONE_HOT"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 241 +input_queue_per_port, "(pronoc_pkg::VC_REALLOCATION_TYPE == "ATOMIC")" + A left 72-bit expression is compared to a right 48-bit expression. + Comparing 'pronoc_pkg::VC_REALLOCATION_TYPE' of type string + with '"ATOMIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 406 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 423 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 441 +input_queue_per_port, "(pronoc_pkg::ROUTE_NAME == "NCA_STRAIGHT_UP")" + A left 16-bit expression is compared to a right 120-bit expression. + Comparing 'pronoc_pkg::ROUTE_NAME' of type string + with '"NCA_STRAIGHT_UP"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 800 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 821 +input_queue_per_port, "(pronoc_pkg::TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'pronoc_pkg::TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1138 +destp_generator, "(TOPOLOGY == "FATTREE")" + A left 32-bit expression is compared to a right 56-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FATTREE"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./input_ports.sv, 1166 +destp_generator, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 287 +look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./routing.v, 314 +look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 721 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA")" + A left 24-bit expression is compared to a right 32-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./comb_nonspec.sv, 747 +swa_output_port_arbiter, "(ARBITER_TYPE == "WRRA_CLASSIC")" + A left 24-bit expression is compared to a right 96-bit expression. + Comparing 'ARBITER_TYPE' of type string + with '"WRRA_CLASSIC"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 28 +mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus.sv, 336 +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus.sv, 336 +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus.sv, 336 +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" + A left 16-bit expression is compared to a right 64-bit expression. + Comparing 'ROUTE_NAME' of type string + with '"TRANC_XY"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 146 +mesh_torus_deterministic_look_ahead_routing, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 146 +mesh_torus_deterministic_look_ahead_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 368 +mesh_torus_next_router_addr_predictor, "(TOPOLOGY == "TORUS")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"TORUS"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 368 +mesh_torus_next_router_addr_predictor, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./mesh_torus_routting.v, 638 +mesh_torus_conventional_routing, "(TOPOLOGY == "FMESH")" + A left 32-bit expression is compared to a right 40-bit expression. + Comparing 'TOPOLOGY' of type string + with '"FMESH"' of type string. + +TimeScale is 1 ns / 1 ps + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_PARTIAL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 466 +pronoc_pkg, "(CAST_TYPE == "BROADCAST_PARTIAL")" + A left 56-bit expression is compared to a right 136-bit expression. + Comparing 'CAST_TYPE' of type string + with '"BROADCAST_PARTIAL"' of type string. + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 328 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 16-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 332 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./topology_localparam.v, 352 +pronoc_pkg, "(CAST_TYPE == "MULTICAST_FULL")" + A left 56-bit expression is compared to a right 112-bit expression. + Comparing 'CAST_TYPE' of type string + with '"MULTICAST_FULL"' of type string. + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./topology_localparam.v, 356 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 16-bit LHS target: + Source info: mcast_list = MCAST_ENDP_LIST; + Expression: mcast_list + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./pronoc_pkg.sv, 300 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 2-bit LHS target: + Source info: hetero_ovc_unary = ((HETERO_VC == 0) ? {V {1'b1}} : ((HETERO_VC + == 1) ? ((1 << VC_CONFIG_TABLE[router_id][0]) - 1) : ((1 << + VC_CONFIG_TABLE[router_id][router_ ... + Expression: hetero_ovc_unary + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 555 + Following is an unused input. + Source info: ssa_granted_ovc_num + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./router_two_stage.sv, 675 +credit_release_gen, "(counter == CREDIT_NUM)" + A left 3-bit expression is compared to a right 32-bit expression. + Comparing 'counter' of type reg [(W - 1):0] + with 'CREDIT_NUM' of type int. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[0].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[0].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[0].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[0].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[1].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[1].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[1].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[1].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[2].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[2].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[2].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[2].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[0].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[0].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[0].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[0].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[1].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[1].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[1].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[1].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[2].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[2].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[2].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[2].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 128 +"chan_in_all[mesh_torus.Y_[3].X_[3].EAST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 133 +"chan_in_all[mesh_torus.Y_[3].X_[3].NORTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 138 +"chan_in_all[mesh_torus.Y_[3].X_[3].WEST_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 143 +"chan_in_all[mesh_torus.Y_[3].X_[3].SOUTH_ID]" + The select index is out of declared bounds : [15:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 116 + Following is an unused input. + Source info: spec_ovc_num_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 118 + Following is an unused input. + Source info: spec_first_arbiter_granted_ivc_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 120 + Following is an unused input. + Source info: spec_granted_dest_port_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./output_ports.sv, 88 + Following is an unused input. + Source info: crossbar_flit_out_wr_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 351 + Following is an unused input. + Source info: ovc_status + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 352 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 353 + Following is an unused input. + Source info: credit_decreased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 354 + Following is an unused input. + Source info: credit_increased_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 355 + Following is an unused input. + Source info: congestion_in_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 356 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 464 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 467 + Following is an unused input. + Source info: reset + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 468 + Following is an unused input. + Source info: clk + + +Lint-[UI] Unused input +./../../rtl/src_noc/./inout_ports.sv, 471 + Following is an unused input. + Source info: ivc_num_getting_ovc_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 965 + Following is an unused input. + Source info: ovc_avalable_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 966 + Following is an unused input. + Source info: ivc_request_all + + +Lint-[UI] Unused input +./../../rtl/src_noc/./congestion_analyzer.v, 967 + Following is an unused input. + Source info: ivc_num_getting_sw_grant + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 80 + Following is an unused input. + Source info: multiple_dest + + +Lint-[UI] Unused input +./../../rtl/src_noc/./flit_buffer.sv, 81 + Following is an unused input. + Source info: sub_rd_ptr_ld + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 222 + Following is an unused input. + Source info: sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 223 + Following is an unused input. + Source info: any_ivc_sw_request_granted + + +Lint-[UI] Unused input +./../../rtl/src_noc/./header_flit.sv, 224 + Following is an unused input. + Source info: lk_dest_not_registered + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 460 + Following is an unused input. + Source info: pck_is_single_flit_all + + +Lint-[ULCO] Unequal length in comparison operator +./../../rtl/src_noc/./flit_buffer.sv, 680 +fwft_fifo, "(IGNORE_SAME_LOC_RD_WR_WARNING == "NO")" + A left 24-bit expression is compared to a right 16-bit expression. + Comparing 'IGNORE_SAME_LOC_RD_WR_WARNING' of type bit [23:0] + with '"NO"' of type string. + + +Lint-[CAWM-L] Width mismatch +./../../rtl/src_noc/./flit_buffer.sv, 631 + Continuous assignment width mismatch + 2 bits (lhs) versus 32 bits (rhs). + Source info: assign mwb2.depth_2 = (depth - 2); + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 276 + Following is an unused input. + Source info: neighbors_r_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./routing.v, 279 + Following is an unused input. + Source info: src_e_addr + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 634 + Following is an unused input. + Source info: vc_weight_is_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./comb_nonspec.sv, 717 + Following is an unused input. + Source info: weight_consumed + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 324 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 324 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 324 + Following is an unused input. + Source info: odd_column + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1213 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1215 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1216 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 273 + Following is an unused input. + Source info: refresh_w_counter + + +Lint-[UI] Unused input +./../../rtl/src_noc/./input_ports.sv, 274 + Following is an unused input. + Source info: granted_dest_port + + +Lint-[WMIA-L] Width mismatch in assignment +./../../rtl/src_noc/./input_ports.sv, 379 + Width mismatch between LHS and RHS is found in assignment: + The following 32-bit wide expression is assigned to a 4-bit LHS target: + Source info: iport_weight_next = ((weight_in == {pronoc_pkg::WEIGHTw + {1'b0}}) ? 1 : weight_in); + Expression: iport_weight_next + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1213 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1215 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1216 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1213 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1215 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1216 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1213 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1215 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1216 + Following is an unused input. + Source info: port_pre_sel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1213 + Following is an unused input. + Source info: endp_localp_num + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1215 + Following is an unused input. + Source info: swap_port_presel + + +Lint-[UI] Unused input +./../../rtl/src_noc/./mesh_torus.sv, 1216 + Following is an unused input. + Source info: port_pre_sel + +Starting vcs inline pass... + +35 modules and 0 UDP read. +Generating code for _VCSgd_reYIK +Generating code for _VCSgd_bQrwm +recompiling package pronoc_pkg +Generating code for _VCSgd_UU20K +Generating code for _VCSgd_sGFGA +recompiling module one_hot_demux +Generating code for _VCSgd_PFE93 +recompiling module custom_or +Generating code for _VCSgd_rxxii +recompiling module one_hot_to_bin +Generating code for _VCSgd_tmkfi +Generating code for _VCSgd_z7NBD +recompiling module binary_mux +Generating code for _VCSgd_w7hk8 +recompiling module arbiter +Generating code for _VCSgd_Z8Hg1 +recompiling module arbiter_2_one_hot +Generating code for _VCSgd_jLwrn +recompiling module extract_header_flit_info +Generating code for _VCSgd_Ly3qd +recompiling module header_flit_update_lk_route_ovc +Generating code for _VCSgd_ECtRV +recompiling module noc_top +Generating code for _VCSgd_qubHr +recompiling module comb_nonspec_allocator +Generating code for _VCSgd_dmk1W +recompiling module swa_input_port_arbiter +Generating code for _VCSgd_wLDGV +recompiling module swa_output_port_arbiter +Generating code for _VCSgd_AW5ic +recompiling module inout_ports +Generating code for _VCSgd_xNBkF +recompiling module vc_alloc_request_gen +Generating code for _VCSgd_bzyYs +recompiling module input_ports +Generating code for _VCSgd_at0sD +recompiling module input_queue_per_port +Generating code for _VCSgd_vPvg3 +Generating code for _VCSgd_TypBP +Generating code for _VCSgd_SQwq4 +Generating code for _VCSgd_hJjVQ +Generating code for _VCSgd_sPxW2 +recompiling module destp_generator +Generating code for _VCSgd_k7SJc +Generating code for _VCSgd_g9A6z +Generating code for _VCSgd_DJdxW +Generating code for _VCSgd_r6P8n +Generating code for _VCSgd_pnIHZ +recompiling module combined_vc_sw_alloc +Generating code for _VCSgd_L5RSt +recompiling module mesh_torus_look_ahead_routing +Generating code for _VCSgd_pKUfH +recompiling module add_sw_loc_one_hot +Generating code for _VCSgd_ihbcT +recompiling module onehot_mux_1D +Generating code for _VCSgd_wje7W +Generating code for _VCSgd_ZzZJM +Generating code for _VCSgd_Dh26b +Generating code for _VCSgd_etkVB +Generating code for _VCSgd_UfJB9 +recompiling module header_flit_info +Generating code for _VCSgd_D067Y +recompiling module port_pre_sel_gen +Generating code for _VCSgd_InS4s +recompiling module output_ports +Generating code for _VCSgd_IhnxI +recompiling module credit_monitor_per_ovc +Generating code for _VCSgd_UPPPJ +recompiling module oport_ovc_sig_gen +Generating code for _VCSgd_iMQv0 +recompiling module full_ovc_predictor +Generating code for _VCSgd_Nx31A +recompiling module router_two_stage +Generating code for _VCSgd_QCD2e +recompiling module credit_release_gen +Generating code for _VCSgd_Mtzs7 +recompiling module flit_buffer +Generating code for _VCSgd_bcmYE +recompiling module fwft_fifo +Generating code for _VCSgd_sIT4b +recompiling module router_top +Generating code for _VCSgd_J4kZy +recompiling module mesh_torus_noc_top +34 of 35 modules done + However, due to incremental compilation, only 34 modules need to be compiled. +make: Warning: File 'filelist.hsopt.llvm2_0.objs' has modification time 55 s in the future +make: warning: Clock skew detected. Your build may be incomplete. +make: Warning: File 'filelist.cu' has modification time 54 s in the future +make[1]: Warning: File 'filelist.cu' has modification time 54 s in the future +rm -f _cuarc*.so _csrc*.so pre_vcsobj_*.so share_vcsobj_*.so +make[1]: warning: Clock skew detected. Your build may be incomplete. +make[1]: Warning: File 'filelist.cu' has modification time 54 s in the future +make[1]: warning: Clock skew detected. Your build may be incomplete. +if [ -x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv ]; then chmod a-x /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv; fi +g++ -o /users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv -no-pie -rdynamic -Wl,-rpath='$ORIGIN'/simv.daidir -Wl,-rpath=./simv.daidir -Wl,-rpath=/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -L/eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib -Wl,-rpath-link=./ -Wl,--no-as-needed objs/amcQw_d.o _1513230_archive_1.so _prev_archive_1.so SIM_l.o rmapats_mop.o rmapats.o rmar.o rmar_nd.o rmar_llvm_0_1.o rmar_llvm_0_0.o -lnuma -lvirsim -lerrorinf -lsnpsmalloc -lvfs -lvcsnew -lsimprofile -luclinative /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_tls.o -Wl,-whole-archive -lvcsucli -Wl,-no-whole-archive _vcs_pli_stub_.o /eda/synopsys/2022-23/RHELx86/VCS_2022.06-SP2/linux64/lib/vcs_save_restore_new.o /eda/synopsys/2022-23/RHELx86/VERDI_2022.06-SP2/share/PLI/VCS/LINUX64/pli.a -ldl -lc -lm -lpthread -ldl +/users/amonemi/ProNoC/mpsoc/Integration_test/VCS/result_logs/work/simv up to date +make: warning: Clock skew detected. Your build may be incomplete. +Verdi KDB elaboration done and the database successfully generated: 0 error(s), 0 warning(s) diff --git a/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3.log b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3.log new file mode 100644 index 0000000..d08082f --- /dev/null +++ b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3.log @@ -0,0 +1,559 @@ +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/../../synthetic_sim/src/src.pl line 24. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/../../synthetic_sim/src/src.pl line 25. +Use of uninitialized value $ENV{"PRONOC_WORK"} in concatenation (.) or string at /users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/../../synthetic_sim/src/src.pl line 26. +Script Path: /users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/../../synthetic_sim/src +confs_dir: /users/amonemi/ProNoC/mpsoc/Integration_test/synthetic_sim/configurations +Root: /users/amonemi/ProNoC/mpsoc +Note: DISPLAY is not set, GUI view commands are disabled. + + VC Static + + Version T-2022.06-SP2 for linux64 - Nov 29, 2022 + + Copyright (c) 2010 - 2022 Synopsys, Inc. + This software and the associated documentation are proprietary to Synopsys, + Inc. This software may only be used in accordance with the terms and conditions + of a written license agreement with Synopsys, Inc. All other use, reproduction, + or distribution of this software is strictly prohibited. Licensed Products + communicate with Synopsys servers for the purpose of providing software + updates, detecting software piracy and verifying that customers are using + Licensed Products in conformity with the applicable License Key for such + Licensed Products. Synopsys will use information gathered in connection with + this process to deliver software updates and pursue software pirates and + infringers. + + Inclusivity & Diversity - Visit SolvNetPlus to read the "Synopsys Statement on + Inclusivity and Diversity" (Refer to article 000036315 at + https://solvnetplus.synopsys.com) + + + + + + + + + + + + + + + + + + + vc_static_shell> set script_dir [file dirname [file normalize [info script]]] +/users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src +set DESIGN noc_top +noc_top +set report_filename $::env(REPORT_FILENAME) +/users/amonemi/ProNoC/mpsoc/Integration_test/VCST/result_logs/line4_smart3_vc_static.txt +# Waivers: +#sg_read_waiver -file ${script_dir}/waiver.awl +#source ${script_dir}/waiver.tcl +# Reading Intel linting rules +source $script_dir/lint_rules.tcl +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W71 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W71 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W71 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W71 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W123 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W123 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W123 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W123 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W123 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W240 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W240 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W240 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W240 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W240 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W240 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W240 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] RDB_CONFIGURE_BAD_TAG: None of the tag pattern(s) 'InferLatch' (/users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/lint_rules.tcl:242) were found. + Revise your tag list and try again.. +[Warning] TCL_COMMAND_FAILED: 'configure_tag' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 02041 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W120 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W120 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W120 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W120 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W120 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W120 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name W120 and parameter name REPORT_ONLY_FROM_ONE_HIERARCHY are not associated, ignore the command. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60024 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60013 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60117 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60010 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60010 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 54005 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 54005 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 54005 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 54005 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 54006 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 54007 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60701 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60152 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60702 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60702 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60703 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60703 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60704 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60704 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60706 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60706 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60706 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60706 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70600 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70600 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70600 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70601 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70601 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70601 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70601 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70602 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70602 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70602 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70602 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70603 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70603 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70603 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70603 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70604 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70604 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70605 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70605 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70605_Info does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70605_Info does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70606 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70606 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70606 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70607 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70607 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70608 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70608 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70609 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70609 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70609 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70610 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70610 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70611 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70611 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70612 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70612 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70612 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70612 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70612 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W164b_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W362b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W110_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W110_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W110_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W110_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W110_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name W110_b does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 70094 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60000_a does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 50520 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 50520 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name ExprParen and parameter name IGNORE_MODULE are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name ExprParen and parameter name IGNORE_MODULE are not associated, ignore the command. +[Error] LINT_CMD042: In configure_hdl_tag_param, tag name ExprParen and parameter name IGNORE_MODULE are not associated, ignore the command. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 2216 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 50002 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 50002 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name ParamReDefined does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name ParamReDefined does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name 60130 does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] RDB_CONFIGURE_BAD_TAG: None of the tag pattern(s) 'DetectUnderAndOverFlows-ML' (/users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/lint_rules.tcl:1298) were found. + Revise your tag list and try again.. +[Warning] TCL_COMMAND_FAILED: 'configure_tag' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD041: In configure_hdl_tag_param, parameter name DIFFERENTIATE_NESTED_CAST does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] LINT_CMD040: In configure_hdl_tag_param, tag name CheckGuardMacro does not exist. +[Warning] TCL_COMMAND_FAILED: 'configure_lint_tag_parameter' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Error] RDB_CONFIGURE_BAD_TAG: None of the tag pattern(s) 'AvoidMultiDimParam-ML' (/users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/lint_rules.tcl:1322) were found. + Revise your tag list and try again.. +[Warning] TCL_COMMAND_FAILED: 'configure_tag' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Error] RDB_CONFIGURE_BAD_TAG: None of the tag pattern(s) 'VC_WAIVER_ONLY_TAG_GIVEN' (/users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/lint_rules.tcl:1352) were found. + Revise your tag list and try again.. +[Warning] TCL_COMMAND_FAILED: 'configure_tag' command failed. [set sh_continue_on_error true] is set. Hence continuing the run. +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +[Info] COM_OPT030: Accepted message severity specification +# Replace this with the actual path to your .f file +set filelist_path $::env(FILE_LIST) +/users/amonemi/ProNoC/mpsoc/Integration_test/VCST/src/file_list.f +# Loop through lines +# File handle and storage +set fp [open $filelist_path r] +file29 +while {[gets $fp line] >= 0} { + set line [string trim $line] + + # Skip empty lines and comments + if {$line eq "" || [string match "#*" $line]} { + continue + } + + # Handle +incdir+ + #if {[string match "+incdir+*" $line]} { + # set incdir [string range $line 8 end] + # set_option include_path $incdir + # continue + #} + + # Add source file + lappend names_list $line +} +close $fp +analyze -format sverilog "$names_list" + +Warning-[UTSFM] Unspecified `timescale for module +./../../rtl/src_topology/./common/custom_ni_routing.v, 2 + Module "custom_ni_routing" has `timescale but previous module(s) do not. + Please either remove this module's timescale or add timescale for previous + module(s)to avoid unexpected simulation result. + + +Warning-[UTSFM] Unspecified `timescale for module +./../../rtl/src_topology/./common/custom_noc_top.sv, 3 + Module "custom_noc_top" has `timescale but previous module(s) do not. + Please either remove this module's timescale or add timescale for previous + module(s)to avoid unexpected simulation result. + + +Warning-[UTSFM] Unspecified `timescale for module +./../../rtl/src_topology/./common/custom_lkh_routing.v, 3 + Module "custom_lkh_routing" has `timescale but previous module(s) do not. + Please either remove this module's timescale or add timescale for previous + module(s)to avoid unexpected simulation result. + +1 +elaborate $DESIGN +[Warning] COM_OPT009: 'search_path' has not been set. +[Warning] COM_OPT010: 'link_library' has not been set. + +Warning-[LCA_FEATURES_ENABLED] Usage warning + LCA features enabled by '-lca' argument on the command line. For more + information regarding list of LCA features please refer to Chapter "LCA + features" in the VCS Release Notes + +Doing common elaboration + +Warning-[UESU] Incorrect -error switch used + Message ID 'SM_TUFC' is not an error ID , it is invalid to specify + 'noSM_TUFC' only in -error switch without 'all' argument in front of it. + If you meant to upgrade all messages to error except for ID 'SM_TUFC', + please use '-error=all,noSM_TUFC'. + + +Warning-[UESU] Incorrect -error switch used + Message ID 'SM_PNP' is not an error ID , it is invalid to specify 'noSM_PNP' + only in -error switch without 'all' argument in front of it. + If you meant to upgrade all messages to error except for ID 'SM_PNP', please + use '-error=all,noSM_PNP'. + + +Warning-[UESU] Incorrect -error switch used + Message ID 'SM_PCNP' is not an error ID , it is invalid to specify + 'noSM_PCNP' only in -error switch without 'all' argument in front of it. + If you meant to upgrade all messages to error except for ID 'SM_PCNP', + please use '-error=all,noSM_PCNP'. + + +Warning-[UESU] Incorrect -error switch used + Message ID 'SM_FCNF' is not an error ID , it is invalid to specify + 'noSM_FCNF' only in -error switch without 'all' argument in front of it. + If you meant to upgrade all messages to error except for ID 'SM_FCNF', + please use '-error=all,noSM_FCNF'. + +Final timescale is '1ps/1ps' + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 83 +"router_chan_out[(0 - 1)][pronoc_pkg::FORWARD]" + The select index is out of declared bounds : [3:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + + +Warning-[SIOB] Select index out of bounds +./../../rtl/src_noc/./mesh_torus_noc_top.sv, 79 +"router_chan_out[(3 + 1)][pronoc_pkg::BACKWARD]" + The select index is out of declared bounds : [3:0]. + In module instance : tori_noc.noc_top + In module : mesh_torus_noc_top. + +Info: Invoking Simon... +Info: Simon VCS Start +======================================================= +VCS CPU Time(s) :0.89 +SIMON CPU Time(s) :2.27 +SIMON Total Time(s) :0.48 +Peak Memory(MB) :411 +======================================================= +Info: Simon VCS Finished +Info: Simon call complete +Info: Exiting after Simon Analysis +Verdi KDB elaboration done and the database successfully generated: 0 error(s), 0 warning(s) +# Gate Counts +Number of Flat Instances = 65472 +Number of Operator = 65472 +Number of Libcells = 0 +Number of Black-Box Instances = 0 + +1 +#read_sdc $constraints_path +# Need to add this waiver in here, otherwise is not applicable +#source ${script_dir}/waiver.tcl +check_lint +[2025-06-05.14:55:11] Queuing for License...... +Waiting to acquire VC-LINT-BASE license in 259200 seconds... +[Info] Loading Lint Structural Checker Plugin... Success +Inferring all potential clocks +Inferring all potential resets +1 +report_lint -verbose -file ${report_filename} +1 +report_lint + + ----------------------------------------------------------------------------- + Management Summary + ----------------------------------------------------------------------------- + Stage Family Fatals Errors Warnings Infos Compressed + ----- -------- -------- -------- -------- -------- ---------- + BUILTIN_CHECK CODING 0 81 0 0 0 + LANGUAGE_CHECK CODING 0 1417 1662 6 0 + STRUCTURAL_CHECK CODING 0 8 727 1 463 + STRUCTURAL_CHECK CONN 0 0 1656 0 0 + ----- -------- -------- -------- -------- -------- ---------- + Total 0 1506 4045 7 463 + + + ----------------------------------------------------------------------------- + Tree Summary + ----------------------------------------------------------------------------- + Severity Stage Tag Count Compressed + -------- ----- ------------------------ ----- ---------- + error BUILTIN_CHECK ExprParen 81 0 + error LANGUAGE_CHECK AlwaysFalseTrueCond-ML 1157 0 + error LANGUAGE_CHECK NoAssignX-ML 15 0 + error LANGUAGE_CHECK OneModule-ML 14 0 + error LANGUAGE_CHECK STARC05-1.1.1.1 8 0 + error LANGUAGE_CHECK STARC05-1.1.1.3 154 0 + error LANGUAGE_CHECK STARC05-2.10.3.7 8 0 + error LANGUAGE_CHECK SignedUnsignedExpr-ML 1 0 + error LANGUAGE_CHECK UseSVAlways-ML 13 0 + error LANGUAGE_CHECK W121 6 0 + error LANGUAGE_CHECK W123 37 0 + error LANGUAGE_CHECK W215 1 0 + error LANGUAGE_CHECK W416 3 0 + error LANGUAGE_CHECK W504 1 0 + error STRUCTURAL_CHECK FlopEConst 1 0 + error STRUCTURAL_CHECK UndrivenOutPort-ML 7 4 + warning LANGUAGE_CHECK ConstName 95 0 + warning LANGUAGE_CHECK FileHdr 24 0 + warning LANGUAGE_CHECK ImproperRangeIndex-ML 1 0 + warning LANGUAGE_CHECK ParamName 178 0 + warning LANGUAGE_CHECK PortName 155 0 + warning LANGUAGE_CHECK STARC05-1.1.1.2 4 0 + warning LANGUAGE_CHECK SigName 5 0 + warning LANGUAGE_CHECK W120 176 0 + warning LANGUAGE_CHECK W175 40 0 + warning LANGUAGE_CHECK W240 902 0 + warning LANGUAGE_CHECK W241 25 0 + warning LANGUAGE_CHECK W287a 36 0 + warning LANGUAGE_CHECK W287b 23 0 + warning LANGUAGE_CHECK W468 1 0 + warning STRUCTURAL_CHECK RegInput-ML 150 157 + warning STRUCTURAL_CHECK RegOutputs 160 300 + warning STRUCTURAL_CHECK UndrivenNUnloaded-ML 369 0 + warning STRUCTURAL_CHECK UnloadedInPort-ML 907 0 + warning STRUCTURAL_CHECK UnloadedNet-ML 48 0 + warning STRUCTURAL_CHECK UnloadedOutTerm-ML 749 0 + info LANGUAGE_CHECK NoExprInPort-ML 1 0 + info LANGUAGE_CHECK ReportPortInfo-ML 1 0 + info STRUCTURAL_CHECK AvoidAsync 1 2 + -------- ----- ------------------------ ----- ---------- + Total 5558 463 + + +1 +exit 0 +======================================================= +Total Time(S) :191.15 +CPU Time(S) :45.49 +Peak Memory(MB):1264 +======================================================= diff --git a/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt new file mode 100644 index 0000000..cc2f40e --- /dev/null +++ b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt @@ -0,0 +1,17558 @@ + + ----------------------------------------------------------------------------- + Report Summary + ----------------------------------------------------------------------------- + Product Info + Name : VC Static Master Shell + Version : T-2022.06-SP2 -- Nov 29, 2022 + + Report Info + Created : Jun 05, 2025 14:57:59 + + TopLevelModule: noc_top + + ----------------------------------------------------------------------------- + Management Summary + ----------------------------------------------------------------------------- + Stage Family Fatals Errors Warnings Infos Compressed + ----- -------- -------- -------- -------- -------- ---------- + BUILTIN_CHECK CODING 0 81 0 0 0 + LANGUAGE_CHECK CODING 0 1417 1662 6 0 + STRUCTURAL_CHECK CODING 0 8 727 1 463 + STRUCTURAL_CHECK CONN 0 0 1656 0 0 + ----- -------- -------- -------- -------- -------- ---------- + Total 0 1506 4045 7 463 + + + ----------------------------------------------------------------------------- + Tree Summary + ----------------------------------------------------------------------------- + Severity Stage Tag Count Compressed + -------- ----- ------------------------ ----- ---------- + error BUILTIN_CHECK ExprParen 81 0 + error LANGUAGE_CHECK AlwaysFalseTrueCond-ML 1157 0 * + error LANGUAGE_CHECK NoAssignX-ML 15 0 + error LANGUAGE_CHECK OneModule-ML 14 0 + error LANGUAGE_CHECK STARC05-1.1.1.1 8 0 + error LANGUAGE_CHECK STARC05-1.1.1.3 154 0 * + error LANGUAGE_CHECK STARC05-2.10.3.7 8 0 + error LANGUAGE_CHECK SignedUnsignedExpr-ML 1 0 + error LANGUAGE_CHECK UseSVAlways-ML 13 0 + error LANGUAGE_CHECK W121 6 0 + error LANGUAGE_CHECK W123 37 0 + error LANGUAGE_CHECK W215 1 0 + error LANGUAGE_CHECK W416 3 0 + error LANGUAGE_CHECK W504 1 0 + error STRUCTURAL_CHECK FlopEConst 1 0 + error STRUCTURAL_CHECK UndrivenOutPort-ML 7 4 + warning LANGUAGE_CHECK ConstName 95 0 + warning LANGUAGE_CHECK FileHdr 24 0 + warning LANGUAGE_CHECK ImproperRangeIndex-ML 1 0 + warning LANGUAGE_CHECK ParamName 178 0 * + warning LANGUAGE_CHECK PortName 155 0 * + warning LANGUAGE_CHECK STARC05-1.1.1.2 4 0 + warning LANGUAGE_CHECK SigName 5 0 + warning LANGUAGE_CHECK W120 176 0 * + warning LANGUAGE_CHECK W175 40 0 + warning LANGUAGE_CHECK W240 902 0 * + warning LANGUAGE_CHECK W241 25 0 + warning LANGUAGE_CHECK W287a 36 0 + warning LANGUAGE_CHECK W287b 23 0 + warning LANGUAGE_CHECK W468 1 0 + warning STRUCTURAL_CHECK RegInput-ML 150 157 * + warning STRUCTURAL_CHECK RegOutputs 160 300 * + warning STRUCTURAL_CHECK UndrivenNUnloaded-ML 369 0 * + warning STRUCTURAL_CHECK UnloadedInPort-ML 907 0 * + warning STRUCTURAL_CHECK UnloadedNet-ML 48 0 + warning STRUCTURAL_CHECK UnloadedOutTerm-ML 749 0 * + info LANGUAGE_CHECK NoExprInPort-ML 1 0 + info LANGUAGE_CHECK ReportPortInfo-ML 1 0 + info STRUCTURAL_CHECK AvoidAsync 1 2 + -------- ----- ------------------------ ----- ---------- + Total 5558 463 + + * The following detailed reports have been limited to 100 per tag. + + + ----------------------------------------------------------------------------- + AlwaysFalseTrueCond-ML (1157 errors/0 waived) + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5097 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 508 + Statement : if(IS_MULTI_MESH==0) begin :ovc_ + RTL_CONDITION : (IS_MULTI_MESH==0) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4225 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 234 + Statement : P_1 = (SELF_LOOP_EN )? P : P-1, + RTL_CONDITION : SELF_LOOP_EN + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5713 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 947 + Statement : if(CAST_TYPE== "UNICAST") begin : unicast + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5776 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (TOPOLOGY=="MESH") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4126 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1145 + Statement : if (TOPOLOGY == "RING" || TOPOLOGY == "LINE" ) begin : one_D + RTL_CONDITION : ((TOPOLOGY=="RING")||(TOPOLOGY=="LINE")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5686 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 441 + Statement : if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat + RTL_CONDITION : (ROUTE_NAME=="NCA_STRAIGHT_UP") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5670 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : ((((((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH"))||(TOPOLOGY=="TORUS"))&&(T3 > 1))&&(CAST_TYPE=="UNICAST")) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3564 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 275 + Statement : NE = + RTL_CONDITION : ((IS_RING||IS_LINE)||IS_MESH) + NodeType : false + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5194 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 480 + Statement : ( MIN_PCK_SIZE == 1 )? flit_is_tail[i] & ~ovc_is_assigned[i] : 1'b0; + RTL_CONDITION : (MIN_PCK_SIZE==1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5895 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 667 + Statement : if(CAST_TYPE!= "UNICAST") begin : muticast + RTL_CONDITION : (CAST_TYPE!="UNICAST") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3627 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 80 + Statement : (x < NX-1) ? router_chan_out[x+1][BACKWARD] : + RTL_CONDITION : (x < (NX - 1)) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4797 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 69 + Statement : if(TOPOLOGY == "MESH" || TOPOLOGY == "FMESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :mesh_torus + RTL_CONDITION : (((TOPOLOGY=="MESH")||(TOPOLOGY=="FMESH"))||(TOPOLOGY=="TORUS")) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[1].smart_en.smart_allocator @smart_allocator_per_iport:routing@conventional_routing + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5521 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 332 + Statement : assign smart_hdr_en = (SMART_EN) ? smart_ctrl_in.ivc_num_getting_ovc_grant: {V{1'b0}}; + RTL_CONDITION : SMART_EN + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5709 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 846 + Statement : if(SWA_ARBITER_TYPE != "RRA")begin : wrra + RTL_CONDITION : (SWA_ARBITER_TYPE!="RRA") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4071 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (((((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH"))||(TOPOLOGY=="TORUS"))&&(T3 > 1)) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5668 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 247 + Statement : PLw = (IS_FMESH) ? Pw : ELw, + RTL_CONDITION : IS_FMESH + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5877 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (TOPOLOGY=="RING") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5799 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (TOPOLOGY=="RING") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5437 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 441 + Statement : if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat + RTL_CONDITION : ((TOPOLOGY=="FATTREE")&&(ROUTE_NAME=="NCA_STRAIGHT_UP")) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4109 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 586 + Statement : if(MAX_DEPTH>2) begin :mwb2 + RTL_CONDITION : (MAX_DEPTH > 2) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\V_[0].smart_.dest_e_addr_fifo @fwft_fifo + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4087 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 929 + Statement : if(PORT_IVC != V) begin : hetero + RTL_CONDITION : (PORT_IVC!=V) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4272 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 821 + Statement : end else if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST") begin : fmesh + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3587 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./pronoc_pkg.sv + LineNumber : 26 + Statement : SMART_EN = (SMART_MAX !=0), + RTL_CONDITION : (SMART_MAX!=0) + NodeType : false + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4111 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1112 + Statement : localparam P_1 = (SELF_LOOP_EN )? P : P-1; + RTL_CONDITION : SELF_LOOP_EN + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5784 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 441 + Statement : if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat + RTL_CONDITION : (TOPOLOGY=="FATTREE") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4982 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : ((TOPOLOGY=="RING")||(TOPOLOGY=="LINE")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5212 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 821 + Statement : end else if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST") begin : fmesh + RTL_CONDITION : ((TOPOLOGY=="FMESH")&&(CAST_TYPE=="UNICAST")) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4284 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1166 + Statement : end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh + RTL_CONDITION : ((TOPOLOGY=="RING")||(TOPOLOGY=="LINE")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5900 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5216 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 868 + Statement : if(SWA_ARBITER_TYPE != "RRA")begin : wrra + RTL_CONDITION : (SWA_ARBITER_TYPE!="RRA") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5673 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3847 + Goal : lint_rtl + Module : one_hot_to_bin + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 274 + Statement : if(ONE_HOT_WIDTH>1)begin :if1 + RTL_CONDITION : (ONE_HOT_WIDTH > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer:\pow2.wr_vc_start_addr @one_hot_to_bin + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5773 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : ((TOPOLOGY=="RING")||(TOPOLOGY=="LINE")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3576 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 296 + Statement : MCASTw = + RTL_CONDITION : (EAw < MCAST_PRTLw) + NodeType : true + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5070 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 240 + Statement : NON_ATOM_PCKS = (PORT_B>MIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, + RTL_CONDITION : (PORT_B > MIN_PCK_SIZE) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3895 + Goal : lint_rtl + Module : remove_sw_loc_one_hot + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 472 + Statement : if(SW_LOC==0)begin :local_p + RTL_CONDITION : (SW_LOC==0) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator:mask_destport@mesh_torus_mask_non_assignable_destport:\slp.remove_sw_loc @remove_sw_loc_one_hot + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3679 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 197 + Statement : if(CAST_TYPE == "UNICAST") begin : uni + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5795 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (((((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH"))||(TOPOLOGY=="TORUS"))&&(T3 > 1)) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4145 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1319 + Statement : if(SELF_LOOP_EN == 0) begin :nslp + RTL_CONDITION : (SELF_LOOP_EN==0) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator:\one_D.decoder @line_ring_destp_decoder + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4783 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 606 + Statement : (IS_RING | IS_LINE) ? (SW_LOC == 0 || SW_LOC > 2) : + RTL_CONDITION : (SW_LOC==0) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[1].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4315 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 287 + Statement : if(TOPOLOGY == "MESH" || TOPOLOGY == "FMESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE")begin :mesh_torus + RTL_CONDITION : (((((TOPOLOGY=="MESH")||(TOPOLOGY=="FMESH"))||(TOPOLOGY=="TORUS"))||(TOPOLOGY=="RING"))||(TOPOLOGY=="LINE")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port:\unicast.lk_routing @look_ahead_routing + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5704 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (T3 > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5613 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 283 + Statement : if( SSA_EN == 1 ) begin : ssa + RTL_CONDITION : (SSA_EN==1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3807 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 947 + Statement : if(CAST_TYPE== "UNICAST") begin : unicast + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3874 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1166 + Statement : end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh + RTL_CONDITION : (TOPOLOGY=="RING") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3575 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 296 + Statement : MCASTw = + RTL_CONDITION : ((CAST_TYPE=="MULTICAST_PARTIAL")&&(EAw < MCAST_PRTLw)) + NodeType : true + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3848 + Goal : lint_rtl + Module : fifo_ram + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 459 + Statement : if(SSA_EN == 1) begin :predict + RTL_CONDITION : (SSA_EN==1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer:\pow2.the_queue @fifo_ram + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5000 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 643 + Statement : if(C>1)begin :cb1 + RTL_CONDITION : (C > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5528 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (TOPOLOGY=="LINE") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5218 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 929 + Statement : if(PORT_IVC != V) begin : hetero + RTL_CONDITION : (PORT_IVC!=V) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5677 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (TOPOLOGY=="MESH") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4799 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 69 + Statement : if(TOPOLOGY == "MESH" || TOPOLOGY == "FMESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :mesh_torus + RTL_CONDITION : (TOPOLOGY=="MESH") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[1].smart_en.smart_allocator @smart_allocator_per_iport:routing@conventional_routing + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5867 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 242 + Statement : IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN==1) || (SMART_EN==1))? "YES" : "NO"; + RTL_CONDITION : ((SSA_EN==1)||(SMART_EN==1)) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4912 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 164 + Statement : end else if (IS_MULTI_MESH) begin + RTL_CONDITION : IS_MULTI_MESH + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3929 + Goal : lint_rtl + Module : mesh_tori_endp_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 955 + Statement : EYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE")? 1 : log2(NY), + RTL_CONDITION : (TOPOLOGY=="RING") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\unicast.lk_routing @look_ahead_routing:\mesh_torus.mesh.end_addr_decode @mesh_tori_endp_addr_decode + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5096 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 491 + Statement : if( P==MAX_P ) begin + RTL_CONDITION : (P==MAX_P) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5685 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 441 + Statement : if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat + RTL_CONDITION : (TOPOLOGY=="FATTREE") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3771 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (TOPOLOGY=="MESH") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5416 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 240 + Statement : NON_ATOM_PCKS = (PORT_B>MIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, + RTL_CONDITION : (PORT_B > MIN_PCK_SIZE) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5805 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 821 + Statement : end else if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST") begin : fmesh + RTL_CONDITION : ((TOPOLOGY=="FMESH")&&(CAST_TYPE=="UNICAST")) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4976 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 247 + Statement : PLw = (IS_FMESH) ? Pw : ELw, + RTL_CONDITION : IS_FMESH + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5696 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (((((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH"))||(TOPOLOGY=="TORUS"))&&(T3 > 1)) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3601 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./pronoc_pkg.sv + LineNumber : 55 + Statement : OVC_ALLOC_MODE= ((V==1 || B <= 4) ) ? 1'b1 : 1'b0; + RTL_CONDITION : ((V==1)||(B<=4)) + NodeType : false + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3591 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./pronoc_pkg.sv + LineNumber : 32 + Statement : localparam CONGw= + RTL_CONDITION : (CONGESTION_INDEX==5) + NodeType : true + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5804 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3868 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1123 + Statement : if(CAST_TYPE!= "UNICAST") begin : muticast + RTL_CONDITION : (CAST_TYPE!="UNICAST") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5363 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 846 + Statement : if(SWA_ARBITER_TYPE != "RRA")begin : wrra + RTL_CONDITION : (SWA_ARBITER_TYPE!="RRA") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5679 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (T3 > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3534 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 121 + Statement : if(IS_MESH || IS_FMESH || IS_TORUS || IS_RING || IS_LINE)begin + RTL_CONDITION : (IS_MESH||IS_FMESH) + NodeType : true + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5012 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (T3 > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5119 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 929 + Statement : if(PORT_IVC != V) begin : hetero + RTL_CONDITION : (PORT_IVC!=V) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5428 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (TOPOLOGY=="RING") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3565 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 275 + Statement : NE = + RTL_CONDITION : (IS_RING||IS_LINE) + NodeType : false + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4292 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1132 + Statement : localparam P_1 = (SELF_LOOP_EN )? P : P-1; + RTL_CONDITION : SELF_LOOP_EN + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5427 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : ((TOPOLOGY=="RING")||(TOPOLOGY=="LINE")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3670 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 161 + Statement : if(SS_PORT == DISABLED) begin: smart_dis + RTL_CONDITION : (SS_PORT==DISABLED) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4171 + Goal : lint_rtl + Module : mesh_torus_deterministic_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 132 + Statement : Yw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 : log2(NY); // number of node in y axis + RTL_CONDITION : ((TOPOLOGY=="RING")||(TOPOLOGY=="LINE")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\unicast.lk_routing @look_ahead_routing:\mesh_torus.look_ahead_route @mesh_torus_look_ahead_routing:\dtrmst.deterministic_look_ahead @mesh_torus_deterministic_look_ahead_routing + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3871 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1166 + Statement : end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh + RTL_CONDITION : ((((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH"))||(TOPOLOGY=="TORUS")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3767 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5700 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (TOPOLOGY=="RING") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4073 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3572 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 296 + Statement : MCASTw = + RTL_CONDITION : ((CAST_TYPE=="MULTICAST_PARTIAL")&&(EAw>=MCAST_PRTLw)) + NodeType : true + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4112 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1123 + Statement : if(CAST_TYPE!= "UNICAST") begin : muticast + RTL_CONDITION : (CAST_TYPE!="UNICAST") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3593 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./pronoc_pkg.sv + LineNumber : 32 + Statement : localparam CONGw= + RTL_CONDITION : (CONGESTION_INDEX==9) + NodeType : true + HIERARCHY : :noc_top + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5466 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 947 + Statement : if(CAST_TYPE== "UNICAST") begin : unicast + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4998 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 508 + Statement : if(IS_MULTI_MESH==0) begin :ovc_ + RTL_CONDITION : (IS_MULTI_MESH==0) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5186 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5767 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 247 + Statement : PLw = (IS_FMESH) ? Pw : ELw, + RTL_CONDITION : IS_FMESH + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5778 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (T3 > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5333 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (T3 > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5079 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : ((((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH"))||(TOPOLOGY=="TORUS")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4055 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_CONDITION : (CAST_TYPE=="UNICAST") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5451 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH")) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5202 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (((((TOPOLOGY=="RING")||(TOPOLOGY=="LINE"))||(TOPOLOGY=="MESH"))||(TOPOLOGY=="TORUS"))&&(T3 > 1)) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4169 + Goal : lint_rtl + Module : mesh_torus_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 43 + Statement : Yw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 : log2(NY); // number of node in y axis + RTL_CONDITION : (TOPOLOGY=="LINE") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\unicast.lk_routing @look_ahead_routing:\mesh_torus.look_ahead_route @mesh_torus_look_ahead_routing + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:3865 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 586 + Statement : if(MAX_DEPTH>2) begin :mwb2 + RTL_CONDITION : (MAX_DEPTH > 2) + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].smart_.dest_e_addr_fifo @fwft_fifo + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5791 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 643 + Statement : if(C>1)begin :cb1 + RTL_CONDITION : (C > 1) + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4266 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 800 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_CONDITION : (TOPOLOGY=="MESH") + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:4170 + Goal : lint_rtl + Module : mesh_torus_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 59 + Statement : if(ROUTE_TYPE=="DETERMINISTIC") begin :dtrmst + RTL_CONDITION : (ROUTE_TYPE=="DETERMINISTIC") + NodeType : false + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\unicast.lk_routing @look_ahead_routing:\mesh_torus.look_ahead_route @mesh_torus_look_ahead_routing + ----------------------------------------------------------------------------- + Tag : AlwaysFalseTrueCond-ML + Description : Condition '[RTL_CONDITION]' can never be '[NodeType]' [Hierarchy: '[HIERARCHY]'] + Violation : Lint:5174 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 247 + Statement : PLw = (IS_FMESH) ? Pw : ELw, + RTL_CONDITION : IS_FMESH + NodeType : true + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + + ----------------------------------------------------------------------------- + ExprParen (81 errors/0 waived) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5995 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 300 + Statement : localparam SL_SW_LOC = ( SW_LOC > P-T3) ? 0 : SW_LOC; //single_local + RTL_EXPRESSION : (Operators > and - used) + Node_Value : (Expr: (SW_LOC > (P - T3))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5958 + Goal : lint_rtl + Module : ovc_list + FileName : ./../../rtl/src_noc/./ovc_list.sv + LineNumber : 36 + Statement : logic [CVw-1 : 0] shiftted = CLASS_SETTING >> c*V; + RTL_EXPRESSION : (Operators >> and * used) + Node_Value : (Expr: (CLASS_SETTING >> (c * V))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5945 + Goal : lint_rtl + Module : + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 122 + Statement : if (router_port_num == 0 || router_port_num > 4 ) port_buffer_size = LB; + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((router_port_num == 0) || (router_port_num > 4))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5987 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 55 + Statement : while(2**log20 && SW_LOC<5) ? 1'b0 : dest_port_in [SW_LOC]; + RTL_EXPRESSION : (Operators > and && used) + Node_Value : (Expr: ((SW_LOC > 0) && (SW_LOC < 5))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5981 + Goal : lint_rtl + Module : xy_line_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 932 + Statement : while(2**log2= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; + RTL_EXPRESSION : (Operators >= and - used) + Node_Value : (Expr: (depth >= (MAX_DEPTH[(DEPTH_DATA_WIDTH - 1):0] - 1'b1))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6004 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 643 + Statement : assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; + RTL_EXPRESSION : (Operators >= and - used) + Node_Value : (Expr: (depth >= (MAX_DEPTH[(DEPTH_DATA_WIDTH - 1):0] - 1'b1))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6015 + Goal : lint_rtl + Module : mesh_tori_endp_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 955 + Statement : EYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE")? 1 : log2(NY), + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5998 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 294 + Statement : if (rd[i] ) rd_ptr_next[i] =(rd_ptr[i]==(B*(i+1))-1)? (B*i) : rd_ptr [i]+ 1'h1; + RTL_EXPRESSION : (Operators == and - used) + Node_Value : (Expr: (rd_ptr[i] == ((B * (i + 1)) - 1))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5957 + Goal : lint_rtl + Module : my_one_hot_arbiter + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 158 + Statement : while(2**log2 4 ) : 0; + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((SW_LOC == 0) || (SW_LOC > 4))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5966 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1166 + Statement : end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5974 + Goal : lint_rtl + Module : mesh_torus_next_router_addr_predictor + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 345 + Statement : Yw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE")? 1 : log2(NY); + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6021 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 152 + Statement : if(y == NY-1 ) assign chan_out_all [SOUTH_ID] = router_chan_out[fmesh_router_id(x, y)][SOUTH]; + RTL_EXPRESSION : (Operators == and - used) + Node_Value : (Expr: (y == (NY - 1))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5948 + Goal : lint_rtl + Module : + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 298 + Statement : (CAST_TYPE == "MULTICAST_PARTIAL" && EAw >= MCAST_PRTLw) ? EAw +1 : + RTL_EXPRESSION : (Operators == and && used) + Node_Value : (Expr: ((CAST_TYPE == "MULTICAST_PARTIAL") && (EAw >= MCAST_PRTLw))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5970 + Goal : lint_rtl + Module : mesh_torus_deterministic_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 123 + Statement : while(2**log21) && (CAST_TYPE== "UNICAST")) begin : multi_local + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5963 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 441 + Statement : if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat + RTL_EXPRESSION : (Operators == and && used) + Node_Value : (Expr: ((TOPOLOGY == "FATTREE") && (ROUTE_NAME == "NCA_STRAIGHT_UP"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5946 + Goal : lint_rtl + Module : + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 144 + Statement : (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((ROUTE_NAME == "XY") || (ROUTE_NAME == "TRANC_XY"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6011 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 381 + Statement : end else if ( ROUTE_NAME == "NEGETIVE_FIRST" || ROUTE_NAME == "TRANC_NEGETIVE_FIRST") begin :negetive_first + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((ROUTE_NAME == "NEGETIVE_FIRST") || (ROUTE_NAME == "TRANC_NEGETIVE_FIRST"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5971 + Goal : lint_rtl + Module : mesh_torus_deterministic_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 132 + Statement : Yw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 : log2(NY); // number of node in y axis + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6009 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 352 + Statement : end else if ( ROUTE_NAME == "WEST_FIRST" || ROUTE_NAME == "TRANC_WEST_FIRST") begin :west_first + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((ROUTE_NAME == "WEST_FIRST") || (ROUTE_NAME == "TRANC_WEST_FIRST"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5975 + Goal : lint_rtl + Module : mesh_torus_next_router_addr_predictor + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 368 + Statement : if(TOPOLOGY=="MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "FMESH" ) begin : mesh + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "MESH") || (TOPOLOGY == "TORUS"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5982 + Goal : lint_rtl + Module : check_straight_oport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 390 + Statement : if (SS_PORT_LOC == 0 || SS_PORT_LOC > 4) begin : local_ports + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((SS_PORT_LOC == 0) || (SS_PORT_LOC > 4))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5944 + Goal : lint_rtl + Module : + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 107 + Statement : (current_port == (router_port_num-1)/2) ? router_port_num: //DISABLED; + RTL_EXPRESSION : (Operators == and / used) + Node_Value : (Expr: (current_port == ((router_port_num - 1) / 2))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6017 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 80 + Statement : (x < NX-1) ? router_chan_out[x+1][BACKWARD] : + RTL_EXPRESSION : (Operators < and - used) + Node_Value : (Expr: (x < (NX - 1))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5980 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 638 + Statement : if (TOPOLOGY == "MESH" || TOPOLOGY == "FMESH")begin :mesh + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "MESH") || (TOPOLOGY == "FMESH"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5973 + Goal : lint_rtl + Module : mesh_torus_next_router_addr_predictor + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 337 + Statement : while(2**log2 2) : + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((SW_LOC == 0) || (SW_LOC > 2))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6010 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 369 + Statement : end else if ( ROUTE_NAME == "NORTH_LAST" || ROUTE_NAME == "TRANC_NORTH_LAST") begin :north_last + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((ROUTE_NAME == "NORTH_LAST") || (ROUTE_NAME == "TRANC_NORTH_LAST"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:6012 + Goal : lint_rtl + Module : mesh_tori_router_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 893 + Statement : while(2**log2 2) begin : local_ports + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((SS_PORT_LOC == 0) || (SS_PORT_LOC > 2))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5961 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 406 + Statement : if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && CAST_TYPE== "UNICAST") begin : multi_local + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5951 + Goal : lint_rtl + Module : + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 392 + Statement : end else if ( diff < 2* NX) begin //bottom mesh edge + RTL_EXPRESSION : (Operators < and * used) + Node_Value : (Expr: (diff < (2 * NX))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5989 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 75 + Statement : RYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 :log2(NY), + RTL_EXPRESSION : (Operators == and || used) + Node_Value : (Expr: ((TOPOLOGY == "RING") || (TOPOLOGY == "LINE"))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5943 + Goal : lint_rtl + Module : + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 93 + Statement : (IS_MULTI_MESH && current_port== DOWN)? UP: + RTL_EXPRESSION : (Operators && and == used) + Node_Value : (Expr: (IS_MULTI_MESH && (current_port == DOWN))) + ----------------------------------------------------------------------------- + Tag : ExprParen + Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] + Violation : Lint:5977 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 615 + Statement : while(2**log21)? log2(ONE_HOT_WIDTH):1 + CValue : BIN_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2934 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 30 + Statement : parameter ROUTER_ID=0, + CValue : ROUTER_ID + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2974 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 239 + Statement : parameter EAw = 3, + CValue : EAw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2913 + Goal : lint_rtl + Module : one_hot_mux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 115 + Statement : parameter OUT_WIDTH = IN_WIDTH/SEL_WIDTH + CValue : OUT_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2989 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 228 + Statement : parameter SELF_LOOP_EN=0 + CValue : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2966 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 33 + Statement : parameter ROUTE_NAME = "XY", + CValue : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2947 + Goal : lint_rtl + Module : mesh_torus_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 14 + Statement : parameter ROUTE_TYPE = "DETERMINISTIC"// "DETERMINISTIC", "FULL_ADAPTIVE", "PAR_ADAPTIVE" + CValue : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2910 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 29 + Statement : `define PRONOC_COMMON + CValue : PRONOC_COMMON + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2986 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 550 + Statement : parameter MAX_DEPTH = 2, + CValue : MAX_DEPTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2981 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 33 + Statement : parameter Fw = 36, + CValue : Fw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2975 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 240 + Statement : parameter DAw = 3, + CValue : DAw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2965 + Goal : lint_rtl + Module : full_ovc_predictor + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 535 + Statement : parameter SELF_LOOP_EN = 0 + CValue : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2916 + Goal : lint_rtl + Module : custom_or + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 170 + Statement : parameter OUT_WIDTH = 5 + CValue : OUT_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2937 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 33 + Statement : parameter ROUTER_ID=0, + CValue : ROUTER_ID + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2938 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 183 + Statement : parameter ROUTER_ID=0, + CValue : ROUTER_ID + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2969 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 39 + Statement : parameter EAw = 3, + CValue : EAw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2997 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1121 + Statement : parameter PPSw=4, + CValue : PPSw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2984 + Goal : lint_rtl + Module : fifo_ram + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 428 + Statement : parameter ADDR_WIDTH = 8, + CValue : ADDR_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2987 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 551 + Statement : parameter IGNORE_SAME_LOC_RD_WR_WARNING="YES" // "YES" , "NO" + CValue : IGNORE_SAME_LOC_RD_WR_WARNING + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2978 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 245 + Statement : parameter ROUTE_TYPE="DETERMINISTIC"// "DETERMINISTIC", "FULL_ADAPTIVE", "PAR_ADAPTIVE" + CValue : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2922 + Goal : lint_rtl + Module : arbiter + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 38 + Statement : parameter ARBITER_WIDTH =8 + CValue : ARBITER_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2936 + Goal : lint_rtl + Module : vc_alloc_request_gen_determinstic + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 606 + Statement : parameter CAST_TYPE = "UNICAST" + CValue : CAST_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2991 + Goal : lint_rtl + Module : mesh_tori_router_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 882 + Statement : parameter RAw=6 + CValue : RAw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2973 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 238 + Statement : parameter RAw = 3, + CValue : RAw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2919 + Goal : lint_rtl + Module : one_hot_to_bin + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 256 + Statement : parameter ONE_HOT_WIDTH = 4, + CValue : ONE_HOT_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2985 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 549 + Statement : parameter DATA_WIDTH = 2, + CValue : DATA_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2925 + Goal : lint_rtl + Module : extract_header_flit_info + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 109 + Statement : parameter DATA_w = 0 + CValue : DATA_w + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2912 + Goal : lint_rtl + Module : one_hot_mux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 114 + Statement : parameter SEL_WIDTH = 5, + CValue : SEL_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2942 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1097 + Statement : parameter PLw=1, + CValue : PLw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2968 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 38 + Statement : parameter RAw = 3, + CValue : RAw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2924 + Goal : lint_rtl + Module : my_one_hot_arbiter + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 146 + Statement : parameter ARBITER_WIDTH =4 + CValue : ARBITER_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2948 + Goal : lint_rtl + Module : mesh_torus_deterministic_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 111 + Statement : parameter ROUTE_NAME="XY"// "XY", "TRANC_XY" + CValue : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:3004 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 31 + Statement : parameter ROUTER_ID=0, + CValue : ROUTER_ID + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2972 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 42 + Statement : parameter LOCATED_IN_NI = 1 // only needed for mesh and odd-even routing + CValue : LOCATED_IN_NI + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2976 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 241 + Statement : parameter DSTPw=P-1, + CValue : DSTPw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2959 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 334 + Statement : parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001 + CValue : ESCAP_VC_MASK + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2931 + Goal : lint_rtl + Module : swa_input_port_arbiter + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 617 + Statement : parameter ARBITER_TYPE = "WRRA"// RRA, WRRA + CValue : ARBITER_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2951 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 603 + Statement : parameter LOCATED_IN_NI = 0//use for add even only + CValue : LOCATED_IN_NI + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2983 + Goal : lint_rtl + Module : fifo_ram + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 427 + Statement : parameter DATA_WIDTH = 32, + CValue : DATA_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2964 + Goal : lint_rtl + Module : full_ovc_predictor + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 534 + Statement : parameter OVC_ALLOC_MODE=1'b0, + CValue : OVC_ALLOC_MODE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2979 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 34 + Statement : parameter ROUTER_ID=0, + CValue : ROUTER_ID + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2944 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1100 + Statement : parameter SELF_LOOP_EN=0, + CValue : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2970 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 40 + Statement : parameter DAw = EAw, + CValue : DAw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2998 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1123 + Statement : parameter SELF_LOOP_EN=0 + CValue : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2994 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1116 + Statement : parameter ROUTE_TYPE = "DETERMINISTIC", + CValue : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2971 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 41 + Statement : parameter DSTPw = 4, + CValue : DSTPw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2932 + Goal : lint_rtl + Module : swa_output_port_arbiter + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 701 + Statement : parameter ARBITER_WIDTH =4, + CValue : ARBITER_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2958 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 333 + Statement : parameter ROUTE_TYPE="ADAPTIVE", + CValue : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2999 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1291 + Statement : parameter ROUTE_TYPE="DETERMINISTIC", + CValue : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2933 + Goal : lint_rtl + Module : swa_output_port_arbiter + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 702 + Statement : parameter ARBITER_TYPE = "WRRA" // RRA, WRRA + CValue : ARBITER_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:3000 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1293 + Statement : parameter DSTPw=2, + CValue : DSTPw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2963 + Goal : lint_rtl + Module : oport_ovc_sig_gen + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 461 + Statement : parameter SELF_LOOP_EN = 0 + CValue : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2954 + Goal : lint_rtl + Module : smart_credit_manage_per_vc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 745 + Statement : parameter Bw=2 + CValue : Bw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2993 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1115 + Statement : parameter ROUTE_NAME = "XY", + CValue : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:3003 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1298 + Statement : parameter SELF_LOOP_EN= 0 + CValue : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2982 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 36 + Statement : parameter SELF_LOOP_EN= 0 + CValue : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2995 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1118 + Statement : parameter DSTPw=4, + CValue : DSTPw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2977 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 244 + Statement : parameter ROUTE_NAME="XY",// + CValue : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2962 + Goal : lint_rtl + Module : congestion_out_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 951 + Statement : parameter CONGw=2 + CValue : CONGw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2923 + Goal : lint_rtl + Module : arbiter_priority_en + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 89 + Statement : parameter ARBITER_WIDTH =8 + CValue : ARBITER_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2943 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1098 + Statement : parameter PPSw=4, + CValue : PPSw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2980 + Goal : lint_rtl + Module : credit_release_gen + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 657 + Statement : parameter CREDIT_NUM=4 + CValue : CREDIT_NUM + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2953 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 538 + Statement : parameter SS_PORT_LOC=1 + CValue : SS_PORT_LOC + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2946 + Goal : lint_rtl + Module : mesh_torus_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 13 + Statement : parameter ROUTE_NAME = "XY",// + CValue : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2955 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 327 + Statement : parameter PPSw=4, + CValue : PPSw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2956 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 331 + Statement : parameter CONGESTION_INDEX=2, + CValue : CONGESTION_INDEX + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2930 + Goal : lint_rtl + Module : swa_input_port_arbiter + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 615 + Statement : parameter ARBITER_WIDTH =4, + CValue : ARBITER_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2927 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 429 + Statement : parameter SWA_ARBITER_TYPE = "WRRA", + CValue : SWA_ARBITER_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2950 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 600 + Statement : parameter ROUTE_TYPE = "DETERMINISTIC", + CValue : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2917 + Goal : lint_rtl + Module : bin_to_one_hot + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 237 + Statement : parameter BIN_WIDTH = 2, + CValue : BIN_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2941 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1096 + Statement : parameter DSTPw=4, + CValue : DSTPw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2961 + Goal : lint_rtl + Module : congestion_out_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 950 + Statement : parameter CONGESTION_INDEX=2, + CValue : CONGESTION_INDEX + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2921 + Goal : lint_rtl + Module : binary_mux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 299 + Statement : parameter OUT_WIDTH = 5 + CValue : OUT_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2918 + Goal : lint_rtl + Module : bin_to_one_hot + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 238 + Statement : parameter ONE_HOT_WIDTH = 2**BIN_WIDTH + CValue : ONE_HOT_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2939 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1091 + Statement : parameter ROUTE_NAME="XY", + CValue : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2996 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1120 + Statement : parameter PLw=1, + CValue : PLw + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2914 + Goal : lint_rtl + Module : one_hot_demux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 147 + Statement : parameter SEL_WIDTH=4, + CValue : SEL_WIDTH + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2990 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 282 + Statement : parameter ROUTE_NAME="XY", + CValue : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2911 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 35 + Statement : `define PRONOC_ARBITER + CValue : PRONOC_ARBITER + ----------------------------------------------------------------------------- + Tag : ConstName + Description : Constant '[CValue]' does not follow recommended naming convention + Violation : Lint:2926 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 428 + Statement : parameter FIRST_ARBITER_EXT_P_EN = 1, + CValue : FIRST_ARBITER_EXT_P_EN + + ----------------------------------------------------------------------------- + FileHdr (24 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5917 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5938 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./pronoc_pkg.sv + LineNumber : 2 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5929 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5924 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5928 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5932 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5922 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5935 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5925 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5918 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5920 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5940 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5936 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5919 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./ovc_list.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5916 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./../pronoc_def.v + LineNumber : 1 + Statement : `ifndef PRONOC_DEF + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5923 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5926 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5931 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5933 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5937 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5930 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5934 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5927 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 1 + Statement : `include "pronoc_def.v" + Reason_Name : Could not find file-header start + ----------------------------------------------------------------------------- + Tag : FileHdr + Description : Non-standard file header: [Reason_Name] + Violation : Lint:5939 + Goal : lint_rtl + Module : noc_top + FileName : ./src/noc_localparam.v + LineNumber : 1 + Statement : `ifdef NOC_LOCAL_PARAM + Reason_Name : Could not find file-header start + + ----------------------------------------------------------------------------- + ImproperRangeIndex-ML (1 warning/0 waived) + ----------------------------------------------------------------------------- + Tag : ImproperRangeIndex-ML + Description : Index '[RTL_EXPRESSION]' of width '[NewExprSize]' is [Reason_Name] than the width '[ExprSize]' required for the max value '[MaxValue]' of the signal '[NodeName]'[Hierarchy: [HIERARCHY]] + Violation : Lint:5862 + Goal : lint_rtl + Module : noc_top + FileName : ./../../rtl/src_noc/./topology_localparam.v + LineNumber : 337 + Statement : if( mcast_list[mcast_id_to_endp_id]==1'b1) begin + RTL_EXPRESSION : mcast_id_to_endp_id + NewExprSize : 32 + Reason_Name : larger + ExprSize : 2 + MaxValue : 3 + NodeName : mcast_list + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port:mcast_id_to_endp_id + + ----------------------------------------------------------------------------- + ParamName (178 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3204 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 603 + Statement : parameter LOCATED_IN_NI = 0//use for add even only + Param : LOCATED_IN_NI + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3200 + Goal : lint_rtl + Module : mesh_torus_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 14 + Statement : parameter ROUTE_TYPE = "DETERMINISTIC"// "DETERMINISTIC", "FULL_ADAPTIVE", "PAR_ADAPTIVE" + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3340 + Goal : lint_rtl + Module : mesh_tori_endp_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 955 + Statement : EYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE")? 1 : log2(NY), + Param : EYw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3166 + Goal : lint_rtl + Module : one_hot_mux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 115 + Statement : parameter OUT_WIDTH = IN_WIDTH/SEL_WIDTH + Param : OUT_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3299 + Goal : lint_rtl + Module : credit_monitor_per_ovc + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 415 + Statement : DEPTHw = log2(PORT_B+1); + Param : DEPTHw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3326 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 58 + Statement : BVw = log2(BV), + Param : BVw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3303 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 76 + Statement : EXw = RXw, + Param : EXw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3233 + Goal : lint_rtl + Module : credit_release_gen + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 657 + Statement : parameter CREDIT_NUM=4 + Param : CREDIT_NUM + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3298 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 72 + Statement : localparam CONG_ALw= CONGw * P; // congestion width per router; + Param : CONG_ALw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3330 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 62 + Statement : BVwV = BVw * V, + Param : BVwV + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3323 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 63 + Statement : P_1Fw = P_1 * Fw, + Param : P_1Fw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3306 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 146 + Statement : LKw= L*Kw, + Param : LKw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3211 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 333 + Statement : parameter ROUTE_TYPE="ADAPTIVE", + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3230 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 244 + Statement : parameter ROUTE_NAME="XY",// + Param : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3258 + Goal : lint_rtl + Module : one_hot_to_bin + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 270 + Statement : localparam MUX_IN_WIDTH = BIN_WIDTH* ONE_HOT_WIDTH; + Param : MUX_IN_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3217 + Goal : lint_rtl + Module : full_ovc_predictor + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 534 + Statement : parameter OVC_ALLOC_MODE=1'b0, + Param : OVC_ALLOC_MODE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3267 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 104 + Statement : PRAw= P * RAw; + Param : PRAw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3261 + Goal : lint_rtl + Module : extract_header_flit_info + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 132 + Statement : Dw = (DATA_w==0)? 1 : DATA_w, + Param : Dw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3341 + Goal : lint_rtl + Module : mesh_tori_endp_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 956 + Statement : ELw = log2(NL); // number of node in y axis + Param : ELw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3300 + Goal : lint_rtl + Module : credit_monitor_per_ovc + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 416 + Statement : localparam [DEPTHw-1 : 0] Bint = PORT_B [DEPTHw-1 : 0]; + Param : Bint + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3178 + Goal : lint_rtl + Module : extract_header_flit_info + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 109 + Statement : parameter DATA_w = 0 + Param : DATA_w + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3169 + Goal : lint_rtl + Module : custom_or + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 170 + Statement : parameter OUT_WIDTH = 5 + Param : OUT_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3322 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 62 + Statement : PFw = P*Fw, + Param : PFw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3256 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1298 + Statement : parameter SELF_LOOP_EN= 0 + Param : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3331 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 63 + Statement : RESTw = Fw -2-V , + Param : RESTw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3213 + Goal : lint_rtl + Module : congestion_out_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 949 + Statement : parameter ROUTE_TYPE ="ADAPTIVE", + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3329 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 61 + Statement : BwV = Bw * V, + Param : BwV + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3327 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 59 + Statement : Vw = (V==1)? 1 : log2(V), + Param : Vw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3187 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 30 + Statement : parameter ROUTER_ID=0, + Param : ROUTER_ID + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3262 + Goal : lint_rtl + Module : extract_header_flit_info + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 135 + Statement : OFFSETw = DATA_MSB - DATA_LSB +1; + Param : OFFSETw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3310 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 272 + Statement : Lw = log2(T2), + Param : Lw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3216 + Goal : lint_rtl + Module : oport_ovc_sig_gen + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 461 + Statement : parameter SELF_LOOP_EN = 0 + Param : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3192 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1091 + Statement : parameter ROUTE_NAME="XY", + Param : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3288 + Goal : lint_rtl + Module : mesh_torus_next_router_addr_predictor + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 358 + Statement : localparam [Yw-1 : 0] LAST_Y_ADDR =(NY[Yw-1 : 0]-1'b1); + Param : LAST_Y_ADDR + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3281 + Goal : lint_rtl + Module : mesh_torus_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 42 + Statement : Xw = log2(NX), // number of node in x axis + Param : Xw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3328 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 60 + Statement : DEPTHw = log2(B+1), + Param : DEPTHw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3221 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 38 + Statement : parameter RAw = 3, + Param : RAw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3186 + Goal : lint_rtl + Module : swa_output_port_arbiter + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 702 + Statement : parameter ARBITER_TYPE = "WRRA" // RRA, WRRA + Param : ARBITER_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3198 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1101 + Statement : parameter CAST_TYPE = "UNICAST" + Param : CAST_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3222 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 39 + Statement : parameter EAw = 3, + Param : EAw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3305 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 145 + Statement : Kw = log2(K), + Param : Kw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3324 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 64 + Statement : P_1w = log2(P_1); + Param : P_1w + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3189 + Goal : lint_rtl + Module : vc_alloc_request_gen_determinstic + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 606 + Statement : parameter CAST_TYPE = "UNICAST" + Param : CAST_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3206 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 538 + Statement : parameter SS_PORT_LOC=1 + Param : SS_PORT_LOC + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3336 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 575 + Statement : localparam MUX_SEL_WIDTH = log2(MAX_DEPTH-1); + Param : MUX_SEL_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3237 + Goal : lint_rtl + Module : fifo_ram + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 428 + Statement : parameter ADDR_WIDTH = 8, + Param : ADDR_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3274 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 240 + Statement : NON_ATOM_PCKS = (PORT_B>MIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, + Param : NON_ATOM_PCKS + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3276 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 245 + Statement : ELw = log2(T3), + Param : ELw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3259 + Goal : lint_rtl + Module : binary_mux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 316 + Statement : SEL_WIDTH_BIN = (IN_NUM>1) ? log2(IN_NUM): 1; + Param : SEL_WIDTH_BIN + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3283 + Goal : lint_rtl + Module : mesh_torus_deterministic_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 131 + Statement : Xw = log2(NX), // number of node in x axis + Param : Xw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3318 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 300 + Statement : localparam SL_SW_LOC = ( SW_LOC > P-T3) ? 0 : SW_LOC; //single_local + Param : SL_SW_LOC + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3301 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 74 + Statement : RXw = log2(NX), + Param : RXw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3238 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 549 + Statement : parameter DATA_WIDTH = 2, + Param : DATA_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3332 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 64 + Statement : PTRw = ((2**Bw)==B)? Bw : BVw, // if B is power of 2 PTRw is Bw else is BVw + Param : PTRw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3214 + Goal : lint_rtl + Module : congestion_out_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 950 + Statement : parameter CONGESTION_INDEX=2, + Param : CONGESTION_INDEX + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3339 + Goal : lint_rtl + Module : mesh_tori_endp_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 954 + Statement : EXw = log2(NX), // number of node in x axis + Param : EXw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3296 + Goal : lint_rtl + Module : congestion_out_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 963 + Statement : CONG_ALw = CONGw* P; // congestion width per router;; + Param : CONG_ALw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3284 + Goal : lint_rtl + Module : mesh_torus_deterministic_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 132 + Statement : Yw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 : log2(NY); // number of node in y axis + Param : Yw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3319 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 87 + Statement : PFw = P*Fw, + Param : PFw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3174 + Goal : lint_rtl + Module : binary_mux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 299 + Statement : parameter OUT_WIDTH = 5 + Param : OUT_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3184 + Goal : lint_rtl + Module : swa_input_port_arbiter + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 617 + Statement : parameter ARBITER_TYPE = "WRRA"// RRA, WRRA + Param : ARBITER_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3278 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 247 + Statement : PLw = (IS_FMESH) ? Pw : ELw, + Param : PLw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3313 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 275 + Statement : PLKw = P * LKw; + Param : PLKw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3243 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 282 + Statement : parameter ROUTE_NAME="XY", + Param : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3280 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 249 + Statement : PRAw= P * RAw; + Param : PRAw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3229 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 241 + Statement : parameter DSTPw=P-1, + Param : DSTPw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3311 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 273 + Statement : LKw= T2 * Kw, + Param : LKw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3337 + Goal : lint_rtl + Module : mesh_tori_router_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 902 + Statement : RXw = log2(NX), // number of node in x axis + Param : RXw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3182 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 431 + Statement : parameter SELF_LOOP_EN=0 + Param : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3241 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 225 + Statement : parameter ROUTE_NAME="XY", + Param : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3165 + Goal : lint_rtl + Module : one_hot_mux + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 114 + Statement : parameter SEL_WIDTH = 5, + Param : SEL_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3287 + Goal : lint_rtl + Module : mesh_torus_next_router_addr_predictor + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 357 + Statement : localparam [Xw-1 : 0] LAST_X_ADDR =(NX[Xw-1 : 0]-1'b1); + Param : LAST_X_ADDR + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3203 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 600 + Statement : parameter ROUTE_TYPE = "DETERMINISTIC", + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3308 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 267 + Statement : PRAw= P * RAw; + Param : PRAw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3273 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 231 + Statement : VDSTPw = V * DSTPw, + Param : VDSTPw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3309 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 271 + Statement : Kw = log2(T1), + Param : Kw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3314 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 292 + Statement : RXw = log2(NX), + Param : RXw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3207 + Goal : lint_rtl + Module : smart_credit_manage_per_vc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 745 + Statement : parameter Bw=2 + Param : Bw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3252 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1291 + Statement : parameter ROUTE_TYPE="DETERMINISTIC", + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3171 + Goal : lint_rtl + Module : bin_to_one_hot + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 238 + Statement : parameter ONE_HOT_WIDTH = 2**BIN_WIDTH + Param : ONE_HOT_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3249 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1120 + Statement : parameter PLw=1, + Param : PLw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3193 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1092 + Statement : parameter ROUTE_TYPE="DETERMINISTIC", + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3172 + Goal : lint_rtl + Module : one_hot_to_bin + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 256 + Statement : parameter ONE_HOT_WIDTH = 4, + Param : ONE_HOT_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3264 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 98 + Statement : PFw = P * Fw, + Param : PFw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3253 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1293 + Statement : parameter DSTPw=2, + Param : DSTPw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3325 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 56 + Statement : Bw = (B==1)? 1 : log2(B), + Param : Bw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3291 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 628 + Statement : DSTw = P_1; + Param : DSTw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3316 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 294 + Statement : EXw = RXw, + Param : EXw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3290 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 627 + Statement : Xw = log2(NX), + Param : Xw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3224 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 41 + Statement : parameter DSTPw = 4, + Param : DSTPw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3202 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 599 + Statement : parameter ROUTE_NAME = "XY", + Param : ROUTE_NAME + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3170 + Goal : lint_rtl + Module : bin_to_one_hot + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 237 + Statement : parameter BIN_WIDTH = 2, + Param : BIN_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3195 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1097 + Statement : parameter PLw=1, + Param : PLw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3235 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 36 + Statement : parameter SELF_LOOP_EN= 0 + Param : SELF_LOOP_EN + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3277 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 246 + Statement : Pw = log2(P), + Param : Pw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3248 + Goal : lint_rtl + Module : mesh_torus_destp_generator + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1118 + Statement : parameter DSTPw=4, + Param : DSTPw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3181 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 430 + Statement : parameter MIN_PCK_SIZE=2, //minimum packet size in flits. The minimum value is 1. + Param : MIN_PCK_SIZE + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3271 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 87 + Statement : PRAw= P * RAw; + Param : PRAw + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3176 + Goal : lint_rtl + Module : arbiter_priority_en + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 89 + Statement : parameter ARBITER_WIDTH =8 + Param : ARBITER_WIDTH + ----------------------------------------------------------------------------- + Tag : ParamName + Description : Parameter name [Param] does not follow naming convention + Violation : Lint:3180 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 429 + Statement : parameter SWA_ARBITER_TYPE = "WRRA", + Param : SWA_ARBITER_TYPE + + ----------------------------------------------------------------------------- + PortName (155 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3042 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 57 + Statement : granted_dest_port_all, + Mod_Port_Name : granted_dest_port_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3073 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 189 + Statement : ivc_num_getting_sw_grant,// for non spec ivc_num_getting_first_sw_grant, + Mod_Port_Name : ivc_num_getting_sw_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3106 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 447 + Statement : smart_single_flit_pck_o, + Mod_Port_Name : smart_single_flit_pck_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3054 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 81 + Statement : vsa_credit_decreased_all, + Mod_Port_Name : vsa_credit_decreased_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3052 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 77 + Statement : refresh_w_counter, + Mod_Port_Name : refresh_w_counter + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3126 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 564 + Statement : smart_mask_available_ss_ovc_o, + Mod_Port_Name : smart_mask_available_ss_ovc_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3107 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 448 + Statement : smart_ivc_smart_en_o, + Mod_Port_Name : smart_ivc_smart_en_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3131 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 339 + Statement : congestion_in_all, + Mod_Port_Name : congestion_in_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3058 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 445 + Statement : ivc_num_getting_ovc_grant, + Mod_Port_Name : ivc_num_getting_ovc_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3134 + Goal : lint_rtl + Module : congestion_out_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 954 + Statement : ivc_num_getting_sw_grant, + Mod_Port_Name : ivc_num_getting_sw_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3024 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 439 + Statement : first_arbiter_granted_ivc_all, + Mod_Port_Name : first_arbiter_granted_ivc_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3080 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 212 + Statement : granted_dest_port, + Mod_Port_Name : granted_dest_port + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3141 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 43 + Statement : congestion_in_all, + Mod_Port_Name : congestion_in_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3035 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 49 + Statement : vsa_ovc_allocated_all, + Mod_Port_Name : vsa_ovc_allocated_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3153 + Goal : lint_rtl + Module : full_ovc_predictor + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 537 + Statement : ssa_granted_ovc_num, + Mod_Port_Name : ssa_granted_ovc_num + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3111 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 453 + Statement : smart_mask_available_ss_ovc_o, + Mod_Port_Name : smart_mask_available_ss_ovc_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3045 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 60 + Statement : granted_dst_is_from_a_single_flit_pck, + Mod_Port_Name : granted_dst_is_from_a_single_flit_pck + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3105 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 445 + Statement : ss_ovc_crossbar_wr, + Mod_Port_Name : ss_ovc_crossbar_wr + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3037 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 51 + Statement : ivc_num_getting_ovc_grant, + Mod_Port_Name : ivc_num_getting_ovc_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3156 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 252 + Statement : lkdestport_encoded, // look ahead destination port number + Mod_Port_Name : lkdestport_encoded + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3038 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 53 + Statement : nonspec_first_arbiter_granted_ivc_all, + Mod_Port_Name : nonspec_first_arbiter_granted_ivc_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3009 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 42 + Statement : ovc_allocated_all,//to the output port + Mod_Port_Name : ovc_allocated_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3074 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 190 + Statement : any_ivc_sw_request_granted, + Mod_Port_Name : any_ivc_sw_request_granted + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3133 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 341 + Statement : credit_increased_all, + Mod_Port_Name : credit_increased_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3044 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 59 + Statement : any_ovc_granted_in_outport_all, + Mod_Port_Name : any_ovc_granted_in_outport_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3132 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 340 + Statement : credit_decreased_all, + Mod_Port_Name : credit_decreased_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3149 + Goal : lint_rtl + Module : credit_monitor_per_ovc + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 401 + Statement : credit_init_val_i, + Mod_Port_Name : credit_init_val_i + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3053 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 78 + Statement : crossbar_flit_out_wr_all, + Mod_Port_Name : crossbar_flit_out_wr_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3039 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 54 + Statement : spec_first_arbiter_granted_ivc_all, + Mod_Port_Name : spec_first_arbiter_granted_ivc_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3092 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 43 + Statement : spec_granted_dest_port_all, + Mod_Port_Name : spec_granted_dest_port_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3028 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 444 + Statement : iport_weight_is_consumed_all, + Mod_Port_Name : iport_weight_is_consumed_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3136 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 33 + Statement : vsa_ovc_allocated_all, + Mod_Port_Name : vsa_ovc_allocated_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3055 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 82 + Statement : vsa_ovc_released_all, + Mod_Port_Name : vsa_ovc_released_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3104 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 444 + Statement : ss_port_link_reg_flit_wr, + Mod_Port_Name : ss_port_link_reg_flit_wr + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3077 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 209 + Statement : vc_weight_is_consumed, + Mod_Port_Name : vc_weight_is_consumed + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3020 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 434 + Statement : ivc_request_masked_all, + Mod_Port_Name : ivc_request_masked_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3108 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 450 + Statement : smart_buff_space_decreased_o, + Mod_Port_Name : smart_buff_space_decreased_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3012 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 48 + Statement : vc_weight_is_consumed_all, + Mod_Port_Name : vc_weight_is_consumed_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3135 + Goal : lint_rtl + Module : congestion_out_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 956 + Statement : congestion_out_all, + Mod_Port_Name : congestion_out_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3006 + Goal : lint_rtl + Module : header_flit_update_lk_route_ovc + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 205 + Statement : lk_dest_not_registered, + Mod_Port_Name : lk_dest_not_registered + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3018 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 56 + Statement : any_ovc_granted_in_outport_all, + Mod_Port_Name : any_ovc_granted_in_outport_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3057 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 438 + Statement : masked_ovc_request_all, + Mod_Port_Name : masked_ovc_request_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3010 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 43 + Statement : granted_ovc_num_all, // to the input port + Mod_Port_Name : granted_ovc_num_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3097 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 49 + Statement : granted_dst_is_from_a_single_flit_pck, + Mod_Port_Name : granted_dst_is_from_a_single_flit_pck + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3120 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 557 + Statement : smart_ivc_smart_en_o, + Mod_Port_Name : smart_ivc_smart_en_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3148 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 58 + Statement : credit_init_val_in + Mod_Port_Name : credit_init_val_in + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3124 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 562 + Statement : smart_ivc_num_getting_ovc_grant_o, + Mod_Port_Name : smart_ivc_num_getting_ovc_grant_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3047 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 66 + Statement : assigned_ovc_not_full_all, + Mod_Port_Name : assigned_ovc_not_full_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3142 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 44 + Statement : granted_dst_is_from_a_single_flit_pck, + Mod_Port_Name : granted_dst_is_from_a_single_flit_pck + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3026 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 442 + Statement : any_ovc_granted_all, + Mod_Port_Name : any_ovc_granted_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3123 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 561 + Statement : smart_ss_ovc_is_released_o, + Mod_Port_Name : smart_ss_ovc_is_released_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3060 + Goal : lint_rtl + Module : vc_alloc_request_gen_determinstic + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 611 + Statement : ovc_is_assigned_all, + Mod_Port_Name : ovc_is_assigned_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3113 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 455 + Statement : smart_ivc_reset_o, + Mod_Port_Name : smart_ivc_reset_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3025 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 441 + Statement : any_ivc_granted_all, + Mod_Port_Name : any_ivc_granted_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3125 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 563 + Statement : smart_ivc_reset_o, + Mod_Port_Name : smart_ivc_reset_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3019 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 57 + Statement : granted_dst_is_from_a_single_flit_pck, + Mod_Port_Name : granted_dst_is_from_a_single_flit_pck + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3121 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 559 + Statement : smart_buff_space_decreased_o, + Mod_Port_Name : smart_buff_space_decreased_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3033 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 44 + Statement : credit_init_val_in, + Mod_Port_Name : credit_init_val_in + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3023 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 438 + Statement : granted_dest_port_all, + Mod_Port_Name : granted_dest_port_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3008 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 39 + Statement : pck_is_single_flit_all, + Mod_Port_Name : pck_is_single_flit_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3146 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 50 + Statement : vsa_ovc_released_all, + Mod_Port_Name : vsa_ovc_released_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3082 + Goal : lint_rtl + Module : destp_generator + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1104 + Statement : dest_port_encoded, + Mod_Port_Name : dest_port_encoded + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3040 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 55 + Statement : nonspec_granted_dest_port_all, + Mod_Port_Name : nonspec_granted_dest_port_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3016 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 54 + Statement : nonspec_first_arbiter_granted_ivc_all, + Mod_Port_Name : nonspec_first_arbiter_granted_ivc_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3159 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 560 + Statement : output recieve_more_than_1, + Mod_Port_Name : recieve_more_than_1 + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3076 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 205 + Statement : nonspec_first_arbiter_granted_ivc, + Mod_Port_Name : nonspec_first_arbiter_granted_ivc + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3088 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 39 + Statement : spec_first_arbiter_granted_ivc_all, + Mod_Port_Name : spec_first_arbiter_granted_ivc_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3034 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 45 + Statement : credit_init_val_out, + Mod_Port_Name : credit_init_val_out + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3116 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 551 + Statement : ovc_locally_requested,//make sure no conflict is existed between local & SMART VC allocation + Mod_Port_Name : ovc_locally_requested + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3151 + Goal : lint_rtl + Module : oport_ovc_sig_gen + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 466 + Statement : granted_dest_port, + Mod_Port_Name : granted_dest_port + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3122 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 560 + Statement : smart_ss_ovc_is_allocated_o, + Mod_Port_Name : smart_ss_ovc_is_allocated_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3144 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 48 + Statement : any_ovc_granted_in_outport_all, + Mod_Port_Name : any_ovc_granted_in_outport_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3099 + Goal : lint_rtl + Module : smart_forward_ivc_info + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 217 + Statement : ovc_locally_requested, + Mod_Port_Name : ovc_locally_requested + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3147 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 51 + Statement : crossbar_flit_out_wr_all, + Mod_Port_Name : crossbar_flit_out_wr_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3011 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 44 + Statement : ivc_num_getting_ovc_grant, + Mod_Port_Name : ivc_num_getting_ovc_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3112 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 454 + Statement : smart_ivc_num_getting_ovc_grant_o, + Mod_Port_Name : smart_ivc_num_getting_ovc_grant_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3051 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 76 + Statement : oports_weight_all, + Mod_Port_Name : oports_weight_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3056 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 437 + Statement : dest_port_decoded_all, + Mod_Port_Name : dest_port_decoded_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3130 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 568 + Statement : smart_ovc_single_flit_pck_o + Mod_Port_Name : smart_ovc_single_flit_pck_o + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3069 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 59 + Statement : oports_weight_all, + Mod_Port_Name : oports_weight_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3143 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 45 + Statement : granted_ovc_num_all, + Mod_Port_Name : granted_ovc_num_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3063 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 38 + Statement : any_ivc_sw_request_granted_all, + Mod_Port_Name : any_ivc_sw_request_granted_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3079 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 211 + Statement : refresh_w_counter, + Mod_Port_Name : refresh_w_counter + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3096 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 48 + Statement : iport_weight_is_consumed_all, + Mod_Port_Name : iport_weight_is_consumed_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3154 + Goal : lint_rtl + Module : full_ovc_predictor + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 545 + Statement : ivc_getting_sw_grant, + Mod_Port_Name : ivc_getting_sw_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3157 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 38 + Statement : granted_dest_port_all, + Mod_Port_Name : granted_dest_port_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3095 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 47 + Statement : vc_weight_is_consumed_all, + Mod_Port_Name : vc_weight_is_consumed_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3062 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 37 + Statement : ivc_num_getting_sw_grant,// for non spec ivc_num_getting_first_sw_grant, + Mod_Port_Name : ivc_num_getting_sw_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3007 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 38 + Statement : masked_ovc_request_all, + Mod_Port_Name : masked_ovc_request_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3021 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 435 + Statement : pck_is_single_flit_all, + Mod_Port_Name : pck_is_single_flit_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3086 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 37 + Statement : ivc_num_getting_ovc_grant, + Mod_Port_Name : ivc_num_getting_ovc_grant + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3115 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 544 + Statement : neighbors_r_addr_i, + Mod_Port_Name : neighbors_r_addr_i + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3101 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 438 + Statement : assigned_to_ss_ovc, + Mod_Port_Name : assigned_to_ss_ovc + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3158 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 559 + Statement : output recieve_more_than_0, + Mod_Port_Name : recieve_more_than_0 + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3081 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 217 + Statement : credit_init_val_out, + Mod_Port_Name : credit_init_val_out + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3050 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 69 + Statement : iport_weight_is_consumed_all, + Mod_Port_Name : iport_weight_is_consumed_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3103 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 443 + Statement : ss_ovc_avalable_in_ss_port, + Mod_Port_Name : ss_ovc_avalable_in_ss_port + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3013 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 49 + Statement : iport_weight_is_consumed_all, + Mod_Port_Name : iport_weight_is_consumed_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3084 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 35 + Statement : ovc_allocated_all, + Mod_Port_Name : ovc_allocated_all + ----------------------------------------------------------------------------- + Tag : PortName + Description : Port [Mod_Port_Name] does not follow naming convention + Violation : Lint:3027 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 443 + Statement : vc_weight_is_consumed_all, + Mod_Port_Name : vc_weight_is_consumed_all + + ----------------------------------------------------------------------------- + RegInput-ML (150 warnings/0 waived/157 compressed) + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2636 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 259 + Statement : input [ONE_HOT_WIDTH-1 : 0] one_hot_code, + Signal : one_hot_code + Module : one_hot_to_bin + MASTER : one_hot_to_bin + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2845 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 472 + Statement : assigned_to_ss_ovc, + Signal : assigned_to_ss_ovc + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2724 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 351 + Statement : input [PV-1 : 0] ovc_status; + Signal : ovc_status + Module : port_pre_sel_gen + MASTER : port_pre_sel_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2667 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./ovc_list.sv + LineNumber : 32 + Statement : input [Cw-1 : 0] class_in; + Signal : class_in + Module : ovc_list + MASTER : ovc_list + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2849 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 477 + Statement : ss_ovc_avalable_in_ss_port, + Signal : ss_ovc_avalable_in_ss_port + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2772 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 78 + Statement : input [P-1 : 0] iport_weight_is_consumed_all; + Signal : iport_weight_is_consumed_all + SignalRange : + Module : combined_vc_sw_alloc + MASTER : combined_vc_sw_alloc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2730 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 356 + Statement : input reset,clk; + Signal : clk + SignalRange : + Module : port_pre_sel_gen + MASTER : port_pre_sel_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2676 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 45 + Statement : input [Xw-1 : 0] current_x; + Signal : current_x + SignalRange : + Module : mesh_torus_look_ahead_routing + MASTER : mesh_torus_look_ahead_routing + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2694 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 963 + Statement : input [EAw-1 : 0] e_addr; + Signal : e_addr + Module : mesh_tori_endp_addr_decode + MASTER : mesh_tori_endp_addr_decode + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2672 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 276 + Statement : input [PRAw-1: 0] neighbors_r_addr; + Signal : neighbors_r_addr + Module : look_ahead_routing + MASTER : look_ahead_routing + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2763 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 625 + Statement : input [PV-1 : 0] ovc_is_assigned_all; + Signal : ovc_is_assigned_all + Module : vc_alloc_request_gen_determinstic + MASTER : vc_alloc_request_gen_determinstic + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2733 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 479 + Statement : input [V-1 : 0] ovc_is_assigned; + Signal : ovc_is_assigned + SignalRange : + Module : oport_ovc_sig_gen + MASTER : oport_ovc_sig_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2606 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 256 + Statement : input any_ivc_sw_request_granted; + Signal : any_ivc_sw_request_granted + SignalRange : + Module : input_queue_per_port + MASTER : input_queue_per_port + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2725 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 352 + Statement : input [PV-1 : 0] ovc_avalable_all; + Signal : ovc_avalable_all + SignalRange : + Module : port_pre_sel_gen + MASTER : port_pre_sel_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2567 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 157 + Statement : input [CRDTw-1 : 0 ] credit_init_val_in [P-1 : 0][V-1 : 0]; + Signal : credit_init_val_in[2][0] + SignalRange : 0, 0-1, 1-2, 2-3, 3-4, 4 + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2741 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 555 + Statement : input [V-1 : 0] assigned_ovc_num,granted_ovc_num,ssa_granted_ovc_num; + Signal : granted_ovc_num + Module : full_ovc_predictor + MASTER : full_ovc_predictor + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2784 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 177 + Statement : input [IN_WIDTH-1 : 0] or_in; + Signal : or_in + Module : custom_or + MASTER : custom_or + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2700 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 76 + Statement : input [PVP_1-1 : 0] dest_port_all; + Signal : dest_port_all + SignalRange : + Module : output_ports + MASTER : output_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2551 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 47 + Statement : input router_config_t router_config_in; + Signal : router_config_in + SignalRange : + Module : router_top + MASTER : router_top + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2595 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 106 + Statement : input [PPSw-1 : 0] port_pre_sel; + Signal : port_pre_sel + SignalRange : + Module : input_ports + MASTER : input_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2843 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 469 + Statement : flit_wr_i, + Signal : flit_wr_i + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2576 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 116 + Statement : input [PVV-1 : 0] spec_ovc_num_all; + Signal : spec_ovc_num_all + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2651 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 1119 + Statement : input odd_column; + Signal : odd_column + SignalRange : + Module : destp_generator + MASTER : destp_generator + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2764 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 626 + Statement : input [PVP_1-1 : 0] dest_port_in_all; + Signal : dest_port_in_all + Module : vc_alloc_request_gen_determinstic + MASTER : vc_alloc_request_gen_determinstic + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2771 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 77 + Statement : input [PV-1 : 0] vc_weight_is_consumed_all; + Signal : vc_weight_is_consumed_all + SignalRange : + Module : combined_vc_sw_alloc + MASTER : combined_vc_sw_alloc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2812 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 226 + Statement : input oport_info_t oport_info [P-1 : 0]; + Signal : oport_info + SignalRange : + Module : smart_forward_ivc_info + MASTER : smart_forward_ivc_info + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2584 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 129 + Statement : input [P-1 : 0] granted_dst_is_from_a_single_flit_pck; + Signal : granted_dst_is_from_a_single_flit_pck + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2585 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 144 + Statement : input refresh_w_counter; + Signal : refresh_w_counter + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2561 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 125 + Statement : input [CONG_ALw-1 : 0] congestion_in_all; + Signal : congestion_in_all + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2824 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 576 + Statement : input smart_chanel_t smart_chanel_i; + Signal : smart_chanel_i + Module : smart_allocator_per_iport + MASTER : smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2555 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 67 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in + SignalRange : + Module : router_two_stage + MASTER : router_two_stage + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2549 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 44 + Statement : input smartflit_chanel_t chan_in_all [NE-1 : 0]; + Signal : chan_in_all[93:0][3:0] + Module : noc_top + MASTER : noc_top + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2752 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 461 + Statement : input [PVP_1-1 : 0] dest_port_decoded_all; + Signal : dest_port_decoded_all + Module : vc_alloc_request_gen + MASTER : vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2621 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 59 + Statement : input [W-1 : 0] reset_to + Signal : reset_to + Module : pronoc_register_reset_init + MASTER : pronoc_register_reset_init + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2827 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 582 + Statement : input ovc_info_t ss_ovc_info [V-1 : 0]; + Signal : ss_ovc_info + Module : smart_allocator_per_iport + MASTER : smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2837 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 462 + Statement : input goes_straight, + Signal : goes_straight + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2593 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 103 + Statement : input [PV-1 : 0] assigned_ovc_not_full_all; + Signal : assigned_ovc_not_full_all + Module : input_ports + MASTER : input_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2729 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 356 + Statement : input reset,clk; + Signal : reset + SignalRange : + Module : port_pre_sel_gen + MASTER : port_pre_sel_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2737 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 151 + Statement : input [IN_WIDTH-1 : 0] demux_in,//repeated + Signal : demux_in + Module : one_hot_demux + MASTER : one_hot_demux + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2559 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 108 + Statement : input [P-1 : 0] flit_in_wr_all; + Signal : flit_in_wr_all + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2809 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 668 + Statement : input en; + Signal : en + Module : credit_release_gen + MASTER : credit_release_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2578 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 118 + Statement : input [PV-1 : 0] spec_first_arbiter_granted_ivc_all; + Signal : spec_first_arbiter_granted_ivc_all + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2848 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 475 + Statement : ivc_request, + Signal : ivc_request + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2580 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 120 + Statement : input [PP_1-1 : 0] spec_granted_dest_port_all; + Signal : spec_granted_dest_port_all + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2829 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 583 + Statement : input ss_port_link_reg_flit_wr; + Signal : ss_port_link_reg_flit_wr + SignalRange : + Module : smart_allocator_per_iport + MASTER : smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2629 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 79 + Statement : input [V-1 :0] ssa_rd; + Signal : ssa_rd + Module : flit_buffer + MASTER : flit_buffer + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2661 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 468 + Statement : input [P-1 : 0] destport_in; + Signal : destport_in + SignalRange : + Module : remove_sw_loc_one_hot + MASTER : remove_sw_loc_one_hot + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2652 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1134 + Statement : input [DSTPw-1 : 0] dest_port_coded; + Signal : dest_port_coded + SignalRange : + Module : mesh_torus_destp_generator + MASTER : mesh_torus_destp_generator + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2579 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 119 + Statement : input [PP_1-1 : 0] nonspec_granted_dest_port_all; + Signal : nonspec_granted_dest_port_all + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2598 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 124 + Statement : input [DSTPw-1 : 0] destport_clear [P-1 : 0][V-1 : 0]; + Signal : destport_clear + SignalRange : + Module : input_ports + MASTER : input_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2770 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 64 + Statement : input [PVV-1 : 0] masked_ovc_request_all; + Signal : masked_ovc_request_all + SignalRange : + Module : combined_vc_sw_alloc + MASTER : combined_vc_sw_alloc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2788 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 629 + Statement : input [ARBITER_WIDTH-1 : 0] request; + Signal : request + SignalRange : + Module : swa_input_port_arbiter + MASTER : swa_input_port_arbiter + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2575 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 115 + Statement : input [PV-1 : 0] ivc_num_getting_ovc_grant; + Signal : ivc_num_getting_ovc_grant + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2608 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 258 + Statement : input flit_in_wr; + Signal : flit_in_wr + SignalRange : + Module : input_queue_per_port + MASTER : input_queue_per_port + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2736 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 150 + Statement : input [SEL_WIDTH-1 : 0] demux_sel,//selectore + Signal : demux_sel + Module : one_hot_demux + MASTER : one_hot_demux + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2678 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 48 + Statement : input [Yw-1 : 0] dest_y; + Signal : dest_y + SignalRange : + Module : mesh_torus_look_ahead_routing + MASTER : mesh_torus_look_ahead_routing + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2825 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + Signal : flit_chanel_i + Module : smart_allocator_per_iport + MASTER : smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2747 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 559 + Statement : input [VP_1-1 : 0] nearly_full; + Signal : nearly_full + Module : full_ovc_predictor + MASTER : full_ovc_predictor + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2739 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 420 + Statement : input credit_decreased; + Signal : credit_decreased + Module : credit_monitor_per_ovc + MASTER : credit_monitor_per_ovc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2744 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 556 + Statement : input [P_1-1 : 0] dest_port; + Signal : dest_port + Module : full_ovc_predictor + MASTER : full_ovc_predictor + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2609 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 264 + Statement : input [V-1 : 0] assigned_ovc_not_full; + Signal : assigned_ovc_not_full + SignalRange : + Module : input_queue_per_port + MASTER : input_queue_per_port + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2642 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 219 + Statement : input [VDSTPw-1 : 0] lk_dest_all_in; + Signal : lk_dest_all_in + Module : header_flit_update_lk_route_ovc + MASTER : header_flit_update_lk_route_ovc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2645 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 224 + Statement : input [DSTPw-1 : 0] lk_dest_not_registered; + Signal : lk_dest_not_registered + Module : header_flit_update_lk_route_ovc + MASTER : header_flit_update_lk_route_ovc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2639 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 442 + Statement : input [ADDR_WIDTH-1 : 0] rd_addr; + Signal : rd_addr + Module : fifo_ram + MASTER : fifo_ram + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2801 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./../arbiter.v + LineNumber : 214 + Statement : input [1 : 0] low_pr + Signal : low_pr + Module : arbiter_3_one_hot + MASTER : arbiter_3_one_hot + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2616 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 274 + Statement : input [P_1-1 : 0] granted_dest_port; + Signal : granted_dest_port + SignalRange : + Module : input_queue_per_port + MASTER : input_queue_per_port + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2749 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 418 + Statement : input [CRDTw-1 : 0] credit_init_val_i; + Signal : credit_init_val_i + Module : credit_monitor_per_ovc + MASTER : credit_monitor_per_ovc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2582 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 122 + Statement : input [P-1 : 0] any_ivc_sw_request_granted_all; + Signal : any_ivc_sw_request_granted_all + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2699 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 75 + Statement : input [PV-1 : 0] flit_is_tail_all; + Signal : flit_is_tail_all + Module : output_ports + MASTER : output_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2626 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 72 + Statement : input [V-1 :0] vc_num_rd;//read virtual chanel + Signal : vc_num_rd + Module : flit_buffer + MASTER : flit_buffer + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2643 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 221 + Statement : input [VV-1 : 0] assigned_ovc_num; + Signal : assigned_ovc_num + SignalRange : + Module : header_flit_update_lk_route_ovc + MASTER : header_flit_update_lk_route_ovc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2738 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 419 + Statement : input credit_increased; + Signal : credit_increased + SignalRange : + Module : credit_monitor_per_ovc + MASTER : credit_monitor_per_ovc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2625 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 71 + Statement : input [V-1 :0] vc_num_wr;//write virtual chanel + Signal : vc_num_wr + Module : flit_buffer + MASTER : flit_buffer + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2841 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 467 + Statement : flit_hdr_flag_i , + Signal : flit_hdr_flag_i + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2556 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 76 + Statement : input smart_ctrl_t smart_ctrl_in [P-1 : 0]; + Signal : smart_ctrl_in + SignalRange : + Module : router_two_stage + MASTER : router_two_stage + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2853 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 724 + Statement : input [V-1 : 0] credit_in, smart_credit_in; + Signal : smart_credit_in + SignalRange : + Module : smart_credit_manage + MASTER : smart_credit_manage + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2583 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 123 + Statement : input [P-1 : 0] any_ovc_granted_in_outport_all; + Signal : any_ovc_granted_in_outport_all + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2630 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 80 + Statement : input [V-1 :0] multiple_dest; + Signal : multiple_dest + Module : flit_buffer + MASTER : flit_buffer + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2731 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 477 + Statement : input [V-1 : 0] flit_is_tail; + Signal : flit_is_tail + Module : oport_ovc_sig_gen + MASTER : oport_ovc_sig_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2573 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 111 + Statement : input [PV-1 : 0] vsa_ovc_allocated_all; + Signal : vsa_ovc_allocated_all + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2638 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 441 + Statement : input [ADDR_WIDTH-1 : 0] wr_addr; + Signal : wr_addr + Module : fifo_ram + MASTER : fifo_ram + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2830 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 584 + Statement : input smart_chanel_t ss_smart_chanel_new; + Signal : ss_smart_chanel_new + Module : smart_allocator_per_iport + MASTER : smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2838 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 463 + Statement : smart_requests_i, + Signal : smart_requests_i + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2631 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 81 + Statement : input [V-1 :0] sub_rd_ptr_ld; + Signal : sub_rd_ptr_ld + Module : flit_buffer + MASTER : flit_buffer + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2671 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 277 + Statement : input [RAw-1 : 0] current_r_addr; + Signal : current_r_addr + SignalRange : + Module : look_ahead_routing + MASTER : look_ahead_routing + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2560 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 110 + Statement : input [PV-1 : 0] credit_in_all; + Signal : credit_in_all + SignalRange : + Module : inout_ports + MASTER : inout_ports + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2852 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 724 + Statement : input [V-1 : 0] credit_in, smart_credit_in; + Signal : credit_in + SignalRange : + Module : smart_credit_manage + MASTER : smart_credit_manage + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2662 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 579 + Statement : input sw_loc_val; + Signal : sw_loc_val + Module : add_sw_loc_one_hot_val + MASTER : add_sw_loc_one_hot_val + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2550 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 43 + Statement : input smartflit_chanel_t chan_in_all [NE-1 : 0]; + Signal : chan_in_all + Module : mesh_torus_noc_top + MASTER : mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2828 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 580 + Statement : input [V-1 : 0] ovc_locally_requested; + Signal : ovc_locally_requested + SignalRange : + Module : smart_allocator_per_iport + MASTER : smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2789 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 634 + Statement : input [ARBITER_WIDTH-1 : 0] vc_weight_is_consumed; + Signal : vc_weight_is_consumed + Module : swa_input_port_arbiter + MASTER : swa_input_port_arbiter + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2735 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 481 + Statement : input [V-1 : 0] first_arbiter_granted_ivc; + Signal : first_arbiter_granted_ivc + Module : oport_ovc_sig_gen + MASTER : oport_ovc_sig_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2814 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 241 + Statement : input [BIN_WIDTH-1 : 0] bin_code, + Signal : bin_code + Module : bin_to_one_hot + MASTER : bin_to_one_hot + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2740 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 555 + Statement : input [V-1 : 0] assigned_ovc_num,granted_ovc_num,ssa_granted_ovc_num; + Signal : ssa_granted_ovc_num + Module : full_ovc_predictor + MASTER : full_ovc_predictor + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2727 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 353 + Statement : input [PV-1 : 0] credit_decreased_all; + Signal : credit_decreased_all + Module : port_pre_sel_gen + MASTER : port_pre_sel_gen + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2775 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 76 + Statement : input [PV-1 : 0] pck_is_single_flit_all; + Signal : pck_is_single_flit_all + SignalRange : + Module : comb_nonspec_allocator + MASTER : comb_nonspec_allocator + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2823 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 574 + Statement : input [RAw-1: 0] neighbors_r_addr_i [P-1 : 0]; + Signal : neighbors_r_addr_i + Module : smart_allocator_per_iport + MASTER : smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2818 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 330 + Statement : input smart_chanel_t smart_chanel_new [P-1 : 0]; + Signal : smart_chanel_new + Module : smart_bypass_chanels + MASTER : smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2677 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 46 + Statement : input [Yw-1 : 0] current_y; + Signal : current_y + SignalRange : + Module : mesh_torus_look_ahead_routing + MASTER : mesh_torus_look_ahead_routing + ----------------------------------------------------------------------------- + Tag : RegInput-ML + Description : Input port '[Signal]' is not registered [module:[MASTER]] + Violation : Lint:2842 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 468 + Statement : flit_tail_flag_i, + Signal : flit_tail_flag_i + Module : smart_validity_check_per_ivc + MASTER : smart_validity_check_per_ivc + + ----------------------------------------------------------------------------- + RegOutputs (160 warnings/0 waived/300 compressed) + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:420 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][0].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:184 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].flit_chanel.flit.hdr_flag + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:412 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][2].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:435 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][2].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:294 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].smart_chanel.dest_e_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:423 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][1].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:375 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][1].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:415 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][2].bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:12 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].ctrl_chanel.router_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:430 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][1].bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:439 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][2].bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:297 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].smart_chanel.requests + SignalRange : 2-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:417 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][0].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:454 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][1].bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:20 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].smart_chanel.hdr_flit + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:393 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][0].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:17 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].smart_chanel.bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:27 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].flit_chanel.flit.payload + SignalRange : 63-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:293 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].smart_chanel.hdr_flit + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:452 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][1].pck_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:290 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].smart_chanel.bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:437 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][2].pck_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:418 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][0].active_high_reset + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:462 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][2].flit_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:434 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][2].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:456 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][2].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:368 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].flit_chanel.flit_wr + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:436 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][2].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:23 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].smart_chanel.ovc[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:108 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].smart_chanel.bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:373 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][0].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:107 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].ctrl_chanel.endp_port + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:385 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][2].active_high_reset + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:388 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][2].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:103 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].ctrl_chanel.router_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:115 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].smart_chanel.requests + SignalRange : 2-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:401 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][1].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:386 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][2].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:6 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].ctrl_chanel.credit_release_en[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:112 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].smart_chanel.dest_e_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:296 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].smart_chanel.ovc[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:400 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][1].active_high_reset + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:289 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].ctrl_chanel.endp_port + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:276 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[2].flit_chanel.credit[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:279 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].ctrl_chanel.credit_release_en[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:366 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].flit_chanel.flit.hdr_flag + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:406 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][1].bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:14 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].ctrl_chanel.endp_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:198 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[2].ctrl_chanel.endp_port + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:432 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][2].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:21 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].smart_chanel.dest_e_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:367 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].flit_chanel.credit[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:410 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][2].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:7 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].ctrl_chanel.credit_init_val[0] + SignalRange : 4-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:444 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][0].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:387 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][2].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:92 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].flit_chanel.flit.tail_flag + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:110 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].smart_chanel.flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:371 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][0].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:384 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][2].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:93 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].flit_chanel.flit.hdr_flag + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:448 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][1].active_high_reset + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:378 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][1].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:409 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][2].active_high_reset + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:379 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][1].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:389 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][2].pck_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:372 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][0].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:428 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][1].pck_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:300 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].flit_chanel.flit.payload + SignalRange : 63-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:403 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][1].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:426 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][1].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:453 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][1].flit_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:199 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[2].smart_chanel.bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:381 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][1].flit_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:364 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].flit_chanel.flit.vc[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:183 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].flit_chanel.flit.tail_flag + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:421 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][0].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:451 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][1].flit_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:111 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].smart_chanel.hdr_flit + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:429 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][1].flit_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:446 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][0].pck_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:463 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][2].bypassed_num + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:203 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[2].smart_chanel.dest_e_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:377 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][1].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:292 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].smart_chanel.flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:380 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][1].pck_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:442 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][0].active_high_reset + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:16 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].ctrl_chanel.endp_port + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:274 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[2].flit_chanel.flit.tail_flag + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:118 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[1].flit_chanel.flit.payload + SignalRange : 63-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:285 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[3].ctrl_chanel.router_addr + SignalRange : 1-0 + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:402 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][1].pck_wr_o + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:395 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[1][0].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:390 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][2].flit_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:422 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][0].pck_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:441 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[3][0].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:369 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[0][0].empty + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:438 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : router_event[2][2].flit_wr_i + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:5 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[0].ctrl_chanel.hetero_ovc_presence[0] + ----------------------------------------------------------------------------- + Tag : RegOutputs + Description : Port '[Signal]' is not driven by a register + Violation : Lint:187 + Goal : lint_rtl + FileName : ./../../rtl/src_noc/./noc_top.sv + LineNumber : 53 + Statement : ) noc_top ( + Module : noc_top + Signal : chan_out_all[2].ctrl_chanel.hetero_ovc_presence[0] + + ----------------------------------------------------------------------------- + SigName (5 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : SigName + Description : Signal [Signal] does not follow naming convention + Violation : Lint:3163 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 117 + Statement : wire [PV-1 : 0] spec_first_arbiter_granted_ivc_all; + Signal : spec_first_arbiter_granted_ivc_all + ----------------------------------------------------------------------------- + Tag : SigName + Description : Signal [Signal] does not follow naming convention + Violation : Lint:3162 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 116 + Statement : wire [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; + Signal : nonspec_first_arbiter_granted_ivc_all + ----------------------------------------------------------------------------- + Tag : SigName + Description : Signal [Signal] does not follow naming convention + Violation : Lint:3164 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 123 + Statement : wire [P-1 : 0] granted_dst_is_from_a_single_flit_pck; + Signal : granted_dst_is_from_a_single_flit_pck + ----------------------------------------------------------------------------- + Tag : SigName + Description : Signal [Signal] does not follow naming convention + Violation : Lint:3161 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 483 + Statement : wire [PV-1 : 0] non_vsa_ivc_num_getting_ovc_grant_all; + Signal : non_vsa_ivc_num_getting_ovc_grant_all + ----------------------------------------------------------------------------- + Tag : SigName + Description : Signal [Signal] does not follow naming convention + Violation : Lint:3160 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 129 + Statement : wire [V-1 : 0] first_arbiter_granted_ivc_per_port[P-1 : 0] ; + Signal : first_arbiter_granted_ivc_per_port + + ----------------------------------------------------------------------------- + STARC05-1.1.1.2 (4 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : STARC05-1.1.1.2 + Description : '[NodeName]' does not follow naming convention + Violation : Lint:3508 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1330 + Statement : end else begin :_me + NodeName : _me + ----------------------------------------------------------------------------- + Tag : STARC05-1.1.1.2 + Description : '[NodeName]' does not follow naming convention + Violation : Lint:3505 + Goal : lint_rtl + Module : smart_forward_ivc_info + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 276 + Statement : ) _or ( + NodeName : _or + ----------------------------------------------------------------------------- + Tag : STARC05-1.1.1.2 + Description : '[NodeName]' does not follow naming convention + Violation : Lint:3507 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1318 + Statement : if(NL==1) begin :_se + NodeName : _se + ----------------------------------------------------------------------------- + Tag : STARC05-1.1.1.2 + Description : '[NodeName]' does not follow naming convention + Violation : Lint:3506 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 215 + Statement : for(i=0;i< PV;i=i+1) begin :_PV + NodeName : _PV + + ----------------------------------------------------------------------------- + UndrivenNUnloaded-ML (369 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2323 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].congestion[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2414 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[13] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2373 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[48] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2282 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart_chanel_in[0].dest_e_addr[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2434 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[33] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2541 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[62] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2378 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[53] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2391 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.hdr_flag + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2262 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart_chanel_in[0].dest_e_addr[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2379 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[54] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2473 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 51 + Statement : smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/router_chan_out[3][1].ctrl_chanel.endp_addr[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2236 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[48] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2207 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[19] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2268 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 339 + Statement : smart_chanel_t smart_chanel_shifted [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/smart_chanel_shifted[0].bypassed_num[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2488 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[9] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2303 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/smart_chanel_in[0].ovc[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2267 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart_chanel_in[0].requests[2] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2496 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[17] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2192 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[4] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2456 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[55] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2405 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[4] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2521 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[42] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2483 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[4] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2438 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[37] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2514 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[35] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2461 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[60] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2224 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[36] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2493 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[14] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2223 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[35] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2294 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/smart_chanel_in[0].requests[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2285 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart_chanel_in[0].requests[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2404 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[3] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2503 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[24] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2384 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[59] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2513 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[34] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2447 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[46] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2278 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart_chanel_in[0].bypassed_num[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2355 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[30] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2516 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[37] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2542 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[63] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2500 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[21] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2381 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[56] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2387 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[62] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2313 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 156 + Statement : wire [RAw-1: 0] neighbors_r_addr [P-1: 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/smart.neighbors_r_addr[0][0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2383 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[58] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2288 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/smart_chanel_in[0].bypassed_num[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2302 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/smart_chanel_in[0].dest_e_addr[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2455 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[54] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2536 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[57] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2220 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[32] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2546 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].credit[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2470 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 157 + Statement : wire [V-1 : 0] credit_out [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/smart.credit_out[0][0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2199 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[11] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2317 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 623 + Statement : ) routing ( + NodeType : terminal + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[2].smart_en.smart_allocator/routing/src_e_addr[1:0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2476 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].congestion[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2429 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[28] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2257 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 157 + Statement : wire [V-1 : 0] credit_out [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.credit_out[0][0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2374 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[49] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2320 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 53 + Statement : router_config_t router_config_in [NR-1 :0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/router_config_in[1].endp_ids[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2409 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[8] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2358 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[33] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2453 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[52] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2343 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[18] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2471 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 53 + Statement : router_config_t router_config_in [NR-1 :0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/router_config_in[3].endp_ids[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2368 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[43] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2509 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[30] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2394 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 157 + Statement : wire [V-1 : 0] credit_out [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.credit_out[0][0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2265 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart_chanel_in[0].requests[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2319 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 53 + Statement : router_config_t router_config_in [NR-1 :0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/router_config_in[1].endp_ids[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2349 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[24] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2221 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[33] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2253 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.tail_flag + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2213 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[25] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2217 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[29] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2459 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[58] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2444 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[43] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2279 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart_chanel_in[0].flit_in_bypassed + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2230 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[42] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2376 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[51] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2463 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[62] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2510 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[31] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2415 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[14] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2431 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[30] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2422 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[0].flit.payload[21] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2195 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[7] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2494 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[15] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2523 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[44] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2352 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[27] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2258 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart_chanel_in[0].bypassed_num[0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2474 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 51 + Statement : smartflit_chanel_t router_chan_out [NR-1 :0][MAX_P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/router_chan_out[3][1].ctrl_chanel.endp_addr[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2259 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 65 + Statement : smart_chanel_t smart_chanel_in [P-1 : 0]; + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart_chanel_in[0].bypassed_num[1] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2212 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[24] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2342 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[17] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2356 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[31] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2328 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[3] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2539 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[60] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2210 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[0].flit.payload[22] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2316 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 655 + Statement : ) lkrouting ( + NodeType : terminal + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/lkrouting/src_e_addr[1:0] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2346 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[0].flit.payload[21] + ----------------------------------------------------------------------------- + Tag : UndrivenNUnloaded-ML + Description : Detected undriven and unloaded(unconnected) [NodeType] [DesignObjSignal] + Violation : Lint:2529 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + NodeType : net + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[0].flit.payload[50] + + ----------------------------------------------------------------------------- + UnloadedInPort-ML (907 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1428 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/ctrl_in[0].endp_addr[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1162 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.vc[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:893 + Goal : lint_rtl + Module : smart_forward_ivc_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.forward_ivc/ivc_info[1][0].dest_port_encoded[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 224 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:620 + Goal : lint_rtl + Module : look_ahead_routing + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/unicast.lk_routing/src_e_addr[1] + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 279 + Statement : input [EAw-1 : 0] src_e_addr; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:659 + Goal : lint_rtl + Module : look_ahead_routing + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/unicast.lk_routing/src_e_addr[0] + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 279 + Statement : input [EAw-1 : 0] src_e_addr; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1110 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[12] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1087 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[2].smart_en.smart_allocator/ss_smart_chanel_new.dest_e_addr[1] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 584 + Statement : input smart_chanel_t ss_smart_chanel_new; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1247 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/ctrl_in[0].credit_init_val[0][4] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1262 + Goal : lint_rtl + Module : inout_ports + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/spec_first_arbiter_granted_ivc_all[1] + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 118 + Statement : input [PV-1 : 0] spec_first_arbiter_granted_ivc_all; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:555 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[9] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1306 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/ctrl_in[0].credit_init_val[0][4] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1142 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[44] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1368 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/ctrl_in[0].endp_addr[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:935 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/ivc_info[2][0].ivc_req + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:991 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/flit_chanel_i.flit.payload[8] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:966 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/smart_chanel_new[0].hdr_flit + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 330 + Statement : input smart_chanel_t smart_chanel_new [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:591 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[45] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1421 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/ctrl_in[0].credit_init_val[0][0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:579 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[33] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1353 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/granted_dest_port[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 274 + Statement : input [P_1-1 : 0] granted_dest_port; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1059 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/ss_ovc_info[0].credit[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 582 + Statement : input ovc_info_t ss_ovc_info [V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1302 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/ctrl_in[0].credit_init_val[0][0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:793 + Goal : lint_rtl + Module : vc_alloc_request_gen + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/ivc_info[1][0].destport_one_hot[2] + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 474 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:742 + Goal : lint_rtl + Module : output_ports + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/output_ports/smart_ctrl_in[1].ivc_num_getting_ovc_grant[0] + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 97 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:664 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/smart_ctrl_in.mask_available_ovc[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1122 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[24] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1342 + Goal : lint_rtl + Module : router_top + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_in[0].smart_chanel.flit_in_bypassed + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1300 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/ctrl_in[0].hetero_ovc_presence[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1068 + Goal : lint_rtl + Module : conventional_routing + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/routing/reset + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 61 + Statement : input reset,clk; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:947 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/iport_info[0].granted_oport_one_hot[2] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 333 + Statement : input iport_info_t iport_info [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1323 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/smart_ctrl_in.lk_destport[1] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1133 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[35] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:975 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/smart_chanel_i.bypassed_num[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 576 + Statement : input smart_chanel_t smart_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1250 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/ctrl_in[0].endp_addr[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:529 + Goal : lint_rtl + Module : router_top + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_in[0].smart_chanel.requests[0] + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1170 + Goal : lint_rtl + Module : router_top + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/chan_in[0].smart_chanel.requests[1] + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1297 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/vsa_ctrl_in.buff_space_decreased[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 281 + Statement : input vsa_ctrl_t vsa_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:668 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/smart_ctrl_in.credit_out[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1260 + Goal : lint_rtl + Module : router_top + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/chan_in[0].smart_chanel.requests[2] + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:736 + Goal : lint_rtl + Module : output_ports + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/output_ports/vsa_ctrl_in[2].ivc_reset[0] + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 95 + Statement : input vsa_ctrl_t vsa_ctrl_in [P-1: 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1120 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[22] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:737 + Goal : lint_rtl + Module : output_ports + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/output_ports/vsa_ctrl_in[2].ivc_num_getting_ovc_grant[0] + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 95 + Statement : input vsa_ctrl_t vsa_ctrl_in [P-1: 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1393 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/ctrl_in[0].credit_init_val[0][2] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:766 + Goal : lint_rtl + Module : port_pre_sel_gen + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/output_ports/port_pre_sel_top/congestion_in_all[1] + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 355 + Statement : input [CONG_ALw-1 : 0] congestion_in_all; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1404 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/smart_ctrl_in.mask_available_ovc[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1064 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/ss_smart_chanel_new.dest_e_addr[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 584 + Statement : input smart_chanel_t ss_smart_chanel_new; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1223 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/granted_dest_port[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 274 + Statement : input [P_1-1 : 0] granted_dest_port; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1047 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/flit_chanel_i.flit.vc[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:950 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/iport_info[1].any_ivc_get_swa_grant + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 333 + Statement : input iport_info_t iport_info [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1285 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/smart_ctrl_in.mask_available_ovc[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1400 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/ctrl_in[0].endp_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:566 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[20] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:561 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[15] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:752 + Goal : lint_rtl + Module : output_ports + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/output_ports/smart_ctrl_in[2].mask_available_ovc[0] + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 97 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:846 + Goal : lint_rtl + Module : vc_alloc_request_gen + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/ctrl_in[0].endp_addr[0] + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 475 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:655 + Goal : lint_rtl + Module : flit_buffer + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/the_flit_buffer/sub_rd_ptr_ld[0] + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 81 + Statement : input [V-1 :0] sub_rd_ptr_ld; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1236 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/smart_ctrl_in.hdr_flit_req + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1279 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/ctrl_in[0].endp_addr[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:592 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[46] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1149 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[51] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1066 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/ss_smart_chanel_new.requests[1] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 584 + Statement : input smart_chanel_t ss_smart_chanel_new; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:856 + Goal : lint_rtl + Module : comb_nonspec_allocator + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/nonspec.cmb_v1.nonspec_comb/ivc_info[0][0].flit_is_tail + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 73 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:957 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/iport_info[2].granted_oport_one_hot[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 333 + Statement : input iport_info_t iport_info [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1201 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/smart_ctrl_in.destport[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1044 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/flit_chanel_i.flit.payload[61] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1367 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/ctrl_in[0].router_addr[1] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1255 + Goal : lint_rtl + Module : router_top + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/chan_in[0].smart_chanel.dest_e_addr[0] + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:662 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/granted_dest_port[1] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 274 + Statement : input [P_1-1 : 0] granted_dest_port; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:530 + Goal : lint_rtl + Module : router_top + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_in[0].smart_chanel.requests[1] + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1134 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[36] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:699 + Goal : lint_rtl + Module : output_ports + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/output_ports/ivc_info[0][0].assigned_ovc_not_full + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 94 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:901 + Goal : lint_rtl + Module : smart_forward_ivc_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.forward_ivc/iport_info[0].any_ivc_get_swa_grant + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 225 + Statement : input iport_info_t iport_info [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:725 + Goal : lint_rtl + Module : output_ports + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/output_ports/ivc_info[2][0].dest_e_addr[0] + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 94 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:672 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/smart_ctrl_in.lk_destport[1] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:960 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/iport_info[2].swa_grant[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 333 + Statement : input iport_info_t iport_info [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1369 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/ctrl_in[0].endp_addr[1] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1132 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[34] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:959 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/iport_info[2].granted_oport_one_hot[2] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 333 + Statement : input iport_info_t iport_info [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1286 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/smart_ctrl_in.ovc_is_released[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1209 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/vsa_ctrl_in.ovc_is_released[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 281 + Statement : input vsa_ctrl_t vsa_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:569 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[23] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:835 + Goal : lint_rtl + Module : vc_alloc_request_gen + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/smart_ctrl_in[2].hdr_flit_req + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 473 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1141 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[43] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:914 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/ivc_info[0][0].dest_port_encoded[1] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1392 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/ctrl_in[0].credit_init_val[0][1] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1080 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[2].smart_en.smart_allocator/ss_ovc_info[0].nearly_full + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 582 + Statement : input ovc_info_t ss_ovc_info [V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1257 + Goal : lint_rtl + Module : router_top + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/chan_in[0].smart_chanel.ovc[0] + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:918 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/ivc_info[0][0].assigned_ovc_num[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:890 + Goal : lint_rtl + Module : smart_forward_ivc_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.forward_ivc/ivc_info[0][0].assigned_ovc_num[0] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 224 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:972 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/smart_chanel_new[0].requests[2] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 330 + Statement : input smart_chanel_t smart_chanel_new [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1127 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[29] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1117 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.Port_[2].smart_en.smart_allocator/flit_chanel_i.flit.payload[19] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:541 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/ctrl_in[0].hetero_ovc_presence[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1013 + Goal : lint_rtl + Module : smart_allocator_per_iport + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/flit_chanel_i.flit.payload[30] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1243 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/ctrl_in[0].credit_init_val[0][0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:1375 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/smart_ctrl_in.ovc_is_released[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:577 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[31] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:665 + Goal : lint_rtl + Module : input_queue_per_port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/smart_ctrl_in.ovc_is_released[0] + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:939 + Goal : lint_rtl + Module : smart_bypass_chanels + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/ivc_info[2][0].destport_one_hot[1] + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + ----------------------------------------------------------------------------- + Tag : UnloadedInPort-ML + Description : Detected unloaded(unconnected)input port [DesignObjSignal] + Violation : Lint:554 + Goal : lint_rtl + Module : extract_header_flit_info + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/flit_in[8] + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 137 + Statement : input [Fw-1 : 0] flit_in; + + ----------------------------------------------------------------------------- + UnloadedNet-ML (48 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:516 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[2].congestion[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:505 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[1].congestion[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:476 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[2].congestion[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:479 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[2].credit[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:500 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 93 + Statement : assign ovc_is_assigned_all[i] = ivc_info[C_PORT][i%V].ovc_is_assigned; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/ovc_is_assigned_all[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:518 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[2].congestion[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:499 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 93 + Statement : assign ovc_is_assigned_all[i] = ivc_info[C_PORT][i%V].ovc_is_assigned; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/ovc_is_assigned_all[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:497 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 91 + Statement : assign ivc_request_all[i] = ivc_info[C_PORT][i%V].ivc_req; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/ivc_request_all[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:520 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[1].congestion[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:494 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 92 + Statement : assign assigned_ovc_not_full_all[i] = ivc_info[C_PORT][i%V].assigned_ovc_not_full; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/assigned_ovc_not_full_all[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:504 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[1].congestion[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:510 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[2].congestion[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:493 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 92 + Statement : assign assigned_ovc_not_full_all[i] = ivc_info[C_PORT][i%V].assigned_ovc_not_full; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/assigned_ovc_not_full_all[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:517 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[2].congestion[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:506 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[1].congestion[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:485 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 499 + Statement : assign dest_port_encoded_all [(i*V+j+1)*DSTPw-1 : (i*V+j)*DSTPw]=ivc_info[i][j].dest_port_encoded; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/dest_port_encoded_all[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:487 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 499 + Statement : assign dest_port_encoded_all [(i*V+j+1)*DSTPw-1 : (i*V+j)*DSTPw]=ivc_info[i][j].dest_port_encoded; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/dest_port_encoded_all[3] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:486 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 499 + Statement : assign dest_port_encoded_all [(i*V+j+1)*DSTPw-1 : (i*V+j)*DSTPw]=ivc_info[i][j].dest_port_encoded; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/dest_port_encoded_all[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:477 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[2].congestion[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:478 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/ss_flit_chanel[2].congestion[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:498 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 91 + Statement : assign ivc_request_all[i] = ivc_info[C_PORT][i%V].ivc_req; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/ivc_request_all[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:514 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[1].congestion[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:489 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 499 + Statement : assign dest_port_encoded_all [(i*V+j+1)*DSTPw-1 : (i*V+j)*DSTPw]=ivc_info[i][j].dest_port_encoded; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/dest_port_encoded_all[5] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:481 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 631 + Statement : assign depth_2 = depth - 2; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/V_[0].smart_.dest_e_addr_fifo/mwb2.depth_2[3] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:522 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[1].congestion[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:490 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 495 + Statement : assign non_vsa_ivc_num_getting_ovc_grant_all [(i+1)*V-1 : i*V] = ssa_ctrl_in[i].ivc_num_getting_ovc_grant | smart_ctrl_in[i].ivc_num_getting_ovc_grant; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/non_vsa_ivc_num_getting_ovc_grant_all[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:519 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[2].credit[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:503 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 349 + Statement : assign ivc_forwardable[i] = (IS_SINGLE_FLIT)? {V{1'b1}} :~iport_info[i].ivc_req; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/ivc_forwardable[0][0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:509 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[2].congestion[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:507 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[1].credit[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:502 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 355 + Statement : assign outport_is_granted[i] = oport_info[i].any_ovc_granted; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/outport_is_granted[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:512 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[1].congestion[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:523 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[1].credit[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:488 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 499 + Statement : assign dest_port_encoded_all [(i*V+j+1)*DSTPw-1 : (i*V+j)*DSTPw]=ivc_info[i][j].dest_port_encoded; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/dest_port_encoded_all[4] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:483 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 631 + Statement : assign depth_2 = depth - 2; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/V_[0].smart_.dest_e_addr_fifo/mwb2.depth_2[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:508 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[2].congestion[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:495 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 92 + Statement : assign assigned_ovc_not_full_all[i] = ivc_info[C_PORT][i%V].assigned_ovc_not_full; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/assigned_ovc_not_full_all[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:491 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 495 + Statement : assign non_vsa_ivc_num_getting_ovc_grant_all [(i+1)*V-1 : i*V] = ssa_ctrl_in[i].ivc_num_getting_ovc_grant | smart_ctrl_in[i].ivc_num_getting_ovc_grant; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/non_vsa_ivc_num_getting_ovc_grant_all[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:484 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 499 + Statement : assign dest_port_encoded_all [(i*V+j+1)*DSTPw-1 : (i*V+j)*DSTPw]=ivc_info[i][j].dest_port_encoded; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/dest_port_encoded_all[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:511 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/ss_flit_chanel[2].credit[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:515 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[1].credit[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:513 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/ss_flit_chanel[1].congestion[1] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:480 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 128 + Statement : assign {flgs_in,vc_in,flit_rest_in}=din; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/the_flit_buffer/vc_in[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:501 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 93 + Statement : assign ovc_is_assigned_all[i] = ivc_info[C_PORT][i%V].ovc_is_assigned; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/ovc_is_assigned_all[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:482 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 128 + Statement : assign {flgs_in,vc_in,flit_rest_in}=din; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/the_flit_buffer/vc_in[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:496 + Goal : lint_rtl + Module : combined_vc_sw_alloc + FileName : ./../../rtl/src_noc/./combined_vc_sw_alloc.sv + LineNumber : 91 + Statement : assign ivc_request_all[i] = ivc_info[C_PORT][i%V].ivc_req; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/vsa/ivc_request_all[0] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:492 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 495 + Statement : assign non_vsa_ivc_num_getting_ovc_grant_all [(i+1)*V-1 : i*V] = ssa_ctrl_in[i].ivc_num_getting_ovc_grant | smart_ctrl_in[i].ivc_num_getting_ovc_grant; + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/vc_alloc_req_gen/non_vsa_ivc_num_getting_ovc_grant_all[2] + ----------------------------------------------------------------------------- + Tag : UnloadedNet-ML + Description : Detected unloaded(unconnected) net [DesignObjSignal] + Violation : Lint:521 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/ss_flit_chanel[1].congestion[1] + + ----------------------------------------------------------------------------- + UnloadedOutTerm-ML (749 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2063 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[11] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[11]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1993 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/oports_weight_all[0] + String1 : + String2 : Connected to floating net 'oports_weight_all[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1595 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 719 + Statement : ) lk_dest_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/V_[0].unicast.lk_dest_fifo/nearly_full + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1441 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/ovc_info[0][0].avalable + String1 : + String2 : Connected to floating net 'ovc_info[0][0].avalable' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2150 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/oports_weight_all[9] + String1 : + String2 : Connected to floating net 'oports_weight_all[9]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1520 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 625 + Statement : ) dest_e_addr_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/V_[0].smart_.dest_e_addr_fifo/recieve_more_than_0 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1937 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/oports_weight_all[6] + String1 : + String2 : Connected to floating net 'oports_weight_all[6]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1524 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 719 + Statement : ) lk_dest_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/V_[0].unicast.lk_dest_fifo/recieve_more_than_0 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2030 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 175 + Statement : ) the_input_port ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/the_input_port/reset_ivc_all[1] + String1 : + String2 : Connected to floating net 'reset_ivc_all[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1745 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[5] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[5]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1431 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].ctrl_chanel.endp_port + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].ctrl_chanel.endp_port' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1785 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[45] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[45]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1876 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 144 + Statement : ) smart_bypass ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/smart_chanel_out[0].bypassed_num[0] + String1 : + String2 : Connected to floating net 'smart_chanel_out[0].bypassed_num[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1437 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/ovc_info[0][0].empty + String1 : + String2 : Connected to floating net 'ovc_info[0][0].empty' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2056 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[4] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[4]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2024 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/oports_weight_all[31] + String1 : + String2 : Connected to floating net 'oports_weight_all[31]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1459 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 387 + Statement : ) header_extractor ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/tail_flg_o + String1 : + String2 : Connected to floating net 'tail_flg_in' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1908 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/ovc_info[0][0].credit[0] + String1 : + String2 : Connected to floating net 'ovc_info[0][0].credit[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1787 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[47] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[47]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1825 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/iport_weight_all[8] + String1 : + String2 : Connected to floating net 'iport_weight_all[8]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1649 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 740 + Statement : ) dest_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/V_[0].unicast.dtrmn_dest.dest_fifo/recieve_more_than_1 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2111 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[59] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[59]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2057 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[5] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[5]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1435 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.hdr_flag + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.hdr_flag' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1494 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 387 + Statement : ) header_extractor ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/header_extractor/tail_flg_o + String1 : + String2 : Connected to floating net 'tail_flg_in' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1529 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 740 + Statement : ) dest_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/V_[0].unicast.dtrmn_dest.dest_fifo/recieve_more_than_1 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1508 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 625 + Statement : ) dest_e_addr_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/V_[0].smart_.dest_e_addr_fifo/recieve_more_than_0 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1730 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].smart_chanel.bypassed_num[1] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].smart_chanel.bypassed_num[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1592 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 625 + Statement : ) dest_e_addr_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/V_[0].smart_.dest_e_addr_fifo/recieve_more_than_0 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2044 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].smart_chanel.dest_e_addr[1] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].smart_chanel.dest_e_addr[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1923 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/iport_weight_all[4] + String1 : + String2 : Connected to floating net 'iport_weight_all[4]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1839 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/oports_weight_all[10] + String1 : + String2 : Connected to floating net 'oports_weight_all[10]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2119 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/ovc_info[0][0].credit[1] + String1 : + String2 : Connected to floating net 'ovc_info[0][0].credit[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1735 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].smart_chanel.requests[1] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].smart_chanel.requests[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1467 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 387 + Statement : ) header_extractor ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/header_extractor/class_o[0] + String1 : + String2 : Connected to floating net 'class_in' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1977 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/ovc_is_assigned_all[2] + String1 : + String2 : Connected to floating net 'ovc_is_assigned_all[2]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2020 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/oports_weight_all[27] + String1 : + String2 : Connected to floating net 'oports_weight_all[27]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1813 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/ovc_is_assigned_all[2] + String1 : + String2 : Connected to floating net 'ovc_is_assigned_all[2]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1493 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 387 + Statement : ) header_extractor ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[1].the_input_queue_per_port/header_extractor/data_o[0] + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2108 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[56] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[56]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2012 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/oports_weight_all[19] + String1 : + String2 : Connected to floating net 'oports_weight_all[19]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1546 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 719 + Statement : ) lk_dest_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/V_[0].unicast.lk_dest_fifo/full + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1882 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 144 + Statement : ) smart_bypass ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.smart_bypass/smart_chanel_out[0].requests[1] + String1 : + String2 : Connected to floating net 'smart_chanel_out[0].requests[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2023 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/oports_weight_all[30] + String1 : + String2 : Connected to floating net 'oports_weight_all[30]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2084 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[32] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[32]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1752 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[12] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[12]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1909 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/ovc_info[0][0].credit[1] + String1 : + String2 : Connected to floating net 'ovc_info[0][0].credit[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1912 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/ovc_info[0][0].credit[4] + String1 : + String2 : Connected to floating net 'ovc_info[0][0].credit[4]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2080 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[28] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[28]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1490 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 387 + Statement : ) header_extractor ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/hdr_flg_o + String1 : + String2 : Connected to floating net 'hdr_flg_in' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1731 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].smart_chanel.dest_e_addr[0] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].smart_chanel.dest_e_addr[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1442 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 387 + Statement : ) header_extractor ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/header_extractor/class_o[0] + String1 : + String2 : Connected to floating net 'class_in' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2086 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[34] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[34]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1686 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 144 + Statement : ) smart_bypass ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/smart.smart_bypass/smart_chanel_out[0].hdr_flit + String1 : + String2 : Connected to floating net 'smart_chanel_out[0].hdr_flit' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1981 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/iport_weight_all[0] + String1 : + String2 : Connected to floating net 'iport_weight_all[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2114 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[62] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[62]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1887 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 144 + Statement : ) smart_bypass ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/smart.smart_bypass/smart_chanel_out[0].dest_e_addr[1] + String1 : + String2 : Connected to floating net 'smart_chanel_out[0].dest_e_addr[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2050 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.congestion[1] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.congestion[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2055 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[3] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[3]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1651 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 625 + Statement : ) dest_e_addr_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/V_[0].smart_.dest_e_addr_fifo/nearly_full + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2157 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/oports_weight_all[16] + String1 : + String2 : Connected to floating net 'oports_weight_all[16]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1742 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[2] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[2]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1801 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[61] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[61]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1816 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/assigned_ovc_not_full_all[2] + String1 : + String2 : Connected to floating net 'assigned_ovc_not_full_all[2]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1987 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/iport_weight_all[6] + String1 : + String2 : Connected to floating net 'iport_weight_all[6]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2060 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[8] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[8]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1817 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/iport_weight_all[0] + String1 : + String2 : Connected to floating net 'iport_weight_all[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2142 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/oports_weight_all[1] + String1 : + String2 : Connected to floating net 'oports_weight_all[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2112 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[60] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[60]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1899 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 144 + Statement : ) smart_bypass ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/smart.smart_bypass/smart_chanel_out[0].requests[2] + String1 : + String2 : Connected to floating net 'smart_chanel_out[0].requests[2]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2041 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].smart_chanel.bypassed_num[0] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].smart_chanel.bypassed_num[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1868 + Goal : lint_rtl + Module : check_straight_oport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 407 + Statement : line_ring_decode_dstport decoder( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[1].smart_en.smart_allocator/check_straight/oneD.non_local.decoder/dstport_one_hot[0] + String1 : + String2 : Connected to floating net 'oneD.non_local.destport_one_hot[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1826 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/iport_weight_all[9] + String1 : + String2 : Connected to floating net 'iport_weight_all[9]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1871 + Goal : lint_rtl + Module : check_straight_oport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 407 + Statement : line_ring_decode_dstport decoder( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/smart.Port_[2].smart_en.smart_allocator/check_straight/oneD.non_local.decoder/dstport_one_hot[2] + String1 : + String2 : Connected to floating net 'oneD.non_local.destport_one_hot[2]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1775 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[35] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[35]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1500 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 387 + Statement : ) header_extractor ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/header_extractor/hdr_flg_o + String1 : + String2 : Connected to floating net 'hdr_flg_in' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1704 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/ovc_info[0][0].empty + String1 : + String2 : Connected to floating net 'ovc_info[0][0].empty' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1756 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[16] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[16]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2067 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[15] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[15]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1806 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 110 + Statement : )router_ref ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/ovc_info[0][0].credit[0] + String1 : + String2 : Connected to floating net 'ovc_info[0][0].credit[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1782 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[42] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[42]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1963 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/oports_weight_all[32] + String1 : + String2 : Connected to floating net 'oports_weight_all[32]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2017 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/oports_weight_all[24] + String1 : + String2 : Connected to floating net 'oports_weight_all[24]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1951 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/oports_weight_all[20] + String1 : + String2 : Connected to floating net 'oports_weight_all[20]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2052 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[0] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2146 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/router_ref/the_inout_ports/oports_weight_all[5] + String1 : + String2 : Connected to floating net 'oports_weight_all[5]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2048 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].smart_chanel.requests[2] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].smart_chanel.requests[2]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1589 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 740 + Statement : ) dest_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[2].the_input_queue_per_port/V_[0].unicast.dtrmn_dest.dest_fifo/recieve_more_than_1 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1827 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/iport_weight_all[10] + String1 : + String2 : Connected to floating net 'iport_weight_all[10]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1799 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[59] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[59]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1509 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 625 + Statement : ) dest_e_addr_fifo ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/V_[0].smart_.dest_e_addr_fifo/recieve_more_than_1 + String1 : + String2 : Left Open + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1712 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.tail_flag + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.tail_flag' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1772 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[32] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[32]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1763 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[23] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[23]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1789 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/chan_out[2].flit_chanel.flit.payload[49] + String1 : + String2 : Connected to floating net 'router_chan_out[0][2].flit_chanel.flit.payload[49]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1917 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[1].the_router/router_ref/the_inout_ports/assigned_ovc_not_full_all[1] + String1 : + String2 : Connected to floating net 'assigned_ovc_not_full_all[1]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1874 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 131 + Statement : ) forward_ivc ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/smart.forward_ivc/ovc_locally_requested[0][0] + String1 : + String2 : Connected to floating net 'ovc_locally_requested[0][0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:1811 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/ovc_is_assigned_all[0] + String1 : + String2 : Connected to floating net 'ovc_is_assigned_all[0]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2004 + Goal : lint_rtl + Module : router_two_stage + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 269 + Statement : ) the_inout_ports ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[2].the_router/router_ref/the_inout_ports/oports_weight_all[11] + String1 : + String2 : Connected to floating net 'oports_weight_all[11]' + ----------------------------------------------------------------------------- + Tag : UnloadedOutTerm-ML + Description : Detected unloaded(unconnected) output terminal [DesignObjSignal] ([String2]) + Violation : Lint:2083 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 70 + Statement : ) the_router ( + DesignObjSignal : tori_noc.noc_top/ring_line.R_[3].the_router/chan_out[1].flit_chanel.flit.payload[31] + String1 : + String2 : Connected to floating net 'router_chan_out[3][1].flit_chanel.flit.payload[31]' + + ----------------------------------------------------------------------------- + W120 (175 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4222 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 291 + Statement : wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + VariableName : dest_port_multi + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5405 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 292 + Statement : wire [V-1 : 0] multiple_dest,dst_onhot0; + VariableName : dst_onhot0 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4142 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1308 + Statement : wire [NL-1 : 0] endp_localp_onehot; + VariableName : endp_localp_onehot + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator:\one_D.decoder @line_ring_destp_decoder + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5597 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.payload[63:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5413 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 317 + Statement : wire [Pw-1 : 0] endp_p_in; + VariableName : endp_p_in[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5752 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 328 + Statement : wire [V-1 : 0] dstport_fifo_not_empty; + VariableName : dstport_fifo_not_empty + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3897 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1308 + Statement : wire [NL-1 : 0] endp_localp_onehot; + VariableName : endp_localp_onehot + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator:\one_D.decoder @line_ring_destp_decoder + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5855 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 316 + Statement : wire [ELw-1 : 0] endp_l_in; + VariableName : endp_l_in + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5505 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 328 + Statement : wire [V-1 : 0] dstport_fifo_not_empty; + VariableName : dstport_fifo_not_empty + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5251 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.payload[63:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4035 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 317 + Statement : wire [Pw-1 : 0] endp_p_in; + VariableName : endp_p_in[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4431 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 124 + Statement : integer k; + VariableName : k + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3825 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 109 + Statement : wire [V-1 : 0] sub_restore; + VariableName : sub_restore + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4746 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 343 + Statement : wire [P-1 :0] smart_forwardable; + VariableName : smart_forwardable[0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5166 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 317 + Statement : wire [Pw-1 : 0] endp_p_in; + VariableName : endp_p_in[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5063 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5861 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 317 + Statement : wire [Pw-1 : 0] endp_p_in; + VariableName : endp_p_in[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5853 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 292 + Statement : wire [V-1 : 0] multiple_dest,dst_onhot0; + VariableName : dst_onhot0 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5160 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 316 + Statement : wire [ELw-1 : 0] endp_l_in; + VariableName : endp_l_in + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5592 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit_wr + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5591 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 158 + Statement : wire [V-1 : 0] ivc_smart_en [P-1 : 0]; + VariableName : smart.ivc_smart_en + ExprSize : (1 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:\smart + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4744 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 339 + Statement : smart_chanel_t smart_chanel_shifted [P-1 : 0]; + VariableName : smart_chanel_shifted[0].flit_in_bypassed + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3746 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 291 + Statement : wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + VariableName : dest_port_multi + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5506 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 316 + Statement : wire [ELw-1 : 0] endp_l_in; + VariableName : endp_l_in + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3741 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 328 + Statement : wire [V-1 : 0] dstport_fifo_not_empty; + VariableName : dstport_fifo_not_empty + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5596 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.vc[0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5507 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 339 + Statement : wire [V-1 : 0] flit_is_tail2; + VariableName : flit_is_tail2 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5164 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 291 + Statement : wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + VariableName : dest_port_multi + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5854 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 328 + Statement : wire [V-1 : 0] dstport_fifo_not_empty; + VariableName : dstport_fifo_not_empty + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3668 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.payload[63:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5248 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.hdr_flag + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5246 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit_wr + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3669 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].congestion[2:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5062 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 339 + Statement : wire [V-1 : 0] flit_is_tail2; + VariableName : flit_is_tail2 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4902 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.hdr_flag + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5306 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 292 + Statement : wire [V-1 : 0] multiple_dest,dst_onhot0; + VariableName : dst_onhot0 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3744 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3747 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 456 + Statement : logic [1:0] ovc_sel_i; + VariableName : ovc_sel_i[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4610 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 473 + Statement : wire [V-1 : 0] pck_is_single_flit [P-1 : 0]; + VariableName : pck_is_single_flit + ExprSize : (3 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:vsa@combined_vc_sw_alloc:\nonspec.cmb_v1.nonspec_comb @comb_nonspec_allocator:nonspeculative_sw_allocator@nonspec_sw_alloc + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5595 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.tail_flag + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4031 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4966 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 291 + Statement : wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + VariableName : dest_port_multi + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5509 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 293 + Statement : wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; + VariableName : clear_dspt_mulicast + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5067 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 317 + Statement : wire [Pw-1 : 0] endp_p_in; + VariableName : endp_p_in[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5412 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 456 + Statement : logic [1:0] ovc_sel_i; + VariableName : ovc_sel_i[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4742 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 339 + Statement : smart_chanel_t smart_chanel_shifted [P-1 : 0]; + VariableName : smart_chanel_shifted[0].dest_e_addr[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3829 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 90 + Statement : wire [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; + VariableName : sub_rd_ptr + ExprSize : (4 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5593 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].credit[0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5252 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].congestion[2:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3845 + Goal : lint_rtl + Module : one_hot_to_bin + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 271 + Statement : wire [MUX_IN_WIDTH-1 : 0] bin_temp ; + VariableName : bin_temp + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer:\pow2.wr_vc_start_addr @one_hot_to_bin + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5511 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 456 + Statement : logic [1:0] ovc_sel_i; + VariableName : ovc_sel_i[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5756 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 293 + Statement : wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; + VariableName : clear_dspt_mulicast + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5598 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].congestion[2:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5660 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 317 + Statement : wire [Pw-1 : 0] endp_p_in; + VariableName : endp_p_in[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3743 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 339 + Statement : wire [V-1 : 0] flit_is_tail2; + VariableName : flit_is_tail2 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5755 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5860 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 456 + Statement : logic [1:0] ovc_sel_i; + VariableName : ovc_sel_i[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4741 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 339 + Statement : smart_chanel_t smart_chanel_shifted [P-1 : 0]; + VariableName : smart_chanel_shifted[0].ovc[0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5504 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 292 + Statement : wire [V-1 : 0] multiple_dest,dst_onhot0; + VariableName : dst_onhot0 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5244 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 157 + Statement : wire [V-1 : 0] credit_out [P-1 : 0]; + VariableName : smart.credit_out + ExprSize : (1 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:\smart + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5758 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 456 + Statement : logic [1:0] ovc_sel_i; + VariableName : ovc_sel_i[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4028 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 328 + Statement : wire [V-1 : 0] dstport_fifo_not_empty; + VariableName : dstport_fifo_not_empty + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5161 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 339 + Statement : wire [V-1 : 0] flit_is_tail2; + VariableName : flit_is_tail2 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4091 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 108 + Statement : wire [V-1 : 0] sub_rd; + VariableName : sub_rd + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3824 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 108 + Statement : wire [V-1 : 0] sub_rd; + VariableName : sub_rd + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4967 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 456 + Statement : logic [1:0] ovc_sel_i; + VariableName : ovc_sel_i[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4094 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 101 + Statement : wire [DEPTHw-1 : 0] sub_depth [V-1 :0]; + VariableName : sub_depth + ExprSize : (3 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3748 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 317 + Statement : wire [Pw-1 : 0] endp_p_in; + VariableName : endp_p_in[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3662 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 158 + Statement : wire [V-1 : 0] ivc_smart_en [P-1 : 0]; + VariableName : smart.ivc_smart_en + ExprSize : (1 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5411 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 291 + Statement : wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + VariableName : dest_port_multi + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3663 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit_wr + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5308 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 316 + Statement : wire [ELw-1 : 0] endp_l_in; + VariableName : endp_l_in + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5245 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 158 + Statement : wire [V-1 : 0] ivc_smart_en [P-1 : 0]; + VariableName : smart.ivc_smart_en + ExprSize : (1 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:\smart + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3745 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 293 + Statement : wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; + VariableName : clear_dspt_mulicast + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4096 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 90 + Statement : wire [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; + VariableName : sub_rd_ptr + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:the_flit_buffer@flit_buffer + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4906 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].congestion[2:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5857 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5064 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 293 + Statement : wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; + VariableName : clear_dspt_mulicast + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5658 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 291 + Statement : wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + VariableName : dest_port_multi + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4219 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 339 + Statement : wire [V-1 : 0] flit_is_tail2; + VariableName : flit_is_tail2 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4027 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 292 + Statement : wire [V-1 : 0] multiple_dest,dst_onhot0; + VariableName : dst_onhot0 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5311 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 293 + Statement : wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; + VariableName : clear_dspt_mulicast + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5061 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 316 + Statement : wire [ELw-1 : 0] endp_l_in; + VariableName : endp_l_in + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5407 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 316 + Statement : wire [ELw-1 : 0] endp_l_in; + VariableName : endp_l_in + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4604 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 93 + Statement : wire [P-1 : 0] any_cand_ovc_exsit; + VariableName : any_cand_ovc_exsit[2:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:vsa@combined_vc_sw_alloc:\nonspec.cmb_v1.nonspec_comb @comb_nonspec_allocator + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5751 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 292 + Statement : wire [V-1 : 0] multiple_dest,dst_onhot0; + VariableName : dst_onhot0 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5066 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 456 + Statement : logic [1:0] ovc_sel_i; + VariableName : ovc_sel_i[1:0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4964 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3860 + Goal : lint_rtl + Module : ovc_list + FileName : ./../../rtl/src_noc/./ovc_list.sv + LineNumber : 42 + Statement : logic [V-1 : 0] ovc_message_class; + VariableName : ovc_message_class + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].ovc_.OvcList @ovc_list + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5594 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].flit.hdr_flag + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5590 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 157 + Statement : wire [V-1 : 0] credit_out [P-1 : 0]; + VariableName : smart.credit_out + ExprSize : (1 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:\smart + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5163 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 293 + Statement : wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; + VariableName : clear_dspt_mulicast + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4030 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 339 + Statement : wire [V-1 : 0] flit_is_tail2; + VariableName : flit_is_tail2 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5654 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 316 + Statement : wire [ELw-1 : 0] endp_l_in; + VariableName : endp_l_in + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5656 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5065 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 291 + Statement : wire [DSTPw-1 : 0] dest_port_multi [V-1 : 0]; + VariableName : dest_port_multi + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5310 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 457 + Statement : logic [1:0] ovc_sel_ivc [V-1 : 0]; + VariableName : ovc_sel_ivc + ExprSize : (2 bits) + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4309 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1308 + Statement : wire [NL-1 : 0] endp_localp_onehot; + VariableName : endp_localp_onehot + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator:\one_D.decoder @line_ring_destp_decoder + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3664 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 104 + Statement : flit_chanel_t ss_flit_chanel [P-1 : 0]; //flit bypass link goes to straight port + VariableName : ss_flit_chanel[0].credit[0] + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W120 + Description : Variable '[VariableName]'[ExprSize] declared but not used.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5655 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 339 + Statement : wire [V-1 : 0] flit_is_tail2; + VariableName : flit_is_tail2 + ExprSize : + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + + ----------------------------------------------------------------------------- + W175 (40 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2895 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1291 + Statement : parameter ROUTE_TYPE="DETERMINISTIC", + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2887 + Goal : lint_rtl + Module : fwft_fifo + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 551 + Statement : parameter IGNORE_SAME_LOC_RD_WR_WARNING="YES" // "YES" , "NO" + Param : IGNORE_SAME_LOC_RD_WR_WARNING + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2860 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 103 + Statement : PVDSTPw= PV * DSTPw, + Param : PVDSTPw + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2884 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 30 + Statement : parameter TOPOLOGY = "MESH", + Param : TOPOLOGY + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2885 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 62 + Statement : BVwV = BVw * V, + Param : BVwV + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2865 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 80 + Statement : VP_1 = V * P_1, + Param : VP_1 + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2856 + Goal : lint_rtl + Module : extract_header_flit_info + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 108 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2864 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 86 + Statement : PVDSTPw= PV * DSTPw, + Param : PVDSTPw + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2877 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 237 + Statement : parameter T4= 8, + Param : T4 + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2872 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 314 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2882 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 57 + Statement : PVV = PV * V, + Param : PVV + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2889 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 312 + Statement : E_WEST = 2, + Param : E_WEST + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2894 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1296 + Statement : parameter PPSw=4, + Param : PPSw + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2893 + Goal : lint_rtl + Module : mesh_tori_router_addr_decode + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 881 + Statement : parameter T3=4, + Param : T3 + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2867 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 76 + Statement : VV = V * V, + Param : VV + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2876 + Goal : lint_rtl + Module : credit_monitor_per_ovc + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 398 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2873 + Goal : lint_rtl + Module : smart_validity_check_per_ivc + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 422 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2857 + Goal : lint_rtl + Module : header_flit_update_lk_route_ovc + FileName : ./../../rtl/src_noc/./header_flit.sv + LineNumber : 196 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2878 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 232 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2863 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 87 + Statement : PRAw= P * RAw; + Param : PRAw + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2866 + Goal : lint_rtl + Module : input_ports + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 77 + Statement : PVV = PV * V, + Param : PVV + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2874 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 347 + Statement : P_1 = P-1, + Param : P_1 + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2868 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 225 + Statement : PORT_Bw= log2(PORT_B), + Param : PORT_Bw + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2862 + Goal : lint_rtl + Module : vc_alloc_request_gen_determinstic + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 606 + Statement : parameter CAST_TYPE = "UNICAST" + Param : CAST_TYPE + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2892 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 292 + Statement : EAST = 1, + Param : EAST + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2890 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 311 + Statement : E_NORTH = 1, + Param : E_NORTH + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2858 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 32 + Statement : parameter NOC_ID = 0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2888 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 313 + Statement : E_SOUTH = 3; + Param : E_SOUTH + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2871 + Goal : lint_rtl + Module : smart_forward_ivc_info + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 210 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2875 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 334 + Statement : parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001 + Param : ESCAP_VC_MASK + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2881 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 59 + Statement : VP_1 = V * P_1, + Param : VP_1 + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2886 + Goal : lint_rtl + Module : flit_buffer + FileName : ./../../rtl/src_noc/./flit_buffer.sv + LineNumber : 61 + Statement : BwV = Bw * V, + Param : BwV + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2861 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 432 + Statement : parameter NOC_ID=0, + Param : NOC_ID + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2880 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 61 + Statement : PVP_1 = PV * P_1, + Param : PVP_1 + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2891 + Goal : lint_rtl + Module : mesh_torus_mask_non_assignable_destport_no_self_loop + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 310 + Statement : E_LOCAL = 0, + Param : E_LOCAL + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2859 + Goal : lint_rtl + Module : inout_ports + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 104 + Statement : PRAw= P * RAw; + Param : PRAw + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2883 + Goal : lint_rtl + Module : crossbar + FileName : ./../../rtl/src_noc/./crossbar.v + LineNumber : 55 + Statement : VV = V * V, + Param : VV + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2870 + Goal : lint_rtl + Module : mesh_torus_conventional_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 600 + Statement : parameter ROUTE_TYPE = "DETERMINISTIC", + Param : ROUTE_TYPE + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2869 + Goal : lint_rtl + Module : mesh_torus_deterministic_look_ahead_routing + FileName : ./../../rtl/src_noc/./mesh_torus_routting.v + LineNumber : 109 + Statement : parameter SW_LOC =0, + Param : SW_LOC + ----------------------------------------------------------------------------- + Tag : W175 + Description : Parameter '[Param]' declared but not used + Violation : Lint:2879 + Goal : lint_rtl + Module : credit_release_gen + FileName : ./../../rtl/src_noc/./router_two_stage.sv + LineNumber : 656 + Statement : parameter NOC_ID=0, + Param : NOC_ID + + ----------------------------------------------------------------------------- + W240 (901 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4464 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 472 + Statement : input ssa_ctrl_t ssa_ctrl_in [P-1: 0]; + Signal : ssa_ctrl_in[2].ivc_granted_ovc_num[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4939 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.credit_out[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3997 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 281 + Statement : input vsa_ctrl_t vsa_ctrl_in; + Signal : vsa_ctrl_in.ovc_is_released[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4486 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 473 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + Signal : smart_ctrl_in[2].buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4727 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[0][0].assigned_ovc_not_full + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4187 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 281 + Statement : input vsa_ctrl_t vsa_ctrl_in; + Signal : vsa_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4441 + Goal : lint_rtl + Module : port_pre_sel_gen + FileName : ./../../rtl/src_noc/./congestion_analyzer.v + LineNumber : 351 + Statement : input [PV-1 : 0] ovc_status; + Signal : ovc_status[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports:port_pre_sel_top@port_pre_sel_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5740 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2].hetero_ovc_presence[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5403 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].hetero_ovc_presence[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4770 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 579 + Statement : input ivc_info_t ivc_info [V-1 : 0]; + Signal : ivc_info[0].flit_is_tail + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[1].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5487 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.mask_available_ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4385 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 97 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + Signal : smart_ctrl_in[1].ivc_reset[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4201 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 253 + Statement : input router_info_t router_info; + Signal : router_info.router_id[31:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4713 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[1][0].ivc_req + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5231 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + Signal : chan_in[0].smart_chanel.flit_in_bypassed + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4578 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 73 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[2][0].destport_one_hot[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:vsa@combined_vc_sw_alloc:\nonspec.cmb_v1.nonspec_comb @comb_nonspec_allocator + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4540 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 474 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[0][0].single_flit_pck + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4710 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[1][0].assigned_ovc_bin[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3991 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.hdr_flit_req + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5731 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5272 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.ssa_flit_wr + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5300 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2:0].endp_port + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4766 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 579 + Statement : input ivc_info_t ivc_info [V-1 : 0]; + Signal : ivc_info[0].dest_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[1].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5494 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[1].endp_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5303 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].credit_release_en[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5739 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2].credit_release_en[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4360 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 96 + Statement : input ssa_ctrl_t ssa_ctrl_in [P-1: 0]; + Signal : ssa_ctrl_in[2].ivc_reset[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5476 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.ovc_is_allocated[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4655 + Goal : lint_rtl + Module : smart_forward_ivc_info + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 224 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[2][0].single_flit_pck + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.forward_ivc @smart_forward_ivc_info + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3996 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 281 + Statement : input vsa_ctrl_t vsa_ctrl_in; + Signal : vsa_ctrl_in.ovc_is_allocated[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5124 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.ssa_flit_wr + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4000 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.ovc_is_released[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4375 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 97 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + Signal : smart_ctrl_in[2].ivc_num_getting_ovc_grant[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4514 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 473 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + Signal : smart_ctrl_in[0].ivc_single_flit_pck[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5725 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5623 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 281 + Statement : input vsa_ctrl_t vsa_ctrl_in; + Signal : vsa_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4387 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 97 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + Signal : smart_ctrl_in[1].ivc_single_flit_pck[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4422 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 94 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[0][0].destport_one_hot[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4548 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 475 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[1].hetero_ovc_presence[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5048 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2].hetero_ovc_presence[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4407 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 94 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[2][0].candidate_ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4841 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 584 + Statement : input smart_chanel_t ss_smart_chanel_new; + Signal : ss_smart_chanel_new.bypassed_num[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[2].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5388 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.mask_available_ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5046 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2].router_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4146 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 279 + Statement : input [EAw-1 : 0] src_e_addr; + Signal : src_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\unicast.lk_routing @look_ahead_routing + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5644 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[1].credit_release_en[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3723 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].credit_release_en[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4591 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 73 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[1][0].class_num[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:vsa@combined_vc_sw_alloc:\nonspec.cmb_v1.nonspec_comb @comb_nonspec_allocator + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4196 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4515 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 473 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + Signal : smart_ctrl_in[0].ovc_single_flit_pck[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4688 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 331 + Statement : input smart_chanel_t smart_chanel_in [P-1 : 0]; + Signal : smart_chanel_in[0].dest_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4583 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 73 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[2][0].single_flit_pck + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:vsa@combined_vc_sw_alloc:\nonspec.cmb_v1.nonspec_comb @comb_nonspec_allocator + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4859 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + Signal : flit_chanel_i.flit.payload[63:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[2].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5818 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.smart_en + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4147 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 276 + Statement : input [PRAw-1: 0] neighbors_r_addr; + Signal : neighbors_r_addr[5:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\unicast.lk_routing @look_ahead_routing + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5132 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4659 + Goal : lint_rtl + Module : smart_forward_ivc_info + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 224 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[1][0].assigned_ovc_not_full + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.forward_ivc @smart_forward_ivc_info + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4849 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 579 + Statement : input ivc_info_t ivc_info [V-1 : 0]; + Signal : ivc_info[0].assigned_ovc_bin[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[2].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5138 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4190 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5153 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].endp_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4412 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 94 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[1][0].destport_one_hot[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5640 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2].credit_release_en[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4669 + Goal : lint_rtl + Module : smart_forward_ivc_info + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 224 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[0][0].single_flit_pck + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.forward_ivc @smart_forward_ivc_info + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3722 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].router_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3705 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.credit_out[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4404 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 94 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[2][0].ivc_req + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4724 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[0][0].dest_port_encoded[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4141 + Goal : lint_rtl + Module : line_ring_destp_decoder + FileName : ./../../rtl/src_noc/./mesh_torus.sv + LineNumber : 1306 + Statement : input [ELw-1 : 0] endp_localp_num; + Signal : endp_localp_num[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port:\V_[0].decoder @destp_generator:\mesh.destp_generator @mesh_torus_destp_generator:\one_D.decoder @line_ring_destp_decoder + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4207 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[1].router_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5493 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2].hetero_ovc_presence[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5501 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].credit_release_en[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4512 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 473 + Statement : input smart_ctrl_t smart_ctrl_in [P-1: 0]; + Signal : smart_ctrl_in[0].ovc_is_released[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3706 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3720 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[2:0].endp_port + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3691 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.smart_en + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5626 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4463 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 472 + Statement : input ssa_ctrl_t ssa_ctrl_in [P-1: 0]; + Signal : ssa_ctrl_in[2].ovc_single_flit_pck[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5304 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].hetero_ovc_presence[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5625 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 282 + Statement : input ssa_ctrl_t ssa_ctrl_in; + Signal : ssa_ctrl_in.ovc_is_released[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4860 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + Signal : flit_chanel_i.congestion[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[2].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4927 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 269 + Statement : input [DSTPw-1 : 0] destport_clear [V-1 : 0]; + Signal : destport_clear + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4181 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.smart_en + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5230 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 49 + Statement : input smartflit_chanel_t chan_in [P-1 : 0]; + Signal : chan_in[0].smart_chanel.hdr_flit + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4687 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 331 + Statement : input smart_chanel_t smart_chanel_in [P-1 : 0]; + Signal : smart_chanel_in[0].ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4858 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 577 + Statement : input flit_chanel_t flit_chanel_i; + Signal : flit_chanel_i.flit.vc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[2].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4956 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[0].router_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5838 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 253 + Statement : input router_info_t router_info; + Signal : router_info.router_id[31:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4924 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.hdr_flit_req + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4695 + Goal : lint_rtl + Module : smart_bypass_chanels + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 332 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[2][0].dest_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.smart_bypass @smart_bypass_chanels + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4656 + Goal : lint_rtl + Module : smart_forward_ivc_info + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 224 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[1][0].assigned_ovc_num[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.forward_ivc @smart_forward_ivc_info + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5042 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.mask_available_ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4349 + Goal : lint_rtl + Module : output_ports + FileName : ./../../rtl/src_noc/./output_ports.sv + LineNumber : 95 + Statement : input vsa_ctrl_t vsa_ctrl_in [P-1: 0]; + Signal : vsa_ctrl_in[2].ivc_granted_ovc_num[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:output_ports@output_ports + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5484 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.buff_space_decreased[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5290 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.ovc_single_flit_pck[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4467 + Goal : lint_rtl + Module : vc_alloc_request_gen + FileName : ./../../rtl/src_noc/./inout_ports.sv + LineNumber : 472 + Statement : input ssa_ctrl_t ssa_ctrl_in [P-1: 0]; + Signal : ssa_ctrl_in[1].ivc_num_getting_sw_grant[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:vc_alloc_req_gen@vc_alloc_request_gen + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4012 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 253 + Statement : input router_info_t router_info; + Signal : router_info.router_id[31:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[1].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4586 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 73 + Statement : input ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; + Signal : ivc_info[1][0].assigned_ovc_bin[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:vsa@combined_vc_sw_alloc:\nonspec.cmb_v1.nonspec_comb @comb_nonspec_allocator + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5630 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 280 + Statement : input smart_ctrl_t smart_ctrl_in; + Signal : smart_ctrl_in.destport[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port + ----------------------------------------------------------------------------- + Tag : W240 + Description : Input '[Signal]' declared but not read.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5843 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 284 + Statement : input ctrl_chanel_t ctrl_in [P-1 : 0]; + Signal : ctrl_in[1].endp_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[2].the_input_queue_per_port @input_queue_per_port + + ----------------------------------------------------------------------------- + W241 (24 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4891 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.bypassed_num[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5233 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4890 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.flit_in_bypassed + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5583 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.bypassed_num[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3647 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.requests[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5582 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.flit_in_bypassed + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5235 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.hdr_flit + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5578 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.requests[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5232 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.requests[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3650 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.hdr_flit + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5581 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.hdr_flit + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5236 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.flit_in_bypassed + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3652 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.bypassed_num[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3651 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.flit_in_bypassed + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3649 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.dest_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4888 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.dest_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5234 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.dest_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4886 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.requests[2:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5237 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.bypassed_num[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4887 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3648 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5579 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.ovc[0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4889 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.hdr_flit + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W241 + Description : Output '[Signal]' is never set.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5580 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 50 + Statement : output smartflit_chanel_t chan_out [P-1 : 0]; + Signal : chan_out[0].smart_chanel.dest_e_addr[1:0] + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + + ----------------------------------------------------------------------------- + W287a (32 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4897 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].bypassed_num[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3655 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].dest_e_addr[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3621 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[2].endp_addrs[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5241 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].hdr_flit + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3622 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[2].endp_ids[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4895 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].hdr_flit + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5585 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].ovc[0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3625 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[0].endp_addrs[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3658 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].bypassed_num[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3620 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[3].endp_ids[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3624 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[1].endp_ids[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5587 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].hdr_flit + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5239 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].ovc[0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3619 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[3].endp_addrs[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5584 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].requests[2:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3626 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[0].endp_ids[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3656 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].hdr_flit + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4892 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].requests[2:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5242 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].flit_in_bypassed + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3653 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].requests[2:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3657 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].flit_in_bypassed + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5243 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].bypassed_num[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5586 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].dest_e_addr[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3623 + Goal : lint_rtl + Module : mesh_torus_noc_top + FileName : ./../../rtl/src_noc/./mesh_torus_noc_top.sv + LineNumber : 71 + Statement : .router_config_in(router_config_in[RID]), + Signal : router_config_in[1].endp_addrs[1:0] + InstName : the_router + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4896 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].flit_in_bypassed + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5588 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].flit_in_bypassed + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5589 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].bypassed_num[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[3].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4894 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].dest_e_addr[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3654 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].ovc[0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5238 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].requests[2:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:5240 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].dest_e_addr[1:0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[2].the_router @router_top + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is undriven.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4893 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 149 + Statement : .smart_chanel_in(smart_chanel_in), + Signal : smart_chanel_in[0].ovc[0] + InstName : smart_bypass + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[1].the_router @router_top + + ----------------------------------------------------------------------------- + W287a (4 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is unconnected.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4862 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 659 + Statement : .src_e_addr ( ),// needed only for custom routing + Signal : src_e_addr + InstName : lkrouting + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[2].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is unconnected.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4779 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 627 + Statement : .src_e_addr ( ),// needed only for custom routing + Signal : src_e_addr + InstName : routing + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[1].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is unconnected.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4861 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 627 + Statement : .src_e_addr ( ),// needed only for custom routing + Signal : src_e_addr + InstName : routing + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[2].smart_en.smart_allocator @smart_allocator_per_iport + ----------------------------------------------------------------------------- + Tag : W287a + Description : Input '[Signal]' of instance '[InstName]' is unconnected.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:4780 + Goal : lint_rtl + Module : smart_allocator_per_iport + FileName : ./../../rtl/src_noc/./router_bypass.sv + LineNumber : 659 + Statement : .src_e_addr ( ),// needed only for custom routing + Signal : src_e_addr + InstName : lkrouting + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:\smart.Port_[1].smart_en.smart_allocator @smart_allocator_per_iport + + ----------------------------------------------------------------------------- + W287b (23 warnings/0 waived) + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3903 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 311 + Statement : .valid( ) + ModPortName : valid + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3733 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 725 + Statement : .nearly_full (), + ModPortName : nearly_full + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3727 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 399 + Statement : .be_o( ), + ModPortName : be_o + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3732 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 724 + Statement : .full (), + ModPortName : full + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3731 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 633 + Statement : .recieve_more_than_1 ( ), + ModPortName : recieve_more_than_1 + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3738 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 747 + Statement : .recieve_more_than_0(), + ModPortName : recieve_more_than_0 + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3736 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 745 + Statement : .full(), + ModPortName : full + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3905 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 340 + Statement : .valid() + ModPortName : valid + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3726 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 400 + Statement : .data_o( ) + ModPortName : data_o + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3734 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 726 + Statement : .recieve_more_than_0 (), + ModPortName : recieve_more_than_0 + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:4794 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 122 + Statement : .valid() + ModPortName : valid + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3659 + Goal : lint_rtl + Module : router_top + FileName : ./../../rtl/src_noc/./router_top.sv + LineNumber : 151 + Statement : .smart_req(), + ModPortName : smart_req + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:4609 + Goal : lint_rtl + Module : nonspec_sw_alloc + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 513 + Statement : .any_grant( ), + ModPortName : any_grant + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3729 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 631 + Statement : .nearly_full ( ), + ModPortName : nearly_full + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3735 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 727 + Statement : .recieve_more_than_1 (), + ModPortName : recieve_more_than_1 + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3730 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 632 + Statement : .recieve_more_than_0 ( ), + ModPortName : recieve_more_than_0 + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3728 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 630 + Statement : .full ( ), + ModPortName : full + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3904 + Goal : lint_rtl + Module : look_ahead_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 339 + Statement : .el( ), + ModPortName : el + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3737 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 746 + Statement : .nearly_full(), + ModPortName : nearly_full + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:4793 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 121 + Statement : .el( ), + ModPortName : el + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:4792 + Goal : lint_rtl + Module : conventional_routing + FileName : ./../../rtl/src_noc/./routing.v + LineNumber : 93 + Statement : .valid( ) + ModPortName : valid + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:3739 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 748 + Statement : .recieve_more_than_1(), + ModPortName : recieve_more_than_1 + ----------------------------------------------------------------------------- + Tag : W287b + Description : Instance output port '[ModPortName]' is not connected + Violation : Lint:4602 + Goal : lint_rtl + Module : comb_nonspec_allocator + FileName : ./../../rtl/src_noc/./comb_nonspec.sv + LineNumber : 161 + Statement : .any_grant() + ModPortName : any_grant + + ----------------------------------------------------------------------------- + W468 (1 warning/0 waived) + ----------------------------------------------------------------------------- + Tag : W468 + Description : Variable/Signal '[Signal_Name]' is indexed by '[Signal]' which cannot index the full range of this vector.[Hierarchy: '[HIERARCHY]'] + Violation : Lint:3858 + Goal : lint_rtl + Module : ovc_list + FileName : ./../../rtl/src_noc/./ovc_list.sv + LineNumber : 46 + Statement : assign ovcs_out= (C == 0 || C == 1)? {V{1'b1}} : class_table[class_in]; + Signal_Name : class_table + Signal : class_in + HIERARCHY : :noc_top:\tori_noc.noc_top @mesh_torus_noc_top:\ring_line.R_[0].the_router @router_top:router_ref@router_two_stage:the_inout_ports@inout_ports:the_input_port@input_ports:\Port_[0].the_input_queue_per_port @input_queue_per_port:\V_[0].ovc_.OvcList @ovc_list + + ----------------------------------------------------------------------------- + AvoidAsync (1 info/0 waived/2 compressed) + ----------------------------------------------------------------------------- + Tag : AvoidAsync + Description : Asynchronous [NodeType] signal '[Signal]' used at flop '[FLOP]' + Violation : Lint:1 + Goal : lint_rtl + NodeType : Reset + Signal : reset + SignalRange : + Module : pronoc_register_reset_init + HIERARCHY : pronoc_register_reset_init + SeqSetRstNet : tori_noc.noc_top/ring_line.R_[0].the_router/router_ref/the_inout_ports/the_input_port/Port_[0].the_input_queue_per_port/reg1/reg1/reset + FileName : ./../../rtl/src_noc/./../main_comp.v + LineNumber : 56 + Statement : input reset, + FLOP : out[0] + + ----------------------------------------------------------------------------- + NoExprInPort-ML (1 info/0 waived) + ----------------------------------------------------------------------------- + Tag : NoExprInPort-ML + Description : Expressions [HdlExp] used in port connection in module instantiation + Violation : Lint:3753 + Goal : lint_rtl + Module : input_queue_per_port + FileName : ./../../rtl/src_noc/./input_ports.sv + LineNumber : 372 + Statement : .in (ivc_num_getting_sw_grant & ~ multiple_dest), + HdlExp : (ivc_num_getting_sw_grant & (~multiple_dest)) + + ----------------------------------------------------------------------------- + ReportPortInfo-ML (1 info/0 waived) + ----------------------------------------------------------------------------- + Tag : ReportPortInfo-ML + Description : Port Information for top design unit has been generated. For details see report ReportPortInfo.rpt + Violation : Lint:5921 + Goal : lint_rtl + FileName : .//vc_lint0/noc_top/VC_GOAL0/spyglass_reports/morelint/ReportPortInfo + LineNumber : 1 + Statement : # Comment : Report Top Level Module Port Info + + ----------------------------------------------------------------------------- + W120 (1 info/0 waived) + ----------------------------------------------------------------------------- + Tag : W120 + Description : Please refer to 'SignalUsageReport.rpt' for details of violating bits + Violation : Lint:3660 + Goal : lint_rtl + Module : noc_top + FileName : .//vc_lint0/noc_top/VC_GOAL0/spyglass_reports/lint/SignalUsageReport.rpt + LineNumber : 1 + Statement : # Comment : SignalUsageReport : It dumps details of violating bits of a signal + + ----------------------------------------------------------------------------- + W123 (1 info/0 waived) + ----------------------------------------------------------------------------- + Tag : W123 + Description : Please refer to 'SignalUsageReport.rpt' for details of violating bits + Violation : Lint:3610 + Goal : lint_rtl + Module : noc_top + FileName : .//vc_lint0/noc_top/VC_GOAL0/spyglass_reports/lint/SignalUsageReport.rpt + LineNumber : 1 + Statement : # Comment : SignalUsageReport : It dumps details of violating bits of a signal + + ----------------------------------------------------------------------------- + W240 (1 info/0 waived) + ----------------------------------------------------------------------------- + Tag : W240 + Description : Please refer to 'SignalUsageReport.rpt' for details of violating bits + Violation : Lint:3640 + Goal : lint_rtl + Module : noc_top + FileName : .//vc_lint0/noc_top/VC_GOAL0/spyglass_reports/lint/SignalUsageReport.rpt + LineNumber : 1 + Statement : # Comment : SignalUsageReport : It dumps details of violating bits of a signal + + ----------------------------------------------------------------------------- + W241 (1 info/0 waived) + ----------------------------------------------------------------------------- + Tag : W241 + Description : Please refer to 'SignalUsageReport.rpt' for details of violating bits + Violation : Lint:3646 + Goal : lint_rtl + Module : noc_top + FileName : .//vc_lint0/noc_top/VC_GOAL0/spyglass_reports/lint/SignalUsageReport.rpt + LineNumber : 1 + Statement : # Comment : SignalUsageReport : It dumps details of violating bits of a signal diff --git a/mpsoc/Integration_test/VCST/configurations/line4_smart3 b/mpsoc/Integration_test/VCST/configurations/line4_smart3 new file mode 100644 index 0000000..548c123 --- /dev/null +++ b/mpsoc/Integration_test/VCST/configurations/line4_smart3 @@ -0,0 +1,16 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + TOPOLOGY=>"\"LINE\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "1", + "MCAST_ENDP_LIST" => "'b11", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/VCST/run.sh b/mpsoc/Integration_test/VCST/run.sh new file mode 100644 index 0000000..898f19e --- /dev/null +++ b/mpsoc/Integration_test/VCST/run.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) +SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) + +# Source the environment variables +conf_dir="${SCRPT_DIR_PATH}/configurations" +log_dir="${SCRPT_DIR_PATH}/result_logs" +conf_dir="${SCRPT_DIR_PATH}/configurations" +work="${SCRPT_DIR_PATH}/work" +file_list_f="${SCRPT_DIR_PATH}/src/file_list.f" +lint_file="${SCRPT_DIR_PATH}/src/lint.tcl" + +export VCS_ARCH_OVERRIDE=linux + +mkdir -p $work +mkdir -p $log_dir + + +VCST_COMMON_ARGS=" -full64 " + + +vcst_lint () { + conf=$1 + conf_file="${conf_dir}/$conf" + log_file="${log_dir}/${conf}.log" + + if [[ ! -f "$conf_file" ]]; then + echo "Configuration file $conf_file does not exist" + exit 1 + fi + + perl "${SCRPT_DIR_PATH}/src/param_gen.pl" "$conf_file" + export REPORT_FILENAME="${log_dir}/${conf}_vc_static.txt" + export FILE_LIST=$file_list_f + cd work + vc_static_shell ${VCST_COMMON_ARGS} -file ${lint_file} -batch -lic_wait 10 + cd - +} + +for f in "$conf_dir"/*; do + [[ -d "$f" ]] && continue + conf=$(basename "$f") + log_file="${log_dir}/${conf}.log" + echo "▶️ Compiling configuration: $conf" + vcst_lint "$conf" |& tee $log_file + if [[ $? -ne 0 ]]; then + echo "❌ Compilation failed for $conf (check $log_file)" + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + exit 1 + else + echo "✅ Compilation successful for $conf" + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + fi + +done diff --git a/mpsoc/Integration_test/VCST/src/file_list.f b/mpsoc/Integration_test/VCST/src/file_list.f new file mode 100644 index 0000000..a86c752 --- /dev/null +++ b/mpsoc/Integration_test/VCST/src/file_list.f @@ -0,0 +1,6 @@ ++incdir+../src + +-F ../../../rtl/src_noc/noc_filelist.f +-F ../../../rtl/src_topology/custom_flist.f + + diff --git a/mpsoc/Integration_test/VCST/src/lint.tcl b/mpsoc/Integration_test/VCST/src/lint.tcl new file mode 100644 index 0000000..820ad6d --- /dev/null +++ b/mpsoc/Integration_test/VCST/src/lint.tcl @@ -0,0 +1,55 @@ +set script_dir [file dirname [file normalize [info script]]] + +set DESIGN noc_top +set report_filename $::env(REPORT_FILENAME) + +# Waivers: +#sg_read_waiver -file ${script_dir}/waiver.awl +#source ${script_dir}/waiver.tcl + +# Reading Intel linting rules +source $script_dir/lint_rules.tcl + + +# Replace this with the actual path to your .f file +set filelist_path $::env(FILE_LIST) + +# Loop through lines +# File handle and storage +set fp [open $filelist_path r] +while {[gets $fp line] >= 0} { + set line [string trim $line] + + # Skip empty lines and comments + if {$line eq "" || [string match "#*" $line]} { + continue + } + + # Handle +incdir+ + #if {[string match "+incdir+*" $line]} { + # set incdir [string range $line 8 end] + # set_option include_path $incdir + # continue + #} + + # Add source file + lappend names_list $line +} +close $fp + + + +analyze -format sverilog "$names_list" + +elaborate $DESIGN + +#read_sdc $constraints_path + +# Need to add this waiver in here, otherwise is not applicable +#source ${script_dir}/waiver.tcl + +check_lint + +report_lint -verbose -file ${report_filename} +report_lint +exit 0 \ No newline at end of file diff --git a/mpsoc/Integration_test/VCST/src/lint_rules.tcl b/mpsoc/Integration_test/VCST/src/lint_rules.tcl new file mode 100644 index 0000000..90fcaff --- /dev/null +++ b/mpsoc/Integration_test/VCST/src/lint_rules.tcl @@ -0,0 +1,1420 @@ + # Goal: SpyglassConvergedLintSOC + +set saved_sh_continue_on_error [get_app_var sh_continue_on_error] + +set_app_var sh_continue_on_error true + + +configure_lint_tag -enable -tag "badimplicitSM1" -severity Error + +configure_lint_tag -enable -tag "badimplicitSM2" -severity Error + +configure_lint_tag -enable -tag "badimplicitSM4" -severity Error + +configure_lint_tag -enable -tag "BlockHeader" -severity Warning + +configure_lint_tag -enable -tag "bothedges" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.1.6.5" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.3.1.2c" -severity Error + +configure_lint_tag -enable -tag "W421" -severity Error + +configure_lint_tag -enable -tag "W442a" -severity Error + +configure_lint_tag -enable -tag "W442b" -severity Error + +configure_lint_tag -enable -tag "sim_race02" -severity Error + +configure_lint_tag_parameter -tag "sim_race02" -parameter WAIVER_COMPAT -value {W143} + +configure_lint_tag -enable -tag "W110a" -severity Error + +configure_lint_tag -enable -tag "W416" -severity Error + +configure_lint_tag -enable -tag "W416" -type_id SG_LINT_W416_VERILOG_W416_VE_ORDER_DEADCODE -severity Warning + +configure_lint_tag -enable -tag "W416" -type_id SG_LINT_W416_VERILOG_W416_VE_WIDTH_DEADCODE -severity Warning + +configure_lint_tag_parameter -tag "W416" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W416" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W416" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W416" -parameter IGNORE_NONSTATIC_COUNTER -value {yes} + +configure_lint_tag_parameter -tag "W416" -parameter CHECK_COUNTER_ASSIGNMENT -value {yes} + +configure_lint_tag_parameter -tag "W416" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag -enable -tag "PragmaComments-ML" -severity Warning + +configure_lint_tag -enable -tag "STARC05-2.10.2.3" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.11.3.1" -severity Warning + +configure_lint_tag_parameter -tag "STARC05-2.11.3.1" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "STARC05-2.3.1.5b" -severity Error + +configure_lint_tag -enable -tag "W215" -severity Error + +configure_lint_tag -enable -tag "W216" -severity Error + +configure_lint_tag -enable -tag "W289" -severity Error + +configure_lint_tag -enable -tag "W292" -severity Error + +configure_lint_tag -enable -tag "W293" -severity Error + +configure_lint_tag -enable -tag "W317" -severity Error + +configure_lint_tag -enable -tag "W352" -severity Error + +configure_lint_tag -enable -tag "W398" -severity Error + +configure_lint_tag_parameter -tag "W398" -parameter STRICT -value {no} + +configure_lint_tag_parameter -tag "W398" -parameter WAIVER_COMPAT -value {W143} + +configure_lint_tag -enable -tag "W422" -severity Error + +configure_lint_tag -enable -tag "W424" -severity Error + +configure_lint_tag -enable -tag "W425" -severity Error + +configure_lint_tag -enable -tag "W426" -severity Error + +configure_lint_tag -enable -tag "W427" -severity Error + +configure_lint_tag -enable -tag "W428" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.1.2.4" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.1.2.4" -parameter IGNORE_SYSTEM_TASKS -value {yes} + +configure_lint_tag -enable -tag "InterfaceWithoutModport-ML" -severity Error + +configure_lint_tag -enable -tag "W467" -severity Error + +configure_lint_tag_parameter -tag "W467" -parameter IGNORE_PARAM_CASE_CONDITION -value {yes} + +configure_lint_tag -enable -tag "W481a" -severity Error + +configure_lint_tag_parameter -tag "W481a" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W481b" -severity Error + +configure_lint_tag -enable -tag "W496a" -severity Error + +configure_lint_tag -enable -tag "W496b" -severity Error + +configure_lint_tag -enable -tag "W71" -severity Error + +configure_lint_tag_parameter -tag "W71" -parameter CHECK_SEQUENTIAL -value {yes} + +configure_lint_tag_parameter -tag "W71" -parameter STRICT -value {no} + +configure_lint_tag_parameter -tag "W71" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "NoAssignX-ML" -severity Error + +configure_lint_tag_parameter -tag "NoAssignX-ML" -parameter ADD_SIGNATURE_EXPRESSION -value {yes} + +configure_lint_tag_parameter -tag "NoAssignX-ML" -parameter CHECK_ENUM_DECL -value {yes} + +configure_lint_tag_parameter -tag "NoAssignX-ML" -parameter CHECK_XASSIGN_CASEDEFAULT -value {yes} + +configure_lint_tag -enable -tag "ReportPortInfo-ML" -severity Info + +configure_lint_tag -enable -tag "STARC05-2.1.3.1" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.1.3.1" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag -enable -tag "STARC05-2.2.3.3" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.2.3.3" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "STARC05-2.3.1.6" -severity Error + +configure_lint_tag -enable -tag "W116" -severity Error + +configure_lint_tag -enable -tag "W116" -type_id SG_LINT_W116_VERILOG_LINT_W116_DEADCODE -severity Warning + +configure_lint_tag_parameter -tag "W116" -parameter CHECK_COUNTER_ASSIGNMENT -value {yes} + +configure_lint_tag_parameter -tag "W116" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W116" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W116" -parameter IGNORE_NONSTATIC_COUNTER -value {yes} + +configure_lint_tag_parameter -tag "W116" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W116" -parameter REPORTCONSTASSIGN -value {yes} + +configure_lint_tag_parameter -tag "W116" -parameter STRICT -value {no} + +configure_lint_tag_parameter -tag "W116" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W122" -severity Error + +configure_lint_tag_parameter -tag "W122" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W123" -severity Error + +configure_lint_tag -enable -tag "W123" -type_id SG_LINT_W123_VHDL_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag -enable -tag "W123" -type_id SG_LINT_W123_VERILOG_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag_parameter -tag "W123" -parameter CHECKFULLRECORD -value {yes} + +configure_lint_tag_parameter -tag "W123" -parameter HANDLE_LARGE_BUS -value {yes} + +configure_lint_tag_parameter -tag "W123" -parameter IGNOREMODULEINSTANCE -value {yes} + +configure_lint_tag_parameter -tag "W123" -parameter REPORT_STRUCT_NAME_ONLY -value {yes} + +configure_lint_tag_parameter -tag "W123" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W19" -severity Error + +configure_lint_tag_parameter -tag "W19" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W218" -severity Error + +configure_lint_tag -enable -tag "W240" -severity Warning + +configure_lint_tag -enable -tag "W240" -type_id SG_LINT_W240_VERILOG_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag -enable -tag "W240" -type_id SG_LINT_W240_VHDL_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag_parameter -tag "W240" -parameter CHECKFULLRECORD -value {yes} + +configure_lint_tag_parameter -tag "W240" -parameter HANDLE_LARGE_BUS -value {yes} + +configure_lint_tag_parameter -tag "W240" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W263" -severity Error + +configure_lint_tag_parameter -tag "W263" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W263" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W337" -severity Error + +configure_lint_tag_parameter -tag "W337" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W486" -severity Error + +configure_lint_tag -enable -tag "W486" -type_id SG_LINT_W486_VERILOG_W486_VE_DEADCODE -severity Warning + +configure_lint_tag_parameter -tag "W486" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W486" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W486" -parameter PROCESS_COMPLETE_CONDOP -value {yes} + +configure_lint_tag -enable -tag "W499" -severity Error + +configure_lint_tag -enable -tag "W499" -type_id SG_LINT_W499_VERILOG_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag_parameter -tag "W499" -parameter HANDLE_LARGE_BUS -value {yes} + +configure_lint_tag_parameter -tag "W499" -parameter IGNORE_AUTO_FUNCTION_RETURN -value {yes} + +configure_lint_tag -enable -tag "W502" -severity Error + +configure_lint_tag -enable -tag "W505" -severity Error + +configure_lint_tag -enable -tag "W66" -severity Error + +configure_lint_tag -enable -tag "InferLatch" -severity Error + +configure_lint_tag -enable -tag "InferLatch" -type_id SG_OPENMORE_INFERLATCH_VERILOG_INFERLATCH -severity Error + +configure_lint_tag -enable -tag "InferLatch" -type_id SG_OPENMORE_INFERLATCH_MIXED_INFERLATCH -severity Error + +configure_lint_tag -enable -tag "InferLatch" -type_id SG_OPENMORE_INFERLATCH_MIXED_INFERLATCH_FOR_REPORTLATCHHIERARCHY -severity Warning + +configure_lint_tag -enable -tag "InferLatch" -type_id SG_OPENMORE_INFERLATCH_MIXED_INFERLATCH_HL -severity Warning + +configure_lint_tag_parameter -tag "InferLatch" -parameter IGNOREREALLATCH -value {yes} + +configure_lint_tag_parameter -tag "InferLatch" -parameter STRICT -value {no} + +#configure_lint_tag_parameter -tag "InferLatch" -parameter REPORTHANGINGLATCH -value {yes} + +configure_lint_tag -enable -tag "STARC05-2.5.1.7" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.5.1.9" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.10.3.2a" -severity Warning + +configure_lint_tag_parameter -tag "STARC05-2.10.3.2a" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "STARC05-2.10.3.2a" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "STARC05-2.10.3.2a" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag -enable -tag "W336" -severity Error + +configure_lint_tag_parameter -tag "W336" -parameter CHECK_TEMPORARY_FLOP -value {yes} + +configure_lint_tag_parameter -tag "W336" -parameter IGNORECELLNAME -value {ctech_lib_clk_ffb,ctech_lib_clk_ffb_rstb,ctech_lib_clk_divider2,ctech_lib_clk_divider2_rstb} + +configure_lint_tag -enable -tag "W414" -severity Error + +configure_lint_tag -enable -tag "W450L" -severity Error + +configure_lint_tag -enable -tag "UndrivenInTerm-ML" -severity Error + +configure_lint_tag_parameter -tag "UndrivenInTerm-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "UndrivenInTerm-ML" -parameter CHECKRTLCINST -value {yes} + +configure_lint_tag_parameter -tag "UndrivenInTerm-ML" -parameter IGNORERTLBUFFER -value {yes} + +configure_lint_tag_parameter -tag "UndrivenInTerm-ML" -parameter IGNORE_DELIBERATELY_UNCONNECTED -value {yes} + +configure_lint_tag_parameter -tag "UndrivenInTerm-ML" -parameter IGNORE_UNUSED_FLOP -value {yes} + +configure_lint_tag -enable -tag "CombLoop" -severity Error + +configure_lint_tag -enable -tag "CombLoop" -type_id SG_OPENMORE_COMBLOOP_MIXED_COMBLOOP_MORE_LATCH -severity Warning + +configure_lint_tag -enable -tag "CombLoop" -type_id SG_OPENMORE_COMBLOOP_MIXED_COMBLOOPRPT -severity Info + +configure_lint_tag_parameter -tag "CombLoop" -parameter ALLVIOL -value {yes} + +configure_lint_tag_parameter -tag "CombLoop" -parameter ENABLEE2Q -value {yes} + +configure_lint_tag_parameter -tag "CombLoop" -parameter ENABLE_LATCH_BASED_CLUSTERS -value {yes} + +configure_lint_tag_parameter -tag "CombLoop" -parameter IGNORE_INTERNAL_LOOPS -value {yes} + +configure_lint_tag_parameter -tag "CombLoop" -parameter REPORT_FLOP_RESET_LOOP -value {yes} + +configure_lint_tag_parameter -tag "CombLoop" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "FlopClockConstant" -severity Error + +configure_lint_tag_parameter -tag "FlopClockConstant" -parameter ALLVIOL -value {yes} + +configure_lint_tag_parameter -tag "FlopClockConstant" -parameter IGNORE_HANGING_FLOP -value {yes} + +configure_lint_tag_parameter -tag "FlopClockConstant" -parameter REPORT_CONST_CONNECT -value {yes} + +configure_lint_tag_parameter -tag "FlopClockConstant" -parameter REPORT_INFERRED_CELL -value {yes} + +#configure_lint_tag_parameter -tag "FlopClockConstant" -parameter REPORT_IMMEDIATE_SRC -value {yes} + +configure_lint_tag -enable -tag "FlopEConst" -severity Error + +configure_lint_tag_parameter -tag "FlopEConst" -parameter ALLVIOL -value {yes} + +configure_lint_tag_parameter -tag "FlopEConst" -parameter IGNORE_HANGING_FLOP -value {yes} + +configure_lint_tag_parameter -tag "FlopEConst" -parameter REPORT_CONST_CONNECT -value {yes} + +configure_lint_tag_parameter -tag "FlopEConst" -parameter REPORT_INFERRED_CELL -value {yes} + +#configure_lint_tag_parameter -tag "FlopEConst" -parameter REPORT_IMMEDIATE_SRC -value {yes} + +configure_lint_tag -enable -tag "FlopSRConst" -severity Error + +configure_lint_tag_parameter -tag "FlopSRConst" -parameter ALLVIOL -value {yes} + +configure_lint_tag_parameter -tag "FlopSRConst" -parameter IGNORE_HANGING_FLOP -value {yes} + +configure_lint_tag_parameter -tag "FlopSRConst" -parameter REPORT_INFERRED_CELL -value {yes} + +#configure_lint_tag_parameter -tag "FlopSRConst" -parameter REPORT_IMMEDIATE_SRC -value {yes} + +configure_lint_tag -enable -tag "LatchFeedback" -severity Warning + +configure_lint_tag -enable -tag "STARC05-1.2.1.2" -severity Error + +configure_lint_tag -enable -tag "STARC05-1.4.3.4" -severity Error + +configure_lint_tag_parameter -tag "STARC05-1.4.3.4" -parameter REPORT_ALLCLK -value {no} + +configure_lint_tag_parameter -tag "STARC05-1.4.3.4" -parameter REPORT_ALLCLK_OPTIMIZED -value {no} + +configure_lint_tag -enable -tag "STARC05-2.1.4.5" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.4.1.5" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.4.1.5" -parameter IGNORE_MUX_CELL -value {yes} + +configure_lint_tag_parameter -tag "STARC05-2.4.1.5" -parameter COMBO_DEPTH -value {1} + +configure_lint_tag -enable -tag "STARC05-2.5.1.2" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.5.1.2" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W415" -severity Error + +configure_lint_tag -enable -tag "W415" -type_id SG_LINT_W415_MIXED_W415RPT -severity Info + +configure_lint_tag_parameter -tag "W415" -parameter ASSUME_DRIVER_LOAD -value {yes} + +configure_lint_tag_parameter -tag "W415" -parameter CHECKCONSTASSIGN -value {yes} + +configure_lint_tag_parameter -tag "W415" -parameter HANDLE_EQUIVALENT_DRIVERS -value {yes} + +configure_lint_tag_parameter -tag "W415" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "STARC05-2.10.1.4a" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.10.1.4a" -parameter CHECK_ANY_BIT_FOR_XZ -value {yes} + +configure_lint_tag_parameter -tag "STARC05-2.10.1.4a" -parameter IGNORE_QMARK -value {yes} + +configure_lint_tag -enable -tag "STARC05-2.10.1.4b" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.10.1.4b" -parameter IGNORE_CASE_COMPARE_OP -value {1} + +configure_lint_tag -enable -tag "W156" -severity Warning + +configure_lint_tag_parameter -tag "W156" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "STARC05-2.3.3.1" -severity Error + +configure_lint_tag -enable -tag "W287b" -severity Warning + +configure_lint_tag -enable -tag "W224" -severity Error + +configure_lint_tag_parameter -tag "W224" -parameter USE_NATURAL_WIDTH -value {yes} + +configure_lint_tag_parameter -tag "W224" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W287a" -severity Warning + +configure_lint_tag_parameter -tag "W287a" -parameter STRICT -value {no} + +configure_lint_tag_parameter -tag "W287a" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "mixedsenselist" -severity Warning + +configure_lint_tag -enable -tag "W339a" -severity Error + +configure_lint_tag -enable -tag "W430" -severity Warning + +configure_lint_tag -enable -tag "W257" -severity Error + +configure_lint_tag_parameter -tag "W257" -parameter ALLVIOL -value {yes} + +configure_lint_tag -enable -tag "W294" -severity Error + +configure_lint_tag -enable -tag "NoStrengthInput-ML" -severity Error + +configure_lint_tag -enable -tag "STARC05-3.2.4.3" -severity Error + +configure_lint_tag -enable -tag "W182g" -severity Error + +configure_lint_tag -enable -tag "W182h" -severity Error + +configure_lint_tag -enable -tag "W182k" -severity Error + +configure_lint_tag -enable -tag "W182n" -severity Error + +configure_lint_tag -enable -tag "W213" -severity Error + +configure_lint_tag_parameter -tag "W213" -parameter IGNORE_PLI_TASKS_AND_FUNCTIONS -value {display,info,warning,error,fatal} + +configure_lint_tag -enable -tag "1490" -severity Error + +configure_lint_tag -enable -tag "1492" -severity Error + +configure_lint_tag -enable -tag "2082" -severity Error + +configure_lint_tag -enable -tag "02041" -severity Error + +configure_lint_tag_parameter -tag "02041" -parameter CHECK_DECL_IN_FUNC -value {yes} + +configure_lint_tag -enable -tag "UnrecSynthDir-ML" -severity Warning + +configure_lint_tag_parameter -tag "UnrecSynthDir-ML" -parameter CHECK_ALL_PRAGMAS -value {yes} + +configure_lint_tag -enable -tag "W495" -severity Warning + +configure_lint_tag_parameter -tag "W495" -parameter HANDLE_LARGE_BUS -value {yes} + +configure_lint_tag -enable -tag "W120" -severity Warning + +configure_lint_tag -enable -tag "W120" -type_id SG_LINT_W120_VHDL_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag -enable -tag "W120" -type_id SG_LINT_W120_VERILOG_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag_parameter -tag "W120" -parameter CHECKFULLRECORD -value {yes} + +configure_lint_tag_parameter -tag "W120" -parameter HANDLE_LARGE_BUS -value {yes} + +configure_lint_tag_parameter -tag "W120" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W241" -severity Warning + +configure_lint_tag -enable -tag "W241" -type_id SG_LINT_W241_VERILOG_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag -enable -tag "W241" -type_id SG_LINT_W241_VHDL_SIGNALUSAGEREPORT_REFER -severity Info + +configure_lint_tag_parameter -tag "W241" -parameter HANDLE_LARGE_BUS -value {yes} + +configure_lint_tag -enable -tag "W494" -severity Warning + +configure_lint_tag_parameter -tag "W494" -parameter CHKTOPMODULE -value {yes} + +configure_lint_tag_parameter -tag "W494" -parameter HANDLE_LARGE_BUS -value {yes} + +configure_lint_tag_parameter -tag "W494" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "UnloadedOutTerm-ML" -severity Warning + +configure_lint_tag_parameter -tag "UnloadedOutTerm-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "UnloadedOutTerm-ML" -parameter IGNORERTLBUFFER -value {yes} + +configure_lint_tag_parameter -tag "UnloadedOutTerm-ML" -parameter IGNORE_DELIBERATELY_UNCONNECTED -value {yes} + +configure_lint_tag -enable -tag "UnloadedInPort-ML" -severity Warning + +configure_lint_tag_parameter -tag "UnloadedInPort-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "UnloadedInPort-ML" -parameter IGNORERTLBUFFER -value {yes} + +configure_lint_tag -enable -tag "UndrivenOutPort-ML" -severity Error + +configure_lint_tag_parameter -tag "UndrivenOutPort-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "UndrivenOutPort-ML" -parameter IGNORERTLBUFFER -value {yes} + +configure_lint_tag -enable -tag "UndrivenNUnloaded-ML" -severity Warning + +configure_lint_tag_parameter -tag "UndrivenNUnloaded-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "UndrivenNUnloaded-ML" -parameter IGNORERTLBUFFER -value {yes} + +configure_lint_tag -enable -tag "UndrivenOutTermNLoaded-ML" -severity Error + +configure_lint_tag_parameter -tag "UndrivenOutTermNLoaded-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag -enable -tag "UnloadedNet-ML" -severity Warning + +configure_lint_tag_parameter -tag "UnloadedNet-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "UnloadedNet-ML" -parameter IGNORERTLBUFFER -value {yes} + +configure_lint_tag -enable -tag "LatchEnableConstant" -severity Error + +#configure_lint_tag_parameter -tag "LatchEnableConstant" -parameter REPORT_IMMEDIATE_SRC -value {yes} + +configure_lint_tag_parameter -tag "LatchEnableConstant" -parameter ALLVIOL -value {yes} + +configure_lint_tag -enable -tag "LatchEnableUndriven" -severity Error + +configure_lint_tag_parameter -tag "LatchEnableUndriven" -parameter ALLVIOL -value {yes} + +configure_lint_tag_parameter -tag "W210" -parameter SET_MESSAGE_SEVERITY -value {yes} + +configure_lint_tag -enable -tag "W210" -type_id SG_LINT_W210_VHDL_MISSING_PORT_ERROR -severity Error + +configure_lint_tag -enable -tag "W210" -type_id SG_LINT_W210_VERILOG_MISSING_PORT_ERROR -severity Error + +configure_lint_tag -enable -tag "W210" -type_id SG_LINT_W210_VHDL_MISSING_PORT_WARNING -severity Warning + +configure_lint_tag -enable -tag "W210" -type_id SG_LINT_W210_VERILOG_MISSING_PORT_WARNING -severity Warning + +configure_lint_tag -enable -tag "60004" -severity Error + +configure_lint_tag -enable -tag "60006" -severity Error + +configure_lint_tag -enable -tag "UndrivenNet-ML" -severity Warning + +configure_lint_tag_parameter -tag "UndrivenNet-ML" -parameter CHECKINHIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "UndrivenNet-ML" -parameter IGNORERTLBUFFER -value {yes} + +configure_lint_tag_parameter -tag "UndrivenNet-ML" -parameter IGNORE_UNUSED_FLOP -value {yes} + +configure_lint_tag -enable -tag "NoExprInPort-ML" -severity Info + +configure_lint_tag_parameter -tag "NoExprInPort-ML" -parameter CHECKGATEINST -value {yes} + +configure_lint_tag_parameter -tag "NoExprInPort-ML" -parameter IGNOREINVERSIONOPERATION -value {yes} + +configure_lint_tag -enable -tag "NamedAssoc" -severity Error + +configure_lint_tag -enable -tag "AssignPatInInst-ML" -severity Error + +configure_lint_tag -enable -tag "60013" -severity Error + +configure_lint_tag_parameter -tag "60013" -parameter PERMIT_SIMILAR_NAMES_AMONGST_DIFFERENT_OBJECT_TYPES -value {1} + +configure_lint_tag -enable -tag "ParamName" -severity Warning + +configure_lint_tag_parameter -tag "ParamName" -parameter PARAMNAME -value {/^[A-Z][0-9A-Z]*/ and not /[a-z]/} + +configure_lint_tag -enable -tag "SigName" -severity Warning + +configure_lint_tag_parameter -tag "SigName" -parameter PRINT_RECOMMENDED_REGEXP -value {yes} + +configure_lint_tag_parameter -tag "SigName" -parameter SIGNAME -value {/^[a-zA-Z]([a-zA-Z0-9_])*$/ and /^.{1,1024}$/ and not /__/} + +configure_lint_tag -enable -tag "PortName" -severity Warning + +configure_lint_tag_parameter -tag "PortName" -parameter IGNORE_FILE -value {.*\.binc\.vs|.*\.tinc\.vs|.*\.ports\.v} + +configure_lint_tag_parameter -tag "PortName" -parameter PORTNAME -value {/^[a-zA-Z]([a-zA-Z0-9_])*$/ and /^.{1,128}$/ and not /__/} + +configure_lint_tag_parameter -tag "PortName" -parameter PRINT_RECOMMENDED_REGEXP -value {yes} + +configure_lint_tag -enable -tag "VarName" -severity Warning + +configure_lint_tag_parameter -tag "VarName" -parameter PRINT_RECOMMENDED_REGEXP -value {yes} + +configure_lint_tag_parameter -tag "VarName" -parameter VARNAME -value {/^[a-zA-Z]([a-zA-Z0-9_])*$/ and /^.{1,1024}$/ and not /__/} + +configure_lint_tag -enable -tag "ConstName" -severity Warning + +configure_lint_tag_parameter -tag "ConstName" -parameter CONSTNAME -value {/^[A-Z][A-Z0-9_]*$/} + +configure_lint_tag_parameter -tag "ConstName" -parameter PRINT_RECOMMENDED_REGEXP -value {yes} + +configure_lint_tag -enable -tag "W121" -severity Error + +configure_lint_tag_parameter -tag "W121" -parameter IGNORE_MACRO_TO_NONMACRO -value {yes} + +configure_lint_tag_parameter -tag "W121" -parameter LIMIT_TASK_FUNCTION_SCOPE -value {yes} + +configure_lint_tag_parameter -tag "W121" -parameter WAIVER_COMPAT -value {W143} + +configure_lint_tag -enable -tag "STARC05-1.1.1.2" -severity Warning + +configure_lint_tag_parameter -tag "STARC05-1.1.1.2" -parameter IGNORE_FILE -value {.*\.binc\.vs|.*\.tinc\.vs|.*\.ports\.v} + +configure_lint_tag_parameter -tag "STARC05-1.1.1.2" -parameter REPORT_TYPEDEF -value {yes} + +configure_lint_tag -enable -tag "STARC05-1.1.1.3" -severity Error + +configure_lint_tag_parameter -tag "STARC05-1.1.1.3" -parameter DISABLE_VHDL_KEYWORDS -value {yes} + +configure_lint_tag -enable -tag "60117" -severity Error + +configure_lint_tag_parameter -tag "60117" -parameter REGEXP_FORBIDDEN_MACROS -value {^((?:LS_\w*)$|ISO_(HIGH|LOW)|AND_ISO|EPG).*} + +configure_lint_tag -enable -tag "60010" -severity Error + +configure_lint_tag_parameter -tag "60010" -parameter REPORT_OBJECT_TYPES -value {net,port,variable,struct,union,enum,typedef,userdefined} + +configure_lint_tag_parameter -tag "60010" -parameter KEYWORDS -value {^semaphore$ ^gnd$ ^above$ ^abs$ ^absdelay$ ^acos$ ^acosh$ ^ac_stim$ ^aliasparam$ ^analog$ ^analysis$ ^asin$ ^asinh$ ^atan$ ^atan2$ ^atanh$ ^branch$ ^ceil$ ^connectrules$ ^cos$ ^cosh$ ^ddt$ ^ddx$ ^discipline$ ^driver_update$ ^enddiscipline$ ^endconnectrules$ ^exclude$ ^exp$ ^final_step$ ^flicker_noise$ ^floor$ ^flow$ ^from$ ^ground$ ^hypot$ ^idt$ ^idtmod$ ^inf$ ^initial_step$ ^laplace_nd$ ^laplace_np$ ^laplace_zd$ ^laplace_zp$ ^last_crossing$ ^limexp$ ^ln$ ^log$ ^max$ ^min$ ^nature$ ^net_resolution$ ^noise_table$ ^paramset$ ^potential$ ^pow$ ^pulldown$ ^sin$ ^sinh$ ^slew$ ^tan$ ^tanh$ ^timer$ ^transition$ ^white_noise$ ^wreal$ ^zi_nd$ ^zi_np$ ^zi_zd$ ^VCC ^vcc ^VDD ^vdd ^VSS ^vss} + +configure_lint_tag -enable -tag "AlwaysEnabledCG" -severity Error + +configure_lint_tag -enable -tag "AlwaysDisabledCG" -severity Error + +configure_lint_tag -enable -tag "FewSeqOnCG" -severity Warning + +configure_lint_tag -enable -tag "54005" -severity Error + +configure_lint_tag_parameter -tag "54005" -parameter BIST_CMP_REGEX -value {.*BIST_CMP.*} + +configure_lint_tag_parameter -tag "54005" -parameter BIST_REN_REGEX -value {.*BIST_REN.*} + +configure_lint_tag_parameter -tag "54005" -parameter ENABLE_SANITY_CHECK -value {1} + +configure_lint_tag_parameter -tag "54005" -parameter EXCLUDE_REGEX -value {.*ungated.*|.*fwls.*|.*dfx_mbist.*} + +configure_lint_tag -enable -tag "54006" -severity Error + +configure_lint_tag_parameter -tag "54006" -parameter EXCLUDE_REGEX -value {.*ungated.*|.*fwls.*|.*dfx_mbist.*} + +configure_lint_tag -enable -tag "54007" -severity Error + +configure_lint_tag_parameter -tag "54007" -parameter EXCLUDE_REGEX -value {.*ungated.*|.*fwls.*|.*dfx_mbist.*} + +configure_lint_tag -enable -tag "54009" -severity Error + +configure_lint_tag -enable -tag "60701" -severity Error + +configure_lint_tag_parameter -tag "60701" -parameter MODULES_REGEXP -value {^(b12.*|d04.*|b05.*|b14.*|b15.*|cc0.*|ec0.*|e05.*|yc8.*|fa0.*|f05.*)} + +configure_lint_tag -enable -tag "60152" -severity Error + +configure_lint_tag_parameter -tag "60152" -parameter PATTERN_REGEXP -value {(.*ctech.*|.*_macro_tech_map\.vh$)} + +configure_lint_tag -enable -tag "60702" -severity Error + +configure_lint_tag_parameter -tag "60702" -parameter CTECH_LIB_REGEXP -value {^ctech_lib.*|^Ctech_lib.*} + +configure_lint_tag_parameter -tag "60702" -parameter MAP_FILE_REGEXP -value {(\w+)_map\.(v|sv)$} + +configure_lint_tag -enable -tag "60703" -severity Error + +configure_lint_tag_parameter -tag "60703" -parameter CTECH_LIB_REGEXP -value {^ctech_lib.*|^Ctech_lib.*} + +configure_lint_tag_parameter -tag "60703" -parameter MAP_FILE_REGEXP -value {(\w+)_map\.(v|sv)$} + +configure_lint_tag -enable -tag "60704" -severity Info + +configure_lint_tag_parameter -tag "60704" -parameter CTECH_LIB_REGEXP -value {^ctech_lib.*|^Ctech_lib.*} + +configure_lint_tag_parameter -tag "60704" -parameter MAP_FILE_REGEXP -value {(\w+)_map\.(v|sv)$} + +configure_lint_tag -enable -tag "60706" -severity Error + +configure_lint_tag_parameter -tag "60706" -parameter CTECH_LIB_REGEXP -value {^ctech_lib.*|^Ctech_lib.*} + +configure_lint_tag_parameter -tag "60706" -parameter EXCLUDE_FILE -value {/nfs/site/disks/hdk_.*|/nfs/site/proj/tech1/.*} + +configure_lint_tag_parameter -tag "60706" -parameter EXCLUDE_PATH -value {/p/hdk/cad/ctech/.*|/nfs/site/disks/crt_tools.*|/nfs/site/disks/.crt_tools.*|/nfs/site/disks/hdk.cad.*|/nfs/site/disks/hdk_stdroot.*|/p/hdk/cad/stdcells/.*|/nfs/site/disks/crt_stdcells.*} + +configure_lint_tag_parameter -tag "60706" -parameter MAP_FILE_REGEXP -value {(\w+)_map\.(v|sv)$} + +configure_lint_tag -enable -tag "70600" -severity Error + +configure_lint_tag_parameter -tag "70600" -parameter DFT_ARRAYMODULES_REGEXP -value {.*dfx_wrapper|.*MSWT_WRP} + +configure_lint_tag_parameter -tag "70600" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70600" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70601" -severity Error + +configure_lint_tag_parameter -tag "70601" -parameter VISA_INPUT_PORT2_CHECKREGEXP -value {lane_in} + +configure_lint_tag_parameter -tag "70601" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70601" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag_parameter -tag "70601" -parameter REPORT_OVERLAPPING_PATHS -value {yes} + +configure_lint_tag -enable -tag "70602" -severity Error + +configure_lint_tag_parameter -tag "70602" -parameter VISA_INPUT_PORT2_CHECKREGEXP -value {lane_in} + +configure_lint_tag_parameter -tag "70602" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70602" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag_parameter -tag "70602" -parameter REPORT_OVERLAPPING_PATHS -value {no} + +configure_lint_tag -enable -tag "70603" -severity Error + +configure_lint_tag_parameter -tag "70603" -parameter VISA_INPUT_PORT2_CHECKREGEXP -value {lane_in} + +configure_lint_tag_parameter -tag "70603" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70603" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag_parameter -tag "70603" -parameter REPORT_OVERLAPPING_PATHS -value {yes} + +configure_lint_tag -enable -tag "70604" -severity Warning + +configure_lint_tag_parameter -tag "70604" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70604" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70605" -severity Info + +configure_lint_tag_parameter -tag "70605" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70605" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70605_Info" -severity Info + +configure_lint_tag_parameter -tag "70605_Info" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70605_Info" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70606" -severity Error + +configure_lint_tag_parameter -tag "70606" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70606" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag_parameter -tag "70606" -parameter REPORT_OVERLAPPING_PATHS -value {yes} + +configure_lint_tag -enable -tag "70607" -severity Warning + +configure_lint_tag_parameter -tag "70607" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70607" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70608" -severity Error + +configure_lint_tag_parameter -tag "70608" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70608" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70609" -severity Error + +configure_lint_tag_parameter -tag "70609" -parameter STAY_EMPTY_PORTNAME -value {.*xbar_out} + +configure_lint_tag_parameter -tag "70609" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70609" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70610" -severity Error + +configure_lint_tag_parameter -tag "70610" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70610" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70611" -severity Error + +configure_lint_tag_parameter -tag "70611" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70611" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag -enable -tag "70612" -severity Error + +configure_lint_tag_parameter -tag "70612" -parameter VISA_CONFIG_INPUTPIN -value {serial_cfg_in.*} + +configure_lint_tag_parameter -tag "70612" -parameter VISA_CONFIG_OUTPUTPIN -value {serial_cfg_out.*} + +configure_lint_tag_parameter -tag "70612" -parameter VISA_MODULES_REGEXP -value {visa_(iomapper|unit|partition|repeater|central)_[0-9a-z_]+} + +configure_lint_tag_parameter -tag "70612" -parameter VISA_MODULES_TO_IGNORE -value {visa_clk_mux,visa_mux_stage,visa_lane_mux,visa_lane_mux_slider} + +configure_lint_tag_parameter -tag "70612" -parameter REPORT_OVERLAPPING_PATHS -value {yes} + +configure_lint_tag -enable -tag "68801" -severity Error + +configure_lint_tag -enable -tag "InvalidAutoAssign" -severity Error + +configure_lint_tag -enable -tag "68803" -severity Error + +configure_lint_tag -enable -tag "68804" -severity Error + +configure_lint_tag -enable -tag "68805" -severity Error + +configure_lint_tag -enable -tag "00843" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.2.2.2b" -severity Error + +configure_lint_tag -enable -tag "SensListRepeat-ML" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.2.2.3a" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.2.2.3a" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W164a_a" -severity Error + +configure_lint_tag -enable -tag "W164a_a" -type_id SG_LINT_W164A_A_VERILOG_ASSIGN_WIDTH_MISMATCH_DEADCODE -severity Warning + +configure_lint_tag -enable -tag "W164a_a" -type_id SG_LINT_W164A_A_VERILOG_ASSIGN_WIDTH_MISMATCH_NBA_DEADCODE -severity Warning + +configure_lint_tag -enable -tag "W164a_a" -type_id SG_LINT_W164A_A_VERILOG_CONCAT_ASSIGN_WIDTH_MISMATCH_DEADCODE -severity Warning + +configure_lint_tag -enable -tag "W164a_a" -type_id SG_LINT_W164A_A_VERILOG_CONCAT_ASSIGN_WIDTH_MISMATCH_NBA_DEADCODE -severity Warning + +configure_lint_tag -enable -tag "W164a_a" -type_id SG_LINT_W164A_A_VERILOG_PACKED_CONCAT_ASSIGN_WIDTH_MISMATCH_DEADCODE -severity Warning + +configure_lint_tag -enable -tag "W164a_a" -type_id SG_LINT_W164A_A_VERILOG_PACKED_CONCAT_ASSIGN_WIDTH_MISMATCH_NBA_DEADCODE -severity Warning + +configure_lint_tag -enable -tag "W164a_a" -type_id SG_LINT_W164A_A_VERILOG_W164_SS_DEADCODE -severity Warning + +configure_lint_tag_parameter -tag "W164a_a" -parameter CHECK_NATURAL_WIDTH_OF_MULTIPLICATION -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter CONCAT_WIDTH_NF -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter HANDLE_LRM_PARAM_IN_SHIFT -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter HANDLE_SHIFT_OP -value {shift_both} + +configure_lint_tag_parameter -tag "W164a_a" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W164a_a" -parameter PROCESS_COMPLETE_CONDOP -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter STRICT -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter TREAT_CONCAT_ASSIGN_SEPARATELY -value {yes} + +configure_lint_tag_parameter -tag "W164a_a" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W164a_b" -severity Warning + +configure_lint_tag_parameter -tag "W164a_b" -parameter CHECK_COUNTER_ASSIGNMENT -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter CHECK_NATURAL_WIDTH_OF_MULTIPLICATION -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter CONCAT_WIDTH_NF -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter HANDLE_LRM_PARAM_IN_SHIFT -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter HANDLE_SHIFT_OP -value {shift_both} + +configure_lint_tag_parameter -tag "W164a_b" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W164a_b" -parameter PROCESS_COMPLETE_CONDOP -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter STRICT -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter TREAT_CONCAT_ASSIGN_SEPARATELY -value {yes} + +configure_lint_tag_parameter -tag "W164a_b" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W164b_a" -severity Error + +configure_lint_tag_parameter -tag "W164b_a" -parameter CHECK_NATURAL_WIDTH_OF_MULTIPLICATION -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter CONCAT_WIDTH_NF -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter HANDLE_LRM_PARAM_IN_SHIFT -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter HANDLE_SHIFT_OP -value {shift_left} + +configure_lint_tag_parameter -tag "W164b_a" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W164b_a" -parameter PROCESS_COMPLETE_CONDOP -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter STRICT -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter TREAT_CONCAT_ASSIGN_SEPARATELY -value {yes} + +configure_lint_tag_parameter -tag "W164b_a" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W164b_b" -severity Warning + +configure_lint_tag_parameter -tag "W164b_b" -parameter CHECK_NATURAL_WIDTH_OF_MULTIPLICATION -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter HANDLE_LRM_PARAM_IN_SHIFT -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter HANDLE_SHIFT_OP -value {shift_left} + +configure_lint_tag_parameter -tag "W164b_b" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W164b_b" -parameter PROCESS_COMPLETE_CONDOP -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter STRICT -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter TREAT_CONCAT_ASSIGN_SEPARATELY -value {yes} + +configure_lint_tag_parameter -tag "W164b_b" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W362a" -severity Error + +configure_lint_tag_parameter -tag "W362a" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W362a" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W362a" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W362a" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W362a" -parameter STRICT -value {yes} + +configure_lint_tag_parameter -tag "W362a" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W362b" -severity Error + +configure_lint_tag_parameter -tag "W362b" -parameter CHECK_STATIC_VALUE -value {yes} + +configure_lint_tag_parameter -tag "W362b" -parameter ENABLE_RTL_DEADCODE -value {yes} + +configure_lint_tag_parameter -tag "W362b" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W362b" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "W362b" -parameter STRICT -value {yes} + +configure_lint_tag_parameter -tag "W362b" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag_parameter -tag "W110_a" -parameter HANDLE_SHIFT_OP -value {shift_both} + +configure_lint_tag_parameter -tag "W110_a" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W110_a" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag -enable -tag "W110_b" -severity Error + +configure_lint_tag_parameter -tag "W110_b" -parameter HANDLE_SHIFT_OP -value {shift_both} + +configure_lint_tag_parameter -tag "W110_b" -parameter HANDLE_ZERO_PADDING -value {yes} + +configure_lint_tag_parameter -tag "W110_b" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag -enable -tag "W348" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.10.3.7" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.10.3.7" -parameter IGNORE_BASED_WIDTH -value {yes} + +configure_lint_tag_parameter -tag "STARC05-2.10.3.7" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "STARC05-2.10.3.6" -severity Error + +configure_lint_tag_parameter -tag "STARC05-2.10.3.6" -parameter BITWIDTH_BASEDCONST -value {32} + +configure_lint_tag_parameter -tag "STARC05-2.10.3.6" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "STARC05-1.4.3.1a" -severity Warning + +configure_lint_tag_parameter -tag "STARC05-1.4.3.1a" -parameter IGNORECELLNAME -value {ctech_lib_clk_ffb,ctech_lib_clk_ffb_rstb,ctech_lib_clk_divider2,ctech_lib_clk_divider2_rstb} + +configure_lint_tag_parameter -tag "STARC05-1.4.3.1a" -parameter IGNOREMODNAME -value {ctech_lib_clk.*} + +configure_lint_tag -enable -tag "STARC05-1.4.3.1b" -severity Warning + +configure_lint_tag_parameter -tag "STARC05-1.4.3.1b" -parameter IGNORECELLNAME -value {ctech_lib_clk_ffb,ctech_lib_clk_ffb_rstb,ctech_lib_clk_divider2,ctech_lib_clk_divider2_rstb} + +configure_lint_tag_parameter -tag "STARC05-1.4.3.1b" -parameter IGNOREMODNAME -value {ctech_lib_clk.*} + +configure_lint_tag -enable -tag "FlopClockUndriven" -severity Error + +configure_lint_tag_parameter -tag "FlopClockUndriven" -parameter ALLVIOL -value {yes} + +#configure_lint_tag -enable -tag "ClockEnableRace" -severity Warning + +#configure_lint_tag_parameter -tag "ClockEnableRace" -parameter CHECKCOMBLOGIC -value {yes} + +#configure_lint_tag_parameter -tag "ClockEnableRace" -parameter IGNORE_HANGING_FLOP -value {yes} + +#configure_lint_tag_parameter -tag "ClockEnableRace" -parameter REPORT_COMMON_SOURCE -value {yes} + +configure_lint_tag -enable -tag "sim_race07" -severity Error + +configure_lint_tag -enable -tag "sim_race04" -severity Error + +#configure_lint_tag -enable -tag "clock_used_as_data" -severity Warning + +#configure_lint_tag_parameter -tag "clock_used_as_data" -parameter ALLVIOL -value {yes} + +configure_lint_tag -enable -tag "70094" -severity Error + +configure_lint_tag_parameter -tag "70094" -parameter CHECKSEQPHASE -value {yes} + +configure_lint_tag -enable -tag "W193" -severity Error + +configure_lint_tag_parameter -tag "W193" -parameter REPORT_IF_BLOCKS_ONLY -value {yes} + +configure_lint_tag -enable -tag "IfWithoutElse-ML" -severity Error + +configure_lint_tag_parameter -tag "IfWithoutElse-ML" -parameter IGNOREREALLATCH -value {yes} + +configure_lint_tag_parameter -tag "IfWithoutElse-ML" -parameter IGNORE_LOOP_INDEX -value {yes} + +configure_lint_tag_parameter -tag "IfWithoutElse-ML" -parameter IGNORE_STATIC_CONDITION -value {yes} + +configure_lint_tag -enable -tag "AlwaysFalseTrueCond-ML" -type_id SG_MORELINT_ALWAYSFALSETRUECOND_ML_VERILOG_ALWAYSFALSETRUECOND_ML_VE -severity Error + +configure_lint_tag -enable -tag "AlwaysFalseTrueCond-ML" -type_id SG_MORELINT_ALWAYSFALSETRUECOND_ML_VERILOG_ALWAYSFALSETRUECOND_ML_VE_1 -severity Warning + +configure_lint_tag_parameter -tag "AlwaysFalseTrueCond-ML" -parameter EVALUATE_FOR_LOOP_INDEX -value {yes} + +configure_lint_tag_parameter -tag "AlwaysFalseTrueCond-ML" -parameter IGNORE_COND_HAVING_IDENTIFIER -value {yes} + +configure_lint_tag_parameter -tag "AlwaysFalseTrueCond-ML" -parameter REPORT_ALWAYS_COND -value {false} + +configure_lint_tag_parameter -tag "AlwaysFalseTrueCond-ML" -parameter REPORT_LESS_SEVERITY -value {yes} + +configure_lint_tag -enable -tag "W527" -severity Warning + +configure_lint_tag -enable -tag "60000_a" -severity Error + +configure_lint_tag_parameter -tag "60000_a" -parameter CHECK_OUTPUT_PORTS -value {yes} + +#configure_lint_tag_parameter -tag "60000_a" -parameter IGNORE_FUNCTION_INITIALIZATION -value {yes} + +configure_lint_tag -enable -tag "NullPort-ML" -severity Error + +configure_lint_tag -enable -tag "W192" -severity Warning + +configure_lint_tag -enable -tag "2218" -severity Error + +configure_lint_tag -enable -tag "50520" -severity Error + +configure_lint_tag_parameter -tag "50520" -parameter IFDEFS -value {SVA_OFF,VCSSIM,INST_ON,DC,SYNTHESIS,VCS,FGPA,QUICKCOV_INST_ENABLE,QC_COVER_ENABLE,MANUAL_XPROP,ASSERT_OFF,ASSERT_ON,SIMULATION,XPROPAGATION,HIPS_PS_RESOLUTION,PULSE_WIDTH_OFF,no_unit_delay,VCS_BUG,LINTRA_BUG,SPYGLASS_BUG,QUESTACDC_BUG,DC_BUG,VELOCE_BUG,ZEBU_BUG,FISHTAIL_BUG,FEV_BUG,SYNPLICITY_BUG,POWERARTIST_BUG,VERDI_BUG,JASPERGOLD_BUG,EMULATION,NO_PWR_PINS,JEM_STANDALONE,JEM_USE_DPI_ENABLING,SLA_RTL_TLM_PORTS_OFF,SLA_RTL_TLM_MONITOR_INST_OFF,SLA_EXTERNAL_RTL_TLM_IMPL,JEM_TLM_PORTS_OFF,JEM_NO_CDT_DPI,JEM_NO_DPI_IN_INITIAL,JEM_INIT_CLK,JEM_INIT_CLK_EDGE,JEM_TLM_PORT_ENABLE_INIT_STATE,JEM_EMILATION_ZSE,JEM_COV_SAMPLE_CLK,QUICKCOV_JEM_COLLECTION,OVM,UVM,SNPS201412B} + +configure_lint_tag -enable -tag "52544" -severity Error + +configure_lint_tag -enable -tag "ExprParen" -severity Error + +configure_lint_tag_parameter -tag "ExprParen" -parameter ALLOWEDOPPRECEDENCE -value {(a + b * c)(a - b * c)(a + b / c)(a - b / c)(a - b + c)(a * b / c)(a - b - c)(a + b + c)(a * b * c)(a / b/ c)(!a)(~a)(a & b & c)(a | b | c)} + +configure_lint_tag_parameter -tag "ExprParen" -parameter DISPLAYEXPRESSION -value {yes} + +configure_lint_tag_parameter -tag "ExprParen" -parameter IGNORE_MODULE -value {1} + +configure_lint_tag -enable -tag "CheckExprCast" -severity Error + +configure_lint_tag -enable -tag "SignedUnsignedExpr-ML" -severity Error + +configure_lint_tag_parameter -tag "SignedUnsignedExpr-ML" -parameter IGNORE_STATIC_EXPRS -value {yes} + +configure_lint_tag_parameter -tag "SignedUnsignedExpr-ML" -parameter IGNOREFORINDEX -value {yes} + +configure_lint_tag_parameter -tag "SignedUnsignedExpr-ML" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W129" -severity Error + +configure_lint_tag -enable -tag "W188" -severity Error + +configure_lint_tag -enable -tag "W504" -severity Error + +configure_lint_tag_parameter -tag "W504" -parameter STRICT -value {yes} + +configure_lint_tag -enable -tag "InvalidMacroCall-ML" -severity Error + +configure_lint_tag -enable -tag "60047" -severity Error + +configure_lint_tag -enable -tag "check_forloop_index" -severity Info + +configure_lint_tag -enable -tag "60118" -severity Error + +configure_lint_tag -enable -tag "0209" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.8.1.5" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.8.5.1" -severity Error + +configure_lint_tag -enable -tag "W171" -severity Warning + +configure_lint_tag_parameter -tag "W171" -parameter IGNORE_CONST_SELECTOR -value {yes} + +configure_lint_tag -enable -tag "DuplicateCase-ML" -severity Error + +configure_lint_tag_parameter -tag "DuplicateCase-ML" -parameter IGNORE_PRIORITY_CASE -value {yes} + +configure_lint_tag -enable -tag "STARC05-2.8.3.5" -severity Warning + +configure_lint_tag -enable -tag "UseSVAlways-ML" -severity Error + +configure_lint_tag_parameter -tag "UseSVAlways-ML" -parameter STRICT -value {yes} + +configure_lint_tag -enable -tag "2216" -severity Error + +configure_lint_tag_parameter -tag "2216" -parameter VIOLATE_SAME_SIGNAL_ONLY -value {yes} + +configure_lint_tag -enable -tag "RptNegEdgeFF-ML" -severity Info + +configure_lint_tag -enable -tag "UnInitializedReset-ML" -severity Error + +configure_lint_tag_parameter -tag "UnInitializedReset-ML" -parameter IGNORE_SYNC_RESET -value {yes} + +configure_lint_tag -enable -tag "RegInput-ML" -severity Warning + +configure_lint_tag_parameter -tag "RegInput-ML" -parameter DEPTH_ML -value {1} + +configure_lint_tag -enable -tag "RegOutputs" -severity Warning + +configure_lint_tag_parameter -tag "RegOutputs" -parameter REPORTUNDRIVENOUT -value {no} + +configure_lint_tag -enable -tag "AvoidAsync" -severity Info + +configure_lint_tag -enable -tag "02084" -severity Error + +configure_lint_tag -enable -tag "0536" -severity Error + +configure_lint_tag -enable -tag "STARC05-2.2.3.1" -severity Error + +configure_lint_tag -enable -tag "0563" -severity Error + +configure_lint_tag -enable -tag "60041" -severity Error + +configure_lint_tag -enable -tag "60086" -severity Error + +configure_lint_tag -enable -tag "60137" -severity Error + +configure_lint_tag -enable -tag "W372" -severity Error + +configure_lint_tag_parameter -tag "W372" -parameter REPORT_CAST -value {yes} + +configure_lint_tag -enable -tag "UnsetProcedureRecord" -severity Warning + +configure_lint_tag -enable -tag "50002" -severity Error + +configure_lint_tag_parameter -tag "50002" -parameter CHECK_PARTIAL_CASE_CASEZ -value {yes} + +configure_lint_tag_parameter -tag "50002" -parameter IGNORE_X_INCASE_CASEZ -value {yes} + +configure_lint_tag -enable -tag "DisallowXInCaseZ-ML" -severity Error + +configure_lint_tag -enable -tag "OneModule-ML" -severity Error + +configure_lint_tag_parameter -tag "OneModule-ML" -parameter IGNOREFILES -value {(.*ctech.*|.*LVISION.*|.*_map\.sv$|.*mbist.*|.*\.lib$)} + +configure_lint_tag -enable -tag "STARC05-1.1.1.1" -severity Error + +configure_lint_tag_parameter -tag "STARC05-1.1.1.1" -parameter IGNORE_FILE_PATH -value {yes} + +configure_lint_tag_parameter -tag "STARC05-1.1.1.1" -parameter IGNORE_FILE_WITH_MULTIPLE_MODULES -value {yes} + +configure_lint_tag_parameter -tag "STARC05-1.1.1.1" -parameter STARC_FILE_EXT_VLOG -value {.v,.vs,.sv,.xfsm.vs} + +configure_lint_tag -enable -tag "FileHdr" -severity Warning + +configure_lint_tag_parameter -tag "FileHdr" -parameter FILE_HDR_IGNORE_PATH -value {.*src\/rtl\/tessent\/.*_(wrapper|uscg)_tessent.*\.v} + +configure_lint_tag_parameter -tag "FileHdr" -parameter IGNORE_FILES_WITH_STOPPED_MODULES -value {yes} + +configure_lint_tag -enable -tag "ModuleInIncludeFile" -severity Warning + +configure_lint_tag -enable -tag "ArrayIndex" -severity Error + +configure_lint_tag_parameter -tag "ArrayIndex" -parameter CHECKALLDIMENSION -value {yes} + +configure_lint_tag_parameter -tag "ArrayIndex" -parameter STRICT -value {no} + +configure_lint_tag -enable -tag "W468" -severity Warning + +# SG rule SYNTH_5130 is mapped to ImproperRangeIndex-ML +# SG rule SYNTH_5255 is also partially mapped to rule ImproperRangeIndex-ML, +# therefore uprevving it to Error with the below exception for ceratin type_ids + +configure_lint_tag -enable -tag "ImproperRangeIndex-ML" -severity Warning + +configure_lint_tag -enable -tag "ImproperRangeIndex-ML" -type_id SG_MORELINT_IMPROPERRANGEINDEX_ML_VERILOG_IMPROPERRANGEINDEX_ML_STATICBITSELECT -severity Warning + +configure_lint_tag -enable -tag "ImproperRangeIndex-ML" -type_id SG_MORELINT_IMPROPERRANGEINDEX_ML_VERILOG_IMPROPERRANGEINDEX_ML_STATICPARTSELECT -severity Warning + +configure_lint_tag_parameter -tag "ImproperRangeIndex-ML" -parameter REPORT_LOOP_VAR_EXPR -value {yes} + +configure_lint_tag_parameter -tag "ImproperRangeIndex-ML" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "ImproperRangeIndex-ML" -parameter REPORT_STATIC_INDEXES -value {yes} + +configure_lint_tag_parameter -tag "ImproperRangeIndex-ML" -parameter REPORT_ONLY_FROM_ONE_HIERARCHY -value {yes} + +configure_lint_tag -enable -tag "W576" -severity Error + +configure_lint_tag -enable -tag "ParamReDefined" -severity Warning + +configure_lint_tag_parameter -tag "ParamReDefined" -parameter IGNORE_MULTIPLE_PACKAGE_IMPORT -value {yes} + +configure_lint_tag_parameter -tag "ParamReDefined" -parameter IGNORE_PARAMS_WITH_SAME_VALUE -value {yes} + +configure_lint_tag -enable -tag "W154" -severity Error + +configure_lint_tag_parameter -tag "W154" -parameter GROUP_BY_MODULE -value {yes} + +configure_lint_tag_parameter -tag "W154" -parameter IGNORE_FILES_REGEXP -value {.*collage.*|.*defacto.*} + +configure_lint_tag_parameter -tag "W154" -parameter REPORT_PORT_NET -value {yes} + +configure_lint_tag -enable -tag "2083" -severity Warning + +configure_lint_tag -enable -tag "UnusedTypedef" -severity Warning + +configure_lint_tag -enable -tag "W175" -severity Warning + +configure_lint_tag_parameter -tag "W175" -parameter REPORT_GLOBAL_PARAM -value {yes} + +configure_lint_tag -enable -tag "60175" -severity Error + +configure_lint_tag -enable -tag "60044" -severity Warning + +configure_lint_tag -enable -tag "0301" -severity Warning + +configure_lint_tag -enable -tag "60130" -severity Error + + +configure_lint_tag -enable -tag "60159" -severity Error + +#configure_lint_tag_parameter -tag "60159" -parameter DEFINITION_TYPES -value {functions,tasks,typedefs,parameters,local_parameters,import_statments} + +configure_lint_tag -enable -tag "ProhibitedDataTypes-ML" -severity Error + +configure_lint_tag_parameter -tag "ProhibitedDataTypes-ML" -parameter PROHIBITED_DATA_TYPES -value {logic,bit} + +configure_lint_tag -enable -tag "CheckExplicitImports" -severity Warning + +configure_lint_tag -enable -tag "UseParamInsteadDefine-ML" -severity Error + +configure_lint_tag -enable -tag "W259" -severity Error + +configure_lint_tag -enable -tag "DetectInvalidSignedAssignment-ML" -severity Info + +configure_lint_tag -enable -tag "DetectUnderAndOverFlows-ML" -type_id SG_MORELINT_DETECTUNDERANDOVERFLOWS_ML_VERILOG_DETECTUNDERANDOVERFLOWS_ML_MSG_WARNING -severity Error + +configure_lint_tag -enable -tag "DetectUnderAndOverFlows-ML" -type_id SG_MORELINT_DETECTUNDERANDOVERFLOWS_ML_VERILOG_DETECTUNDERANDOVERFLOWS_ML_MSG_NC_TRUNCATION -severity Warning + +configure_lint_tag -enable -tag "DetectUnderAndOverFlows-ML" -type_id SG_MORELINT_DETECTUNDERANDOVERFLOWS_ML_VERILOG_DETECTUNDERANDOVERFLOWS_ML_MSG_INFO -severity Warning + +configure_lint_tag_parameter -tag "DetectUnderAndOverFlows-ML" -parameter CHECK_TYPE_CAST -value {yes} + +configure_lint_tag_parameter -tag "DetectUnderAndOverFlows-ML" -parameter NOCHECKOVERFLOW -value {no} + +configure_lint_tag_parameter -tag "DetectUnderAndOverFlows-ML" -parameter HANDLE_SHIFT_OP -value {shift_left} + +configure_lint_tag_parameter -tag "DetectUnderAndOverFlows-ML" -parameter DIFFERENTIATE_NESTED_CAST -value {yes} + +configure_lint_tag -enable -tag "UseParamInsteadDefine-ML" -severity Error + +configure_lint_tag -enable -tag "IfOverlap-ML" -severity Error + +configure_lint_tag -enable -tag "UniqueIfMissingCond-ML" -severity Error -formal + +configure_lint_tag -enable -tag "CheckGuardMacro" -severity Error + +configure_lint_tag_parameter -tag "CheckGuardMacro" -parameter CHECK_FILE_NAME -value {yes} + +configure_lint_tag -enable -tag "AvoidMultiDimParam-ML" -severity Error + +# Rules for testing purposes ONLY + +#configure_lint_tag -enable -tag DefaultState -severity Warning + +#configure_lint_tag_parameter -tag "DefaultState" -parameter CHECK_ONLY_CASE_STMT -value {yes} + +set_app_var sh_continue_on_error $saved_sh_continue_on_error + +#################### Builtin Rule Configurations #################### + +set saved_sh_continue_on_error [get_app_var sh_continue_on_error] + +set_app_var sh_continue_on_error true + +#Rule configuration for SG rule : INFO_1010 + +configure_tag -tag VC_INFO_UDP_TRANSLATE -enable -severity Error + +#Rule configuration for SG rule : SGDCWRN_127 + +configure_tag -tag VC_PRAGMA_INCORRECT_RULE -disable + +#Rule configuration for SG rule : SGDC_waive35 + +configure_tag -tag VC_WAIVER_BLOCK_NOT_FOUND -severity Warning + +# blanket waivers are NOT allowed : SGDC_waive39 + +configure_tag -tag {VC_WAIVER_ONLY_TAG_GIVEN} -severity {Error} + +#Rule configuration for SG rule : SYNTH_1082 + +configure_tag -tag OOECAIAB -enable -severity Error + +#Rule configuration for SG rule : SYNTH_1111 + +configure_tag -tag SM_URT -enable -severity Error + +#Rule configuration for SG rule : SYNTH_12605 + +configure_tag -tag { SM_FCNF SM_PCNP SM_PNP SM_TUFC } -enable -severity Warning + +#Rule configuration for SG rule : SYNTH_12608 + +configure_tag -tag { SM_MCAL SM_MLAC SM_MLAFF } -enable -severity Error + +#Rule configuration for SG rule : SYNTH_132 + +configure_tag -tag VC_SYNTH_HIER_REF -enable -severity Error + +#Rule configuration for SG rule : SYNTH_196 + +configure_tag -tag VC_SYNTH_TASK_EVENT -enable -severity Error + +#Rule configuration for SG rule : SYNTH_5064 + +configure_tag -tag VC_SYNTH_STMT_IGNORED -disable + +#Rule configuration for SG rule : SYNTH_5142 + +configure_tag -tag VC_SYNTH_SPECIFY_UNSUPP -enable -severity Error + +#Rule configuration for SG rule : SYNTH_5143 + +configure_tag -tag SM_IGN_INITIAL -disable + +#Rule configuration for SG rule : WRN_1036 + +configure_tag -tag VC_WRN_EVENT_VALID -enable -severity Error + +#Rule configuration for SG rule : WRN_1041 + +configure_tag -tag VC_WRN_UNDERSCORE_IGNORED -severity Error + +#Rule configuration for SG rule : WRN_1042 + +configure_tag -tag IIPCNDO -enable -severity Error + +#Rule configuration for SG rule : WRN_1453 + +configure_tag -tag VC_WRN_PORT_INVALID -enable -severity Error + +#Rule configuration for SG rule : WRN_1469 + +configure_tag -tag ENUMASSIGN -enable -severity Warning + +#Rule configuration for SG rule : WRN_26 + +configure_tag -tag TMR -enable -severity Error + +#Rule configuration for SG rule : WRN_32 + +configure_tag -tag IICD -severity Warning + +#Rule configuration for SG rule : WRN_54 and WRN_1464 + +configure_tag -tag AOUP -enable -severity Error + +#Rule configuration for SG rule : WRN_70 + +configure_tag -tag SAGB -enable -severity Error + +configure_tag -tag OPD -enable -severity Info + +#Rule configuration for SG rule: WRN_1467 + +configure_tag -tag DPIMI -enable -severity Error + +# Rule configuration for SG rule: STX_VE_361 + +#configure_tag -tag IUAO -enable -severity Fatal + +configure_tag -tag IBLHS-NT -enable -severity Fatal + +# Rule configuration for SG rule: STX_VE_467 + +configure_tag -tag ICTA -enable -severity Fatal + +# Rule configuration for SG rule: STX_VE_462 + +configure_tag -tag SV-USAC -enable -severity Fatal + +# Rule configuration for SG rule: WRN_40 + +configure_tag -tag IPDW -enable -severity Fatal + +# Rule configuration for SG rule: WRN_1471 + +configure_tag -tag USL -enable -severity Error + +#Rule configuration for SG rule : SYNTH_89 + +configure_tag -tag VC_SYNTH_INITIAL_IGNORED -enable -severity Error + +set_app_var sh_continue_on_error $saved_sh_continue_on_error + +#################### Builtin Rule Configurations End +#################### + +#configure_lint_setup -j 4 diff --git a/mpsoc/Integration_test/VCST/src/param_gen.pl b/mpsoc/Integration_test/VCST/src/param_gen.pl new file mode 100644 index 0000000..1ad4763 --- /dev/null +++ b/mpsoc/Integration_test/VCST/src/param_gen.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl +package ProNOC; +use strict; +use warnings; +use File::Basename; + + +#add home dir in perl 5.6 +use FindBin; +use lib $FindBin::Bin; +use Cwd qw(realpath); + + + + +use File::Path qw(make_path); + + +use strict; +use warnings; + + + + +my $script_path = dirname(__FILE__); + +require "$script_path/../../synthetic_sim/src/src.pl"; +use lib "../synthetic_sim/src/perl_lib"; + +use constant::boolean; +use base 'Class::Accessor::Fast'; + +my $conf_file=$ARGV[0]; + + +sub create_noc_param_vv { + my ($conf_file)=@_; + my $o = do $conf_file; + die "Could not parse $conf_file: $@" if $@; + die "Could not read $conf_file: $!" unless defined $o; + my $param = $o->{'noc_param'}; + my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); + save_file("$script_path/noc_localparam.v",$param_v); +} + +create_noc_param_vv ($conf_file); diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 100c376..b7ea314 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -98,7 +98,7 @@ (current_port== BACKWARD)? FORWARD: router_port_num; //DISABLED; end else if (IS_FATTREE ) begin - if(router_port_num[0]==1'b0) begin //even port num + if((router_port_num & 1) == 0) begin // even port strieght_port = (current_port < (router_port_num/2) )? (router_port_num/2)+ current_port : current_port - (router_port_num/2); @@ -360,18 +360,18 @@ end end end - endfunction + endfunction function automatic integer mcast_partial_width; input [NE-1 : 0] p; - integer i; + integer i; begin mcast_partial_width=0; for (i=0;i Date: Fri, 6 Jun 2025 16:57:54 +0200 Subject: [PATCH 037/107] fix linting --- mpsoc/rtl/arbiter.v | 106 +- mpsoc/rtl/arch/flit_buffer_reg_bas.v | 8 +- mpsoc/rtl/arch/iport_reg_base.sv | 16 +- mpsoc/rtl/main_comp.v | 152 +-- mpsoc/rtl/src_modelsim/multicast_injector.sv | 6 +- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 2 +- mpsoc/rtl/src_noc/comb-spec1.v | 2 +- mpsoc/rtl/src_noc/comb_nonspec.sv | 28 +- mpsoc/rtl/src_noc/comb_spec2.v | 2 +- mpsoc/rtl/src_noc/congestion_analyzer.v | 88 +- mpsoc/rtl/src_noc/crossbar.v | 4 +- mpsoc/rtl/src_noc/debug.v | 18 +- mpsoc/rtl/src_noc/fattree_route.v | 20 +- mpsoc/rtl/src_noc/flit_buffer.sv | 74 +- mpsoc/rtl/src_noc/fmesh.sv | 24 +- mpsoc/rtl/src_noc/header_flit.sv | 14 +- mpsoc/rtl/src_noc/inout_ports.sv | 12 +- mpsoc/rtl/src_noc/input_ports.sv | 38 +- mpsoc/rtl/src_noc/mesh_torus.sv | 22 +- mpsoc/rtl/src_noc/mesh_torus_routting.v | 8 +- mpsoc/rtl/src_noc/output_ports.sv | 56 +- mpsoc/rtl/src_noc/packet_injector.sv | 18 +- mpsoc/rtl/src_noc/router_bypass.sv | 74 +- mpsoc/rtl/src_noc/router_top.sv | 8 +- mpsoc/rtl/src_noc/router_two_stage.sv | 28 +- mpsoc/rtl/src_noc/routing.v | 8 +- mpsoc/rtl/src_noc/ss_allocator.sv | 4 +- mpsoc/rtl/src_noc/topology_localparam.v | 12 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 8 +- mpsoc/rtl/src_noc/tree_route.v | 4 +- mpsoc/rtl/src_noc/wrra.v | 52 +- mpsoc/rtl/src_peripheral/bus/wishbone_bus.v | 14 +- .../xilinx_pll/xilinx_pll_sim/freq_gen.v | 10 +- .../xilinx_pll_sim/plle2_base_sim.v | 8 +- .../jtag/jtag_wb/xilinx_jtag_wb.v | 30 +- .../jtag_ram_test/src_verilog/lib/arbiter.v | 106 +- .../jtag_ram_test/src_verilog/lib/main_comp.v | 943 ++++++------------ 37 files changed, 831 insertions(+), 1196 deletions(-) mode change 100644 => 100755 mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v diff --git a/mpsoc/rtl/arbiter.v b/mpsoc/rtl/arbiter.v index 0cdb1aa..16708f1 100755 --- a/mpsoc/rtl/arbiter.v +++ b/mpsoc/rtl/arbiter.v @@ -181,88 +181,88 @@ module my_one_hot_arbiter #( end assign any_grant = | request; generate - if(ARBITER_WIDTH ==2) begin: w2 arbiter_2_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==3) begin: w3 arbiter_3_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==4) begin: w4 arbiter_4_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==2) begin: w2 arbiter_2_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==3) begin: w3 arbiter_3_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==4) begin: w4 arbiter_4_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end endgenerate endmodule module arbiter_2_one_hot( - input [1 : 0] in, - output reg[1 : 0] out, + input [1 : 0] D_in, + output reg[1 : 0] Q_out, input low_pr ); always @(*) begin - out=2'b00; + Q_out=2'b00; case(low_pr) 1'd0: - if(in[1]) out=2'b10; - else if(in[0]) out=2'b01; + if(D_in[1]) Q_out=2'b10; + else if(D_in[0]) Q_out=2'b01; 1'd1: - if(in[0]) out=2'b01; - else if(in[1]) out=2'b10; - default: out=2'b00; + if(D_in[0]) Q_out=2'b01; + else if(D_in[1]) Q_out=2'b10; + default: Q_out=2'b00; endcase end endmodule module arbiter_3_one_hot( - input [2 : 0] in, - output reg[2 : 0] out, + input [2 : 0] D_in, + output reg[2 : 0] Q_out, input [1 : 0] low_pr ); always @(*) begin - out=3'b000; + Q_out=3'b000; case(low_pr) 2'd0: - if(in[1]) out=3'b010; - else if(in[2]) out=3'b100; - else if(in[0]) out=3'b001; + if(D_in[1]) Q_out=3'b010; + else if(D_in[2]) Q_out=3'b100; + else if(D_in[0]) Q_out=3'b001; 2'd1: - if(in[2]) out=3'b100; - else if(in[0]) out=3'b001; - else if(in[1]) out=3'b010; + if(D_in[2]) Q_out=3'b100; + else if(D_in[0]) Q_out=3'b001; + else if(D_in[1]) Q_out=3'b010; 2'd2: - if(in[0]) out=3'b001; - else if(in[1]) out=3'b010; - else if(in[2]) out=3'b100; - default: out=3'b000; + if(D_in[0]) Q_out=3'b001; + else if(D_in[1]) Q_out=3'b010; + else if(D_in[2]) Q_out=3'b100; + default: Q_out=3'b000; endcase end endmodule module arbiter_4_one_hot( - input [3 : 0] in, - output reg[3 : 0] out, + input [3 : 0] D_in, + output reg[3 : 0] Q_out, input [1 : 0] low_pr ); always @(*) begin - out=4'b0000; + Q_out=4'b0000; case(low_pr) 2'd0: - if(in[1]) out=4'b0010; - else if(in[2]) out=4'b0100; - else if(in[3]) out=4'b1000; - else if(in[0]) out=4'b0001; + if(D_in[1]) Q_out=4'b0010; + else if(D_in[2]) Q_out=4'b0100; + else if(D_in[3]) Q_out=4'b1000; + else if(D_in[0]) Q_out=4'b0001; 2'd1: - if(in[2]) out=4'b0100; - else if(in[3]) out=4'b1000; - else if(in[0]) out=4'b0001; - else if(in[1]) out=4'b0010; + if(D_in[2]) Q_out=4'b0100; + else if(D_in[3]) Q_out=4'b1000; + else if(D_in[0]) Q_out=4'b0001; + else if(D_in[1]) Q_out=4'b0010; 2'd2: - if(in[3]) out=4'b1000; - else if(in[0]) out=4'b0001; - else if(in[1]) out=4'b0010; - else if(in[2]) out=4'b0100; + if(D_in[3]) Q_out=4'b1000; + else if(D_in[0]) Q_out=4'b0001; + else if(D_in[1]) Q_out=4'b0010; + else if(D_in[2]) Q_out=4'b0100; 2'd3: - if(in[0]) out=4'b0001; - else if(in[1]) out=4'b0010; - else if(in[2]) out=4'b0100; - else if(in[3]) out=4'b1000; - default: out=4'b0000; + if(D_in[0]) Q_out=4'b0001; + else if(D_in[1]) Q_out=4'b0010; + else if(D_in[2]) Q_out=4'b0100; + else if(D_in[3]) Q_out=4'b1000; + default: Q_out=4'b0000; endcase end endmodule @@ -312,9 +312,9 @@ module my_one_hot_arbiter_priority_en #( assign any_grant = | request; generate - if(ARBITER_WIDTH ==2) begin : w2 arbiter_2_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==3) begin : w3 arbiter_3_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==4) begin : w4 arbiter_4_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==2) begin : w2 arbiter_2_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==3) begin : w3 arbiter_3_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==4) begin : w4 arbiter_4_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end endgenerate endmodule @@ -326,13 +326,13 @@ endmodule module thermo_gen #( parameter WIDTH=16 )( - input [WIDTH-1 : 0]in, - output [WIDTH-1 : 0]out + input [WIDTH-1 : 0]D_in, + output [WIDTH-1 : 0]Q_out ); genvar i; generate for(i=0;i1)? log2(ONE_HOT_WIDTH):1 + parameter BIN_WIDTH = (ONE_HOT_WIDTH > 1) ? $clog2(ONE_HOT_WIDTH) : 1 )( input [ONE_HOT_WIDTH-1 : 0] one_hot_code, output [BIN_WIDTH-1 : 0] bin_code ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21)begin :if1 - for(i=0; i1)begin :if1 + for(i=0; i1) ? log2(IN_NUM): 1; + IN_NUM = IN_WIDTH / OUT_WIDTH, + SEL_WIDTH_BIN = (IN_NUM > 1) ? $clog2(IN_NUM) : 1; input [IN_WIDTH-1 : 0] mux_in; output [OUT_WIDTH-1 : 0] mux_out; input [SEL_WIDTH_BIN-1 : 0] sel; genvar i; generate - if(IN_NUM>1) begin :if1 + if(IN_NUM > 1) begin wire [OUT_WIDTH-1 : 0] mux_in_2d [IN_NUM -1 : 0]; for (i=0; i< IN_NUM; i=i+1) begin : loop - assign mux_in_2d[i] =mux_in[((i+1)*OUT_WIDTH)-1 : i*OUT_WIDTH]; + assign mux_in_2d[i] = mux_in[((i+1)*OUT_WIDTH)-1 : i*OUT_WIDTH]; end assign mux_out = mux_in_2d[sel]; - end else begin :els + end else begin assign mux_out = mux_in; end endgenerate @@ -338,7 +321,7 @@ module accumulator #( parameter NUM =5 )( in_all, - out + sum_o ); function integer log2; input integer number; begin @@ -353,22 +336,22 @@ module accumulator #( N = INw/NUM, SUMw = log2(NUM)+N; input [INw-1 : 0] in_all; - output[OUTw-1 : 0] out; - - wire [N-1 : 0] in [NUM-1 : 0]; + output[OUTw-1 : 0] sum_o; + + wire [N-1 : 0] D_in [NUM-1 : 0]; reg [SUMw-1 : 0] sum; genvar i; generate for (i=0; i OUTw) begin : bigger - assign out = (sum[SUMw-1 : OUTw] > 0 ) ? {OUTw{1'b1}} : sum[OUTw-1 : 0] ; + assign sum_o = (sum[SUMw-1 : OUTw] > 0 ) ? {OUTw{1'b1}} : sum[OUTw-1 : 0] ; end else begin : less - assign out = {{(OUTw-SUMw){1'b0}}, sum} ; + assign sum_o = {{(OUTw-SUMw){1'b0}}, sum} ; end endgenerate // This is supposed to be synyhesized as "sum=in[0]+in[1]+...in[Num-1]"; @@ -377,7 +360,7 @@ module accumulator #( always @(*)begin sum = {SUMw{1'b0}}; for (k=0;k congestion_y_min)? YDIR : XDIR; assign conjestion_cmp[X_MINUS_Y_MINUS]= (congestion_x_min > congestion_y_min)? YDIR : XDIR; // assign port_pre_sel = conjestion_cmp; - pronoc_register #(.W(PPSw)) reg1 (.in(conjestion_cmp ), .reset(reset), .clk(clk), .out(port_pre_sel)); + pronoc_register #(.W(PPSw)) reg1 (.D_in(conjestion_cmp ), .reset(reset), .clk(clk), .Q_out(port_pre_sel)); endmodule @@ -441,8 +441,8 @@ module congestion_out_based_ivc_req #( .INw (PV), .OUTw (CONGw) ) ivc_req_counter ( - .in (ivc_request_all), - .out (congestion_out) + .D_in(ivc_request_all), + .Q_out(congestion_out) ); assign congestion_out_all = {P{congestion_out}}; @@ -488,10 +488,10 @@ module congestion_out_based_ivc_notgrant #( pronoc_register #( .W(PV) ) reg1 ( - .in(ivc_request_all & ~ivc_num_getting_sw_grant), + .D_in(ivc_request_all & ~ivc_num_getting_sw_grant), .reset(reset), .clk(clk), - .out(ivc_request_not_granted) + .Q_out(ivc_request_not_granted) ); accumulator #( .INw(PV), @@ -499,7 +499,7 @@ module congestion_out_based_ivc_notgrant #( .NUM(PV) ) ivc_req_counter ( .in_all(ivc_request_not_granted), - .out(ivc_req_num) + .sum_o(ivc_req_num) ); generate @@ -571,8 +571,8 @@ module congestion_out_based_3port_avb_ovc #( .INw(CNT_Iw), .OUTw(CONGw) ) ovc_avb_east ( - .in(counter_in[i]), - .out(congestion_out[i]) + .D_in(counter_in[i]), + .Q_out(congestion_out[i]) ); end endgenerate @@ -627,8 +627,8 @@ module congestion_out_based_avb_ovc_w2 #( .INw(CNT_Iw), .OUTw(1) ) ovc_not_avb_cnt ( - .in(counter_in[i]), - .out(threshold[i]) + .D_in(counter_in[i]), + .Q_out(threshold[i]) ); end endgenerate @@ -677,8 +677,8 @@ module congestion_out_based_avb_ovc_w3 #( .INw(V), .OUTw(1) ) ovc_avb_east( - .in(ovc_not_avb[i]), - .out(threshold[i]) + .D_in(ovc_not_avb[i]), + .Q_out(threshold[i]) ); end endgenerate @@ -738,8 +738,8 @@ module congestion_out_based_avb_ovc_w4 #( .INw(CNT_Iw), .OUTw(2) ) ovc_not_avb_cnt ( - .in(counter_in[i]), - .out(threshold[i]) + .D_in(counter_in[i]), + .Q_out(threshold[i]) ); end endgenerate @@ -816,10 +816,10 @@ module congestion_out_based_avb_ovc_not_granted_ivc #( pronoc_register #( .W(PV) ) reg1 ( - .in(ivc_request_all & ~ivc_num_getting_sw_grant), + .D_in(ivc_request_all & ~ivc_num_getting_sw_grant), .reset(reset), .clk(clk), - .out(ivc_request_not_granted) + .Q_out(ivc_request_not_granted) ); assign {ivc_not_grnt[SOUTH], ivc_not_grnt[WEST], ivc_not_grnt[NORTH],ivc_not_grnt[EAST]}= ivc_request_not_granted[PV-1 : V]; genvar i; @@ -831,7 +831,7 @@ module congestion_out_based_avb_ovc_not_granted_ivc #( .NUM(CNT_Iw) ) ovc_counter ( .in_all(counter_in[i]), - .out(counter_o[i]) + .sum_o(counter_o[i]) ); accumulator #( .INw(V), @@ -839,7 +839,7 @@ module congestion_out_based_avb_ovc_not_granted_ivc #( .NUM(V) ) ivc_counter ( .in_all(ivc_not_grnt[i]), - .out(ivc_not_grnt_num[i]) + .sum_o(ivc_not_grnt_num[i]) ); wire [CNG_w-1 : 0] congestion_num [P_1-1 : 0]; assign congestion_num [i] = counter_o[i]+ ivc_not_grnt_num[i]+ {ivc_not_grnt_num[i],1'b0}; @@ -847,8 +847,8 @@ module congestion_out_based_avb_ovc_not_granted_ivc #( .MAX_IN(6*V), .OUTw(CONGw) )norm ( - .in(congestion_num [i]), - .out(congestion_out[i]) + .D_in(congestion_num [i]), + .Q_out(congestion_out[i]) ); end//for endgenerate @@ -862,8 +862,8 @@ module parallel_count_normalize #( parameter INw = 12, parameter OUTw= 2 )( - in, - out + D_in, + Q_out ); function integer log2; @@ -875,8 +875,8 @@ module parallel_count_normalize #( end endfunction // log2 - input [INw-1 : 0] in; - output [OUTw-1 : 0] out; + input [INw-1 : 0] D_in; + output [OUTw-1 : 0] Q_out; localparam CNTw = log2(INw+1); wire [CNTw-1 : 0] counter; accumulator #( @@ -884,16 +884,16 @@ module parallel_count_normalize #( .OUTw(CNTw), .NUM(INw) ) ovc_avb_cnt ( - .in_all(in), - .out(counter) + .in_all(D_in), + .sum_o(counter) ); normalizer #( .MAX_IN(INw), .OUTw(OUTw) )norm ( - .in(counter), - .out(out) + .D_in(counter), + .Q_out(Q_out) ); endmodule @@ -904,8 +904,8 @@ module normalizer #( parameter MAX_IN= 10, parameter OUTw= 2 )( - in, - out + D_in, + Q_out ); function integer log2; input integer number; begin @@ -918,15 +918,15 @@ module normalizer #( localparam INw= log2(MAX_IN+1), OUT_ON_HOT_NUM = 2**OUTw; - input [INw-1 : 0] in; - output [OUTw-1 : 0] out; + input [INw-1 : 0] D_in; + output [OUTw-1 : 0] Q_out; wire [OUT_ON_HOT_NUM-1 : 0] one_hot_out; genvar i; generate for(i=0;i< OUT_ON_HOT_NUM;i=i+1)begin :lp /* verilator lint_off WIDTH */ - if(i==0) begin : i0 assign one_hot_out[i]= (in<= (MAX_IN /OUT_ON_HOT_NUM)); end - else begin :ib0 assign one_hot_out[i]= ((in> ((MAX_IN *i)/OUT_ON_HOT_NUM)) && (in<= ((MAX_IN *(i+1))/OUT_ON_HOT_NUM))); end + if(i==0) begin : i0 assign one_hot_out[i]= (D_in <= (MAX_IN /OUT_ON_HOT_NUM)); end + else begin :ib0 assign one_hot_out[i]= ((D_in> ((MAX_IN *i)/OUT_ON_HOT_NUM)) && (D_in<= ((MAX_IN *(i+1))/OUT_ON_HOT_NUM))); end /* verilator lint_on WIDTH */ end//for endgenerate @@ -935,7 +935,7 @@ module normalizer #( .ONE_HOT_WIDTH(OUT_ON_HOT_NUM) )cnv ( .one_hot_code(one_hot_out), - .bin_code(out) + .bin_code(Q_out) ); endmodule @@ -1046,10 +1046,10 @@ localparam pronoc_register #( .W(CONG_ALw) ) reg1 ( - .in(congestion_out_all_next), + .D_in(congestion_out_all_next), .reset(reset), .clk(clk), - .out(congestion_out_all) + .Q_out(congestion_out_all) ); endmodule @@ -1093,10 +1093,10 @@ module deadlock_detector #( pronoc_register #( .W(PV) ) reg1 ( - .in(ivc_num_getting_sw_grant), + .D_in(ivc_num_getting_sw_grant), .reset(reset), .clk(clk), - .out(ivc_num_getting_sw_grant_reg) + .Q_out(ivc_num_getting_sw_grant_reg) ); //seperate all same virtual chanels requests genvar i,j; @@ -1119,10 +1119,10 @@ module deadlock_detector #( pronoc_register #( .W(CNTw) ) reg2 ( - .in(counter_next[i]), + .D_in(counter_next[i]), .reset(reset), .clk(clk), - .out(counter[i]) + .Q_out(counter[i]) ); // check counters value to detect deadlock assign detect_gen[i] = (counter[i]== MAX_CLK-1); diff --git a/mpsoc/rtl/src_noc/crossbar.v b/mpsoc/rtl/src_noc/crossbar.v index b12c36f..22b6956 100755 --- a/mpsoc/rtl/src_noc/crossbar.v +++ b/mpsoc/rtl/src_noc/crossbar.v @@ -118,8 +118,8 @@ module crossbar #( .W (Fw), .N (P_1) ) cross_mux ( - .in (mux_in [i]), - .out (flit_out_all[(i+1)*Fw-1 : i*Fw]), + .D_in(mux_in [i]), + .Q_out(flit_out_all[(i+1)*Fw-1 : i*Fw]), .sel (mux_sel[i]) ); end else begin : binary diff --git a/mpsoc/rtl/src_noc/debug.v b/mpsoc/rtl/src_noc/debug.v index c68c846..8c0981a 100644 --- a/mpsoc/rtl/src_noc/debug.v +++ b/mpsoc/rtl/src_noc/debug.v @@ -42,10 +42,10 @@ module check_flit_chanel_type_is_in_order #( pronoc_register #( .W(V) ) reg2 ( - .in(hdr_passed_next), + .D_in(hdr_passed_next), .reset(reset), .clk(clk), - .out(hdr_passed) + .Q_out(hdr_passed) ); always @ (posedge clk ) begin if(( hdr_passed & vc_num_hdr_wr)>0 )begin @@ -201,10 +201,10 @@ module debug_mesh_tori_route_ckeck #( pronoc_register #( .W(V) ) reg2 ( - .in(not_empty_next), + .D_in(not_empty_next), .reset(reset), .clk(clk), - .out(not_empty) + .Q_out(not_empty) ); always@(*) begin not_empty_next = not_empty; @@ -580,10 +580,10 @@ module check_pck_size #( end pronoc_register #(.W(32)) reg1( - .in (pck_size_counter_next[i]), + .D_in(pck_size_counter_next[i]), .reset (reset ), .clk (clk ), - .out (pck_size_counter[i] ) + .Q_out (pck_size_counter[i] ) ); always @(posedge clk) begin @@ -603,11 +603,11 @@ module check_pck_size #( //Check that the size of multicast/broadcast packets <= buffer size assign vc_hdr_wr_en [i] = flit_in_wr & hdr_flg_in & (vc_num_in == i); pronoc_register_ld_en #(.W(DAw)) reg2( - .in (dest_e_addr_in), + .D_in (dest_e_addr_in), .reset (reset ), .clk (clk ), .ld (vc_hdr_wr_en [i] ), - .out (dest_e_addr[i]) + .Q_out (dest_e_addr[i]) ); mcast_dest_list_decode #( @@ -622,7 +622,7 @@ module check_pck_size #( is_onehot0 #( .IN_WIDTH(NE) ) one_h ( - .in(dest_mcast_all_endp[i]), + .D_in(dest_mcast_all_endp[i]), .result(onehot[i]) ); always @(posedge clk) begin diff --git a/mpsoc/rtl/src_noc/fattree_route.v b/mpsoc/rtl/src_noc/fattree_route.v index 41794a6..6375d7c 100644 --- a/mpsoc/rtl/src_noc/fattree_route.v +++ b/mpsoc/rtl/src_noc/fattree_route.v @@ -60,10 +60,10 @@ module fattree_nca_random_up_routing #( .W(K), .RESET_TO(1) ) reg1 ( - .in({counter[0],counter[K-1:1]}), + .D_in({counter[0],counter[K-1:1]}), .reset(reset), .clk(clk), - .out(counter) + .Q_out(counter) ); assign current_addr [0]={Kw{1'b0}}; @@ -153,10 +153,10 @@ module fattree_nca_destp_up_routing #( .W(K), .RESET_TO(1) ) reg1 ( - .in({counter[0],counter[K-1:1]}), + .D_in({counter[0],counter[K-1:1]}), .reset(reset), .clk(clk), - .out(counter) + .Q_out(counter) ); assign current_addr [0]={Kw{1'b0}}; @@ -243,10 +243,10 @@ module fattree_nca_straight_up_routing #( .W(K), .RESET_TO(1) ) reg1 ( - .in({counter[0],counter[K-1:1]}), + .D_in({counter[0],counter[K-1:1]}), .reset(reset), .clk(clk), - .out(counter) + .Q_out(counter) ); assign current_addr [0]={Kw{1'b0}}; @@ -445,19 +445,19 @@ module fattree_look_ahead_routing #( pronoc_register #( .W(K+1) ) reg1 ( - .in(destport_encoded), + .D_in(destport_encoded), .reset(reset), .clk(clk), - .out(destport_encoded_delayed) + .Q_out(destport_encoded_delayed) ); pronoc_register #( .W(LKw) ) reg2 ( - .in(dest_addr_encoded), + .D_in(dest_addr_encoded), .reset(reset), .clk(clk), - .out(dest_addr_encoded_delayed) + .Q_out(dest_addr_encoded_delayed) ); endmodule diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 0574bb7..bcee140 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -142,9 +142,8 @@ module flit_buffer /* verilator lint_on WIDTH */ assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = sub_rd_ptr[i]; localparam RESET_TO = ((2**Bw)==B)? 0 : B*i; - pronoc_register #(.W(PTRw),.RESET_TO(RESET_TO)) reg4 (.in(sub_rd_ptr_next[i]), .out(sub_rd_ptr[i]), .reset(reset), .clk(clk)); - - pronoc_register #(.W(DEPTHw)) sub_depth_reg (.in(sub_depth_next[i] ), .out(sub_depth [i]), .reset(reset), .clk(clk)); + pronoc_register #(.W(PTRw),.RESET_TO(RESET_TO)) reg4 (.D_in(sub_rd_ptr_next[i]), .Q_out(sub_rd_ptr[i]), .reset(reset), .clk(clk)); + pronoc_register #(.W(DEPTHw)) sub_depth_reg (.D_in(sub_depth_next[i] ), .Q_out(sub_depth [i]), .reset(reset), .clk(clk)); always @ (*)begin sub_depth_next [i] = sub_depth [i]; if(sub_restore[i]) sub_depth_next [i]= depth_next[i]; @@ -180,8 +179,8 @@ module flit_buffer .W(Bw), .N(V) ) wr_ptr_mux ( - .in(wr_ptr_array), - .out(vc_wr_addr), + .D_in(wr_ptr_array), + .Q_out(vc_wr_addr), .sel(vc_num_wr) ); @@ -189,8 +188,8 @@ module flit_buffer .W(Bw), .N(V) ) rd_ptr_mux ( - .in(rd_ptr_array), - .out(vc_rd_addr), + .D_in(rd_ptr_array), + .Q_out(vc_rd_addr), .sel(vc_num_rd) ); @@ -228,9 +227,9 @@ module flit_buffer if(wr[i]) tail_fifo[i][wr_ptr[i]] <= din[Fw-2]; end - pronoc_register #(.W(Bw )) reg1 (.in(rd_ptr_next[i]), .out(rd_ptr[i]), .reset(reset), .clk(clk)); - pronoc_register #(.W(Bw )) reg2 (.in(wr_ptr_next[i]), .out(wr_ptr[i]), .reset(reset), .clk(clk)); - pronoc_register #(.W(DEPTHw)) reg3 (.in(depth_next[i] ), .out(depth [i]), .reset(reset), .clk(clk)); + pronoc_register #(.W(Bw )) reg1 (.D_in(rd_ptr_next[i]), .Q_out(rd_ptr[i]), .reset(reset), .clk(clk)); + pronoc_register #(.W(Bw )) reg2 (.D_in(wr_ptr_next[i]), .Q_out(wr_ptr[i]), .reset(reset), .clk(clk)); + pronoc_register #(.W(DEPTHw)) reg3 (.D_in(depth_next[i] ), .Q_out(depth [i]), .reset(reset), .clk(clk)); always @ (*) begin rd_ptr_next [i] = rd_ptr [i]; @@ -274,11 +273,10 @@ module flit_buffer wire [BVw- 1 : 0] wr_addr; wire [BVw- 1 : 0] rd_addr; for(i=0;i 0) counter_next = counter -1'b1; end assign credit_out = credit_in | smart_credit_in | (counter > 0); - pronoc_register #(.W(Bw+1)) reg1 (.in(counter_next), .reset(reset), .clk(clk), .out(counter)); + pronoc_register #(.W(Bw+1)) reg1 (.D_in(counter_next), .reset(reset), .clk(clk), .Q_out(counter)); endmodule diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index cc40e15..05fa452 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -77,8 +77,7 @@ module router_top #( current_r_id = 0; current_r_id [NRw-1 : 0] = router_config_in.router_id; for( int k=0; k0) begin - out = $fopen(fname[p],"a"); - if(CYCLE_REPORT) $fwrite(out,"%t:",$time); - $fwrite(out, "credit %s:%h Port %0d\n",DIRECTION, chan_in[p].credit,p); - $fclose(out); + Q_out = $fopen(fname[p],"a"); + if(CYCLE_REPORT) $fwrite(Q_out,"%t:",$time); + $fwrite(Q_out, "credit %s:%h Port %0d\n",DIRECTION, chan_in[p].credit,p); + $fclose(Q_out); end end end diff --git a/mpsoc/rtl/src_noc/routing.v b/mpsoc/rtl/src_noc/routing.v index a514c90..58a9273 100755 --- a/mpsoc/rtl/src_noc/routing.v +++ b/mpsoc/rtl/src_noc/routing.v @@ -462,8 +462,8 @@ module next_router_addr_selector_onehot #( .W(RXw), .N(P) ) next_x_mux ( - .in(neighbors_rx), - .out(next_rx), + .D_in(neighbors_rx), + .Q_out(next_rx), .sel(destport_onehot) ); @@ -471,8 +471,8 @@ module next_router_addr_selector_onehot #( .W(RYw), .N(P) ) next_y_mux ( - .in(neighbors_ry), - .out(next_ry), + .D_in(neighbors_ry), + .Q_out(next_ry), .sel(destport_onehot) ); endmodule diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index af1f879..553936a 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -160,8 +160,8 @@ module ss_allocator #( for(i=0;i weight_i) | load_i; - assign out = couner_zero; + assign Q_out = couner_zero; assign weight= (weight_i == {WEIGHTw{1'b0}} )? 1 : weight_i; // minimum weight is 1; always @(*)begin counter_next = counter; @@ -190,7 +190,7 @@ module weight_counter #( if(decr) counter_next = (couner_zero)? weight-1'b1 : counter - 1'b1; // if the couner has zero value then the load is active not decrese end - pronoc_register #(.W(WEIGHTw)) reg2 (.in(counter_next ), .out(counter), .reset(reset), .clk(clk)); + pronoc_register #(.W(WEIGHTw)) reg2 (.D_in(counter_next ), .Q_out(counter), .reset(reset), .clk(clk)); endmodule @@ -204,30 +204,30 @@ module classic_weight_counter #( weight_i, decr, load_i, - out, + Q_out, reset, clk ); input [WEIGHTw-1 : 0] weight_i; input reset,clk,decr,load_i; - output out; + output Q_out; wire [WEIGHTw-1 : 0] weight; reg [WEIGHTw-1 : 0] counter_next; wire [WEIGHTw-1 : 0] counter; - wire couner_zero, load; + wire counter_zero, load; - assign couner_zero = counter == {WEIGHTw{1'b0}}; + assign counter_zero = counter == {WEIGHTw{1'b0}}; assign load = (counter > weight_i) | load_i; - assign out = couner_zero; + assign Q_out = counter_zero; assign weight= (weight_i == {WEIGHTw{1'b0}} )? 1 : weight_i; // minimum weight is 1; always @(*)begin counter_next = counter; if(load) counter_next = weight- 1'b1 ; - if(decr && !couner_zero) counter_next = counter - 1'b1; // if the couner has zero value then the load is active not decrese + if(decr && !counter_zero) counter_next = counter - 1'b1; // if the counter has zero value then the load is active not decrese end - pronoc_register #(.W(WEIGHTw)) reg2 (.in(counter_next ), .out(counter), .reset(reset), .clk(clk)); + pronoc_register #(.W(WEIGHTw)) reg2 (.D_in(counter_next ), .Q_out(counter), .reset(reset), .clk(clk)); endmodule @@ -298,7 +298,7 @@ module weight_control #( genvar i; generate if(PROPOGATE_EQUALL | PROPOGATE_LIMITED )begin : eq - for (i=1;i 0 && start) begin @@ -54,10 +54,10 @@ module freq_gen ( * easy solution to returning floating point numbers. */ out_period_length_1000 <= ((ref_period_1000 / 1000.0) * ((D * (O_1000 / 1000.0) * 1.0) / (M_1000 / 1000.0)) * 1000); - out <= ~out; + Q_out <= ~Q_out; #(((ref_period_1000 / 1000.0) * ((D * (O_1000 / 1000.0) * 1.0) / (M_1000 / 1000.0))) / 2.0); end else begin - out <= 1'b0; + Q_out <= 1'b0; #1; end end diff --git a/mpsoc/rtl/src_peripheral/clk_source/xilinx_pll/xilinx_pll_sim/plle2_base_sim.v b/mpsoc/rtl/src_peripheral/clk_source/xilinx_pll/xilinx_pll_sim/plle2_base_sim.v index 65159cf..def2c59 100644 --- a/mpsoc/rtl/src_peripheral/clk_source/xilinx_pll/xilinx_pll_sim/plle2_base_sim.v +++ b/mpsoc/rtl/src_peripheral/clk_source/xilinx_pll/xilinx_pll_sim/plle2_base_sim.v @@ -157,7 +157,7 @@ module plle2_base_sim #( .period_length((clkin_period_length_1000 / 1000.0)), .period_stable(period_stable)); - wire out[0:6]; + wire Q_out[0:6]; wire [31:0] out_period_length_1000[0:6]; wire lock[0:6]; @@ -175,7 +175,7 @@ module plle2_base_sim #( .period_stable(period_stable), .ref_period_1000((clkin_period_length_1000)), .clk(clkin), - .out(out[i]), + .Q_out(Q_out[i]), .out_period_length_1000(out_period_length_1000[i])); end endgenerate @@ -186,7 +186,7 @@ module plle2_base_sim #( phase_shift ps ( .RST(RST), .PWRDWN(PWRDWN), - .clk(out[i]), + .clk(Q_out[i]), .shift_1000(CLKOUT_PHASE_INT_1000[i] + CLKFBOUT_PHASE_INT_1000), .duty_cycle(CLKOUT_DUTY_CYCLE_INT_1000[i] / 10), .clk_period_1000(out_period_length_1000[i]), @@ -209,7 +209,7 @@ module plle2_base_sim #( .period_stable(period_stable), .ref_period_1000((clkin_period_length_1000)), .clk(clkin), - .out(fb_out), + .Q_out(fb_out), .out_period_length_1000(fb_out_period_length_1000)); phase_shift fb_ps ( diff --git a/mpsoc/rtl/src_peripheral/jtag/jtag_wb/xilinx_jtag_wb.v b/mpsoc/rtl/src_peripheral/jtag/jtag_wb/xilinx_jtag_wb.v index d742fc9..ae3f3f0 100644 --- a/mpsoc/rtl/src_peripheral/jtag/jtag_wb/xilinx_jtag_wb.v +++ b/mpsoc/rtl/src_peripheral/jtag/jtag_wb/xilinx_jtag_wb.v @@ -64,7 +64,7 @@ module xilinx_jtag_wb #( input reset;//,clk; output reg cpu_en, system_reset; - // output [7: 0 ] out; + // output [7: 0 ] Q_out; input [JWB_NUM*WB2Jw-1 : 0] wb_to_jtag_all; output[JWB_NUM*J2WBw-1 : 0] jtag_to_wb_all; @@ -127,8 +127,8 @@ module xilinx_jtag_wb #( ( .clk(clk), .jtag_clk(tclk), - .in(wb_to_jtag_ack_all[i]), - .out(wb_to_jtag_ack_all_latched[i]) + .D_in(wb_to_jtag_ack_all[i]), + .Q_out(wb_to_jtag_ack_all_latched[i]) ); @@ -277,32 +277,32 @@ endmodule module wb_to_jtag_latch ( clk, jtag_clk, - in, - out + D_in, + Q_out ); - input clk,jtag_clk,in; - output out; - + input clk,jtag_clk,D_in; + output Q_out; + reg out_latch,reset_out; always @ (posedge clk) begin - if(in) out_latch<=1'b1; + if(D_in) out_latch<=1'b1; else if(reset_out) out_latch<=1'b0; end always @(posedge jtag_clk)begin - if(out_latch | in) reset_out<=1'b1; + if(out_latch | D_in) reset_out<=1'b1; else reset_out<=1'b0; end - - - assign out = reset_out ; - - + + + assign Q_out = reset_out ; + + endmodule diff --git a/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v b/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v old mode 100644 new mode 100755 index 0cdb1aa..16708f1 --- a/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v +++ b/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/arbiter.v @@ -181,88 +181,88 @@ module my_one_hot_arbiter #( end assign any_grant = | request; generate - if(ARBITER_WIDTH ==2) begin: w2 arbiter_2_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==3) begin: w3 arbiter_3_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==4) begin: w4 arbiter_4_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==2) begin: w2 arbiter_2_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==3) begin: w3 arbiter_3_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==4) begin: w4 arbiter_4_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end endgenerate endmodule module arbiter_2_one_hot( - input [1 : 0] in, - output reg[1 : 0] out, + input [1 : 0] D_in, + output reg[1 : 0] Q_out, input low_pr ); always @(*) begin - out=2'b00; + Q_out=2'b00; case(low_pr) 1'd0: - if(in[1]) out=2'b10; - else if(in[0]) out=2'b01; + if(D_in[1]) Q_out=2'b10; + else if(D_in[0]) Q_out=2'b01; 1'd1: - if(in[0]) out=2'b01; - else if(in[1]) out=2'b10; - default: out=2'b00; + if(D_in[0]) Q_out=2'b01; + else if(D_in[1]) Q_out=2'b10; + default: Q_out=2'b00; endcase end endmodule module arbiter_3_one_hot( - input [2 : 0] in, - output reg[2 : 0] out, + input [2 : 0] D_in, + output reg[2 : 0] Q_out, input [1 : 0] low_pr ); always @(*) begin - out=3'b000; + Q_out=3'b000; case(low_pr) 2'd0: - if(in[1]) out=3'b010; - else if(in[2]) out=3'b100; - else if(in[0]) out=3'b001; + if(D_in[1]) Q_out=3'b010; + else if(D_in[2]) Q_out=3'b100; + else if(D_in[0]) Q_out=3'b001; 2'd1: - if(in[2]) out=3'b100; - else if(in[0]) out=3'b001; - else if(in[1]) out=3'b010; + if(D_in[2]) Q_out=3'b100; + else if(D_in[0]) Q_out=3'b001; + else if(D_in[1]) Q_out=3'b010; 2'd2: - if(in[0]) out=3'b001; - else if(in[1]) out=3'b010; - else if(in[2]) out=3'b100; - default: out=3'b000; + if(D_in[0]) Q_out=3'b001; + else if(D_in[1]) Q_out=3'b010; + else if(D_in[2]) Q_out=3'b100; + default: Q_out=3'b000; endcase end endmodule module arbiter_4_one_hot( - input [3 : 0] in, - output reg[3 : 0] out, + input [3 : 0] D_in, + output reg[3 : 0] Q_out, input [1 : 0] low_pr ); always @(*) begin - out=4'b0000; + Q_out=4'b0000; case(low_pr) 2'd0: - if(in[1]) out=4'b0010; - else if(in[2]) out=4'b0100; - else if(in[3]) out=4'b1000; - else if(in[0]) out=4'b0001; + if(D_in[1]) Q_out=4'b0010; + else if(D_in[2]) Q_out=4'b0100; + else if(D_in[3]) Q_out=4'b1000; + else if(D_in[0]) Q_out=4'b0001; 2'd1: - if(in[2]) out=4'b0100; - else if(in[3]) out=4'b1000; - else if(in[0]) out=4'b0001; - else if(in[1]) out=4'b0010; + if(D_in[2]) Q_out=4'b0100; + else if(D_in[3]) Q_out=4'b1000; + else if(D_in[0]) Q_out=4'b0001; + else if(D_in[1]) Q_out=4'b0010; 2'd2: - if(in[3]) out=4'b1000; - else if(in[0]) out=4'b0001; - else if(in[1]) out=4'b0010; - else if(in[2]) out=4'b0100; + if(D_in[3]) Q_out=4'b1000; + else if(D_in[0]) Q_out=4'b0001; + else if(D_in[1]) Q_out=4'b0010; + else if(D_in[2]) Q_out=4'b0100; 2'd3: - if(in[0]) out=4'b0001; - else if(in[1]) out=4'b0010; - else if(in[2]) out=4'b0100; - else if(in[3]) out=4'b1000; - default: out=4'b0000; + if(D_in[0]) Q_out=4'b0001; + else if(D_in[1]) Q_out=4'b0010; + else if(D_in[2]) Q_out=4'b0100; + else if(D_in[3]) Q_out=4'b1000; + default: Q_out=4'b0000; endcase end endmodule @@ -312,9 +312,9 @@ module my_one_hot_arbiter_priority_en #( assign any_grant = | request; generate - if(ARBITER_WIDTH ==2) begin : w2 arbiter_2_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==3) begin : w3 arbiter_3_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end - if(ARBITER_WIDTH ==4) begin : w4 arbiter_4_one_hot arb( .in(request) , .out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==2) begin : w2 arbiter_2_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==3) begin : w3 arbiter_3_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end + if(ARBITER_WIDTH ==4) begin : w4 arbiter_4_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end endgenerate endmodule @@ -326,13 +326,13 @@ endmodule module thermo_gen #( parameter WIDTH=16 )( - input [WIDTH-1 : 0]in, - output [WIDTH-1 : 0]out + input [WIDTH-1 : 0]D_in, + output [WIDTH-1 : 0]Q_out ); genvar i; generate for(i=0;i. +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ** ** -** Description: -** This file contains several general RTL modules such as -** different types of multiplexors, converters and counters ... +** Description: +** This file contains several general RTL modules such as +** different types of multiplexors, converters and counters ... ** **************************************************************/ +`ifndef PRONOC_COMMON +`define PRONOC_COMMON + +module pronoc_register #( + parameter W=1, + parameter RESET_TO={W{1'b0}} +)( + input [W-1: 0] D_in, + input reset, + input clk, + output [W-1: 0] Q_out +); + pronoc_register_reset_init #( + .W(W) + )reg1( + .D_in(D_in), + .reset(reset), + .clk(clk), + .Q_out(Q_out), + .reset_to(RESET_TO[W-1 : 0]) + ); +endmodule +module pronoc_register_reset_init #( + parameter W=1 +)( + input [W-1: 0] D_in, + input reset, + input clk, + output reg [W-1: 0] Q_out, + input [W-1 : 0] reset_to +); + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) Q_out<=reset_to; + else Q_out<=D_in; + end +endmodule +module pronoc_register_reset_init_ld_en #( + parameter W=1 +)( + input [W-1: 0] D_in, + input reset, + input clk, + input ld, + output reg [W-1: 0] Q_out, + input [W-1 : 0] reset_to +); + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) Q_out<=reset_to; + else if(ld) Q_out<=D_in; + end +endmodule - -/********************************* - +module pronoc_register_ld_en #( + parameter W=1, + parameter RESET_TO={W{1'b0}} +)( + input [W-1: 0] D_in, + input reset, + input clk, + input ld, + output [W-1: 0] Q_out +); + pronoc_register_reset_init_ld_en #( + .W(W) + )reg1( + .D_in(D_in), + .reset(reset), + .clk(clk), + .ld(ld), + .Q_out(Q_out), + .reset_to(RESET_TO[W-1 : 0]) + ); +endmodule - multiplexer - - +/********************************* +* multiplexer ********************************/ - module one_hot_mux #( - parameter IN_WIDTH = 20, - parameter SEL_WIDTH = 5, - parameter OUT_WIDTH = IN_WIDTH/SEL_WIDTH - - ) - ( - input [IN_WIDTH-1 :0] mux_in, - output[OUT_WIDTH-1 :0] mux_out, - input[SEL_WIDTH-1 :0] sel - - ); - - wire [IN_WIDTH-1 :0] mask; - wire [IN_WIDTH-1 :0] masked_mux_in; - wire [SEL_WIDTH-1:0] mux_out_gen [OUT_WIDTH-1:0]; + parameter IN_WIDTH = 20, + parameter SEL_WIDTH = 5, + parameter OUT_WIDTH = IN_WIDTH/SEL_WIDTH +)( + input [IN_WIDTH-1 : 0] mux_in, + output[OUT_WIDTH-1 : 0] mux_out, + input[SEL_WIDTH-1 : 0] sel +); + wire [IN_WIDTH-1 : 0] mask; + wire [IN_WIDTH-1 : 0] masked_mux_in; + wire [SEL_WIDTH-1: 0] mux_out_gen [OUT_WIDTH-1: 0]; genvar i,j; - //first selector masking generate // first_mask = {sel[0],sel[0],sel[0],....,sel[n],sel[n],sel[n]} for(i=0; i1)? log2(ONE_HOT_WIDTH):1 -) -( - input [ONE_HOT_WIDTH-1 : 0] one_hot_code, - output [BIN_WIDTH-1 : 0] bin_code - + parameter ONE_HOT_WIDTH = 4, + parameter BIN_WIDTH = (ONE_HOT_WIDTH > 1) ? $clog2(ONE_HOT_WIDTH) : 1 +)( + input [ONE_HOT_WIDTH-1 : 0] one_hot_code, + output [BIN_WIDTH-1 : 0] bin_code ); - - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21)begin :if1 for(i=0; i1)? log2(IN_NUM): 1; - - - input [IN_WIDTH-1 :0] mux_in; - output [OUT_WIDTH-1 :0] mux_out; - input [SEL_WIDTH_BIN-1 :0] sel; + parameter IN_WIDTH = 20, + parameter OUT_WIDTH = 5 +)( + mux_in, + mux_out, + sel +); + localparam + IN_NUM = IN_WIDTH / OUT_WIDTH, + SEL_WIDTH_BIN = (IN_NUM > 1) ? $clog2(IN_NUM) : 1; + input [IN_WIDTH-1 : 0] mux_in; + output [OUT_WIDTH-1 : 0] mux_out; + input [SEL_WIDTH_BIN-1 : 0] sel; genvar i; - - - generate - if(IN_NUM>1) begin :if1 - wire [OUT_WIDTH-1 :0] mux_in_2d [IN_NUM -1 :0]; - for (i=0; i< IN_NUM; i=i+1) begin : loop - assign mux_in_2d[i] =mux_in[((i+1)*OUT_WIDTH)-1 : i*OUT_WIDTH]; - end - assign mux_out = mux_in_2d[sel]; - end else begin :els - assign mux_out = mux_in; - end - endgenerate - + generate + if(IN_NUM > 1) begin + wire [OUT_WIDTH-1 : 0] mux_in_2d [IN_NUM -1 : 0]; + for (i=0; i< IN_NUM; i=i+1) begin : loop + assign mux_in_2d[i] = mux_in[((i+1)*OUT_WIDTH)-1 : i*OUT_WIDTH]; + end + assign mux_out = mux_in_2d[sel]; + end else begin + assign mux_out = mux_in; + end + endgenerate endmodule -/****************************** - - set_bits_counter - -*******************************/ - - -module set_bits_counter #( - parameter IN_WIDTH =120, - parameter OUT_WIDTH = log2(IN_WIDTH+1) - ) - ( - input [IN_WIDTH-1 : 0] in, - output [OUT_WIDTH-1 : 0] out - +module accumulator #( + parameter INw= 20, + parameter OUTw=4, + parameter NUM =5 +)( + in_all, + sum_o ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 OUTw) begin : bigger + assign sum_o = (sum[SUMw-1 : OUTw] > 0 ) ? {OUTw{1'b1}} : sum[OUTw-1 : 0] ; + end else begin : less + assign sum_o = {{(OUTw-SUMw){1'b0}}, sum} ; + end endgenerate - + // This is supposed to be synyhesized as "sum=in[0]+in[1]+...in[Num-1]"; + // It works with Quartus, Verilator and Modelsim compilers + integer k; + always @(*)begin + sum = {SUMw{1'b0}}; + for (k=0;k1) for(i=0; ij) begin :if1 assign comp_array [i][j] = ~ comp_array [j][i-1]; end else begin :els assign comp_array [i] [j] = numbers[i]<= numbers[j+1]; end end//for j - assign min_out[i]= & comp_array[i]; + assign min_out[i]= & comp_array[i]; end//for i end//else endgenerate - endmodule -/******************************************** - - Carry-based reduction parallel counter - - -********************************************/ -module parallel_counter #( - parameter IN_WIDTH =120 // max 127 -) -( - in, - out -); - - - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 IN_WIDTH ) begin :w1 - assign pc_in = {{(PCIw-IN_WIDTH){1'b0}},in}; - end else begin:els - assign pc_in=in; - end // if - - if(PCIw == 7) begin :w7 - - PC_7_3 pc ( - .in(pc_in), - .out(pc_out) - ); - - end else if(PCIw == 15) begin :w15 - PC_15_4 pc ( - .in(pc_in), - .out(pc_out) - ); - - end else if(PCIw == 31) begin :w31 - PC_31_5 pc ( - .in(pc_in), - .out(pc_out) - ); - end else if(PCIw == 63) begin :w63 - PC_63_6 pc ( - .in(pc_in), - .out(pc_out) - ); - - end else begin :w127 - PC_127_7 pc ( - .in(pc_in), - .out(pc_out) - ); - end - - endgenerate - - assign out = pc_out[OUT_WIDTH-1 : 0]; - -endmodule - - - -//carry-sum generation blocks -module CS_GEN ( - in, - abc, - s -); - input [6 : 0] in; - output s; - output [2 : 0] abc; - - wire a,b,c,s; - wire [3 : 0] in1; - wire [2 : 0] in2; - wire [2 : 0] j1; - wire [1 : 0] j2; - - assign {in2,in1} = in; - assign j1= in1[3]+in1[2]+in1[1]+in1[0]; - assign j2= in2[2]+in2[1]+in2[0]; - - //s is asserted when both in1 and in2 have odd number of ones. - assign s = j1[0] ^ j2[0]; - // a is asserted when there are at least two ones in in1 (i.e., j1 >= 2); - assign a = (j1 > 3'd1); - - //b is asserted when there are at least two ones in in2 (i.e., j2 >= 2); - assign b = (j2 > 2'd1); - - // C is asserted when when j1 equals 4 or when s is asserted - assign c = (j1==4) | (j1[0] & j2[0]); - - assign abc = {a,b,c}; -endmodule - -/************************* - - (7,3) parallel counter - -*************************/ - -module PC_7_3 ( - in, - out - -); - input [6 : 0] in; - output [2 : 0] out; - - wire [2 : 0] abc; - - CS_GEN cs( - .in(in), - .abc(abc), - .s(out[0]) - ); - - assign out[2:1] = abc[2]+abc[1]+abc[0]; - - - - -endmodule - -/************************* - - (15,4) parallel counter - -*************************/ - -module PC_15_4 ( - in, - out - -); - input [14 : 0] in; - output [3 : 0] out; - - wire [2:0] abc0,abc1; - wire s0,s1,b2; - - CS_GEN cs0( - .in (in [6 : 0]), - .abc (abc0), - .s (s0) - ); - - CS_GEN cs1( - .in (in [13 : 7]), - .abc (abc1), - .s (s1) - ); - - assign {b2,out[0]} =in [14] + s0 +s1; - - PC_7_3 pc_sub( - .in({abc0,abc1,b2}), - .out(out[3:1]) - ); - - - - -endmodule - - -// (31,5) parallel counter -module PC_31_5 ( - in, - out - -); - localparam CS_NUM = 5; - - input [30 : 0] in; - output [4 : 0] out; - - - wire [CS_NUM-1 : 0] s; - wire [(CS_NUM*7)-1 : 0] cs_in; - wire [14 : 0] pc_15_in; - - assign cs_in ={s[3:0] ,in }; - - genvar i; - generate - for (i=0;i 2) begin :l1 + always @(*)begin + if(NC[0]==1'b0)begin // odd + start_o_next={start_o[NC-3: 0],start_o[NC-2],start}; + end else begin //even + start_o_next={start_o[NC-3: 0],start_o[NC-1],start}; + end + end + end else begin :l2 + always @(*) start_o_next = {NC{start}}; + end endgenerate - assign {out[0]} = s[20]; - - PC_63_6 pc63( - .in(pc_63_in), - .out(out[6:1]) - ); - - - endmodule - - - - - + reg [2: 0] counter; + assign cnt_increase=(counter==3'd0); + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + start_o_reg <= {NC{1'b0}}; + start_i_reg <= 1'b0; + counter <= 3'd0; + end else begin + counter <= counter+3'd1; + start_i_reg <= start_i; + if(cnt_increase | start) start_o_reg <= start_o_next; + + end//reset + end //always + assign start_o=(cnt_increase | start)? start_o_reg : {NC{1'b0}}; +endmodule +`endif \ No newline at end of file From 5ac7610bbcf42b9c6b57cd99940aac44bbaff1c7 Mon Sep 17 00:00:00 2001 From: amonemi Date: Fri, 6 Jun 2025 19:22:06 +0200 Subject: [PATCH 038/107] fix UseSVAlways-ML --- mpsoc/rtl/arch/iport_reg_base.sv | 2 +- mpsoc/rtl/src_emulate/rtl/noc_emulator.sv | 8 ++++---- mpsoc/rtl/src_modelsim/multicast_injector.sv | 2 +- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 12 ++++++------ mpsoc/rtl/src_noc/flit_buffer.sv | 20 ++++++++++---------- mpsoc/rtl/src_noc/fmesh.sv | 6 +++--- mpsoc/rtl/src_noc/header_flit.sv | 2 +- mpsoc/rtl/src_noc/inout_ports.sv | 4 ++-- mpsoc/rtl/src_noc/input_ports.sv | 8 ++++---- mpsoc/rtl/src_noc/mesh_torus.sv | 8 ++++---- mpsoc/rtl/src_noc/multicast.sv | 16 ++++++++-------- mpsoc/rtl/src_noc/output_ports.sv | 4 ++-- mpsoc/rtl/src_noc/ovc_list.sv | 6 +++--- mpsoc/rtl/src_noc/packet_injector.sv | 6 +++--- mpsoc/rtl/src_noc/router_bypass.sv | 6 +++--- mpsoc/rtl/src_noc/router_top.sv | 2 +- mpsoc/rtl/src_noc/ss_allocator.sv | 6 +++--- mpsoc/rtl/src_noc/traffic_gen_top.sv | 8 ++++---- mpsoc/rtl/src_openpiton/piton_mesh.sv | 2 +- mpsoc/rtl/src_openpiton/wrapper.sv | 16 ++++++++-------- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 6 +++--- 21 files changed, 75 insertions(+), 75 deletions(-) diff --git a/mpsoc/rtl/arch/iport_reg_base.sv b/mpsoc/rtl/arch/iport_reg_base.sv index 3a7988a..5acd50c 100644 --- a/mpsoc/rtl/arch/iport_reg_base.sv +++ b/mpsoc/rtl/arch/iport_reg_base.sv @@ -238,7 +238,7 @@ module iport_reg_base #( .Q_out(iport_weight )); - always @ (*)begin + always_combbegin iport_weight_next = iport_weight; if(hdr_flit_wr != {V{1'b0}}) iport_weight_next = (weight_in=={WEIGHTw{1'b0}})? 1 : weight_in; // the minimum weight is 1 end diff --git a/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv b/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv index 3d68b2b..5beee7a 100644 --- a/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv +++ b/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv @@ -412,7 +412,7 @@ module traffic_gen_ram .mcast_dst_num_o() ); - always @ (*)begin + always_combbegin case (statistic_jtag_addr_b) SENT_PCK_ADDR: statistic_jtag_q_b= total_pck_sent; RSVD_PCK_ADDR: statistic_jtag_q_b= total_pck_recieved; @@ -422,7 +422,7 @@ module traffic_gen_ram endcase end - always @ (*)begin + always_combbegin ns=ps; addr_a_next = addr_a; pck_number_sent_next = pck_number_sent; @@ -608,13 +608,13 @@ module jtag_emulator_controller #( end end - always @(*)begin + always_combbegin wb_addr_next= wb_addr; if(wb_wr_addr_en) wb_addr_next = data_out [Aw-1 : 0]; else if (wb_addr_inc) wb_addr_next = wb_addr + 1'b1; end - always @(*)begin + always_combbegin ns=ps; wr_mem_en =1'b0; wb_addr_inc=1'b0; diff --git a/mpsoc/rtl/src_modelsim/multicast_injector.sv b/mpsoc/rtl/src_modelsim/multicast_injector.sv index 0dc43c1..e2a2577 100644 --- a/mpsoc/rtl/src_modelsim/multicast_injector.sv +++ b/mpsoc/rtl/src_modelsim/multicast_injector.sv @@ -114,7 +114,7 @@ module multicast_injector #( .sel (pck_injct_in.vc) ); - always @ (*) begin + always_comb begin counter_next = counter; counter2_next =counter2; flit_type_next =flit_type; diff --git a/mpsoc/rtl/src_modelsim/traffic_pattern.sv b/mpsoc/rtl/src_modelsim/traffic_pattern.sv index 6974dab..14e9300 100755 --- a/mpsoc/rtl/src_modelsim/traffic_pattern.sv +++ b/mpsoc/rtl/src_modelsim/traffic_pattern.sv @@ -48,7 +48,7 @@ module pck_class_in_gen #( end end - always @(*) begin + always_comb begin if ( rnd < C0_p) pck_class_o =0; else if ( rnd < (C0_p+C1_p)) pck_class_o =1; else if ( rnd < (C0_p+C1_p+C2_p)) pck_class_o =2; @@ -185,7 +185,7 @@ module pck_dst_gen #( if(CAST_TYPE == "MULTICAST_FULL") begin :mful - always @( * ) begin + always_comb begin multicast_dest_e_addr = {DAw{1'b0}}; temp={DAw{1'b0}}; temp[unicast_id_num]=1'b1; @@ -205,7 +205,7 @@ module pck_dst_gen #( end else if(CAST_TYPE == "MULTICAST_PARTIAL") begin :mpar - always @( * ) begin + always_comb begin multicast_dest_e_addr = {DAw{1'b0}}; temp={unicast_dest_e_addr,1'b1}; pck_siz_tmp= pck_size_uni; @@ -227,7 +227,7 @@ module pck_dst_gen #( end else begin //Broadcast - always @( * ) begin + always_comb begin multicast_dest_e_addr = {DAw{1'b0}}; pck_siz_tmp = pck_size_uni; if(rnd_reg >= MCAST_TRAFFIC_RATIO) begin @@ -748,7 +748,7 @@ module pck_size_gen reg [PCK_SIZw-1 : 0] rnd,rnd_next; integer rnd2; integer k; - always @(*) begin + always_comb begin rnd_next = rnd; if(en) begin if(rnd2 < rnd_discrete[0].percentage) rnd_next = rnd_discrete[0].value; @@ -819,7 +819,7 @@ module hot_spot_dest_gen end logic hotspot_flag; integer i; - always @(*)begin + always_combbegin off_flag=0; for (i=0;i dest_x)? src_x - dest_x : dest_x - src_x; y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; end diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index 0c24b44..4f689d3 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -298,7 +298,7 @@ module header_flit_update_lk_route_ovc #( */ end - always @(*)begin + always_combbegin flit_out = {flit_in[Fw-1 : Fw-2],ovc_num,flit_in[FPAYw-1 :0]}; if(hdr_flag) flit_out[DST_P_MSB : DST_P_LSB]= dest_coded; end diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index 40319f7..0b629f2 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -390,7 +390,7 @@ module output_vc_status #( .reset_to(credit_init_val_in[i][DEPTH_WIDTH-1:0]) ); - always @ ( * )begin + always_combbegin credit_next[i] = credit [i]; if( wr_in[i] && ~credit_in[i]) credit_next[i] = credit[i]-1'b1; if( ~wr_in[i] && credit_in[i]) credit_next[i] = credit[i]+1'b1; @@ -418,7 +418,7 @@ module output_vc_status #( logic [V-1 : 0] cand_vc_ld_next; pronoc_register #(.W(V)) reg2 (.D_in(cand_vc_ld_next ), .Q_out(cand_vc), .reset(reset), .clk(clk)); - always @ ( *) begin + always_comb begin cand_vc_ld_next = cand_vc; if(cand_wr_vc_en) cand_vc_ld_next = cand_vc_next; end diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 3b6b0f4..d9cb0a5 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -374,7 +374,7 @@ module input_queue_per_port #( .clk (clk), .Q_out (credit_out)); - always @ (*)begin + always_combbegin iport_weight_next = iport_weight; if(hdr_flit_wr != {V{1'b0}}) iport_weight_next = (weight_in=={WEIGHTw{1'b0}})? WEIGHT_INIT : weight_in; // the minimum weight is 1 end @@ -542,7 +542,7 @@ module input_queue_per_port #( end if(PCK_TYPE == "MULTI_FLIT") begin : multi_flit - always @ (*) begin + always_comb begin ovc_is_assigned_next[i] = ovc_is_assigned[i]; if( vsa_ctrl_in.ivc_reset[i] | ssa_ctrl_in.ivc_reset[i] | @@ -554,7 +554,7 @@ module input_queue_per_port #( ) ovc_is_assigned_next[i] = 1'b1; end//always - always @(*) begin + always_comb begin assigned_ovc_num_next[(i+1)*V-1 : i*V] = assigned_ovc_num[(i+1)*V-1 : i*V] ; if(vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | ssa_ctrl_in.ivc_num_getting_ovc_grant[i] | smart_ctrl_in.ivc_num_getting_ovc_grant[i] ) begin assigned_ovc_num_next[(i+1)*V-1 : i*V] = mux_out[i]; @@ -598,7 +598,7 @@ module input_queue_per_port #( //assign flit_is_tail[i]=1'b1; assign ovc_is_assigned_next[i] = 1'b0; - always @(*) begin + always_comb begin assigned_ovc_num_next[(i+1)*V-1 : i*V] = assigned_ovc_num[(i+1)*V-1 : i*V] ; if(vsa_ctrl_in.ivc_num_getting_ovc_grant[i] | ssa_ctrl_in.ivc_num_getting_ovc_grant[i]) begin assigned_ovc_num_next[(i+1)*V-1 : i*V] = mux_out[i]; diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index eb13dbe..83c96c7 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -713,14 +713,14 @@ module mesh_torus_distance_gen ( reg [Yw-1 : 0] y_offset; generate if( IS_MESH | IS_LINE) begin : oneD - always @(*) begin + always_comb begin x_offset = (src_x> dest_x)? src_x - dest_x : dest_x - src_x; y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; end end else begin : twoD //torus ring wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y; /* verilator lint_off WIDTH */ - always @ (*) begin + always_comb begin x_offset= {Xw{1'b0}}; y_offset= {Yw{1'b0}}; //x_offset @@ -1221,7 +1221,7 @@ module mesh_torus_destp_decoder #( if( ROUTE_TYPE == "DETERMINISTIC") begin :dtrmn wire x,y,a,b; assign {x,y,a,b} = dest_port_coded; - always @(*)begin + always_combbegin case({a,b}) 2'b10 : portout = {1'b0,~x,1'b0,x,1'b0}; 2'b01 : portout = {~y,1'b0,y,1'b0,1'b0}; @@ -1234,7 +1234,7 @@ module mesh_torus_destp_decoder #( assign {x,y,a,b} = dest_port_coded; wire [PPSw-1:0] port_pre_sel_final; assign port_pre_sel_final= (swap_port_presel)? ~port_pre_sel: port_pre_sel; - always @(*)begin + always_combbegin case({a,b}) 2'b10 : portout = {1'b0,~x,1'b0,x,1'b0}; 2'b01 : portout = {~y,1'b0,y,1'b0,1'b0}; diff --git a/mpsoc/rtl/src_noc/multicast.sv b/mpsoc/rtl/src_noc/multicast.sv index add786b..e963a4b 100644 --- a/mpsoc/rtl/src_noc/multicast.sv +++ b/mpsoc/rtl/src_noc/multicast.sv @@ -157,7 +157,7 @@ module multicast_routing_mesh #( assign goto_local[i] = |(local_p[i] & dest_mcast_all_endp);// will be synthesized as single bit assign end//for reg [4 : 0] destport_tmp; - always @(*) begin + always_comb begin destport_tmp = {5{1'b0}}; destport_tmp[LOCAL]=goto_local[LOCAL]; if (SW_LOC == SOUTH) destport_tmp [NORTH] = goto_north; @@ -303,7 +303,7 @@ module multicast_routing_fmesh #( wire goto_west = (|(x_plus & row_has_any_dest)) | goto_local[WEST]; reg [4 : 0] destport_tmp; - always @(*) begin + always_comb begin destport_tmp = {DSTPw{1'b0}}; destport_tmp[LOCAL]=goto_local[LOCAL]; if (SW_LOC == SOUTH)begin @@ -392,7 +392,7 @@ module mcast_dest_list_decode #( .id(unicast_id) ); - always @(*)begin + always_combbegin dest_o_uni = {NE{1'b0}}; dest_o_uni[unicast_id]=1'b1; end @@ -424,7 +424,7 @@ module mcast_dest_list_decode #( .id(unicast_id) ); - always @(*)begin + always_combbegin dest_o_uni = {NE{1'b0}}; dest_o_uni[unicast_id]=1'b1; end @@ -451,7 +451,7 @@ module mcast_dest_list_decode #( .id(unicast_id) ); - always @(*)begin + always_combbegin dest_o_uni = {NE{1'b0}}; dest_o_uni[unicast_id]=1'b1; end @@ -526,7 +526,7 @@ module multicast_chan_in_process #( assign row_has_any_dest[i] =| endp_mask[i]; end reg [DSTPw-1 : 0] destport_tmp; - always @(*) begin + always_comb begin destport_tmp = destport; if(SELF_LOOP_EN == 0) destport_tmp [ SW_LOC ] = 1'b0; end @@ -567,7 +567,7 @@ module multicast_chan_in_process #( else assign row_has_any_dest_endp_port[i] =(| endp_mask[i]) | north_endps[i] | south_endps[i]; end reg [DSTPw-1 : 0] destport_tmp; - always @(*) begin + always_comb begin destport_tmp = destport; if(SELF_LOOP_EN == 0) destport_tmp [ SW_LOC ] = 1'b0; end @@ -588,7 +588,7 @@ module multicast_chan_in_process #( .dest_e_addr(dest_e_addr), // destination endpoint address .destport(destport) ); - always @(*) begin + always_comb begin chan_out=chan_in; if(chan_in.flit.hdr_flag == 1'b1) begin chan_out.flit [E_DST_MSB : E_DST_LSB] = dest_e_addr; diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index a695782..3f4f1b6 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -134,7 +134,7 @@ module output_ports #( if(ROUTE_TYPE == "FULL_ADAPTIVE") begin :full_adpt /* verilator lint_on WIDTH */ reg [PV-1 : 0] full_adaptive_ovc_mask,full_adaptive_ovc_mask_next; - always @(*) begin + always_comb begin for(k=0; k V )begin :b2 for (i=0;i {V{1'b0}} ) endp_is_active=1'b1; diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index 95af01b..7ccbd61 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -358,7 +358,7 @@ module smart_bypass_chanels #( if(SS_PORT != DISABLE) begin: ssp //smart_chanel_shifter assign smart_forwardable[i] = | (ivc_forwardable[i] & smart_chanel_in[i].ovc); - always @(*) begin + always_comb begin smart_chanel_shifted[i] = smart_chanel_in [i]; {smart_chanel_shifted[i].requests,rq[i]} =(smart_forwardable[i])? {1'b0,smart_chanel_in[i].requests}:{{SMART_NUM{1'b0}},smart_chanel_in[i].requests[0]}; smart_chanel_shifted[i].bypassed_num = smart_chanel_in [i].bypassed_num +1'b1; @@ -491,7 +491,7 @@ module smart_validity_check_per_ivc #( output reg [V-1 : 0] smart_ivc_granted_ovc_num_o; - always @(*) begin + always_comb begin smart_ivc_granted_ovc_num_o={V{1'b0}}; smart_ivc_granted_ovc_num_o[IVC_NUM]=smart_ivc_num_getting_ovc_grant_o; end @@ -754,7 +754,7 @@ module smart_credit_manage_per_vc #( output credit_out; logic [Bw : 0] counter, counter_next; - always @(*) begin + always_comb begin counter_next=counter; if(credit_in & smart_credit_in) counter_next = counter +1'b1; else if(credit_in | smart_credit_in) counter_next=counter; diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 05fa452..e21d8bd 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -372,7 +372,7 @@ module router_top #( // logic router_is_ideal /*verilator public_flat_rd*/ ; // logic not_ideal_next,not_ideal; // integer ii,jj; -// always @(*) begin +// always_comb begin // router_is_ideal = 1'b1; // not_ideal_next = 1'b0; // for(ii=0; iiSS_PORT) ? SS_PORT : SS_PORT-1; - always @(*)begin + always_combbegin destport_temp=destport_in; if(destport_in=={P_1{1'b0}}) begin destport_temp[SS_PORT_CODE]= 1'b1; diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index f39b03d..99d48d4 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -187,7 +187,7 @@ module traffic_gen_top #( pronoc_register #(.W(1)) streg1 (.reset(reset),.clk(clk), .D_in(start_en_next), .Q_out(start_en) ); pronoc_register #(.W(DELAYw)) streg2 (.reset(reset),.clk(clk), .D_in(start_delay_counter_next), .Q_out(start_delay_counter) ); - always @(*) begin + always_comb begin start_en_next =start_en; start_delay_counter_next= start_delay_counter; if(start) begin @@ -399,7 +399,7 @@ module traffic_gen_top #( reg not_yet_sent_aflit_next,not_yet_sent_aflit; - always @(*)begin + always_combbegin wr_vc_next = wr_vc; cand_wr_vc_en = 1'b0; flit_out_wr = 1'b0; @@ -686,7 +686,7 @@ module traffic_gen_top #( // `ifdef VERILATOR // logic endp_is_active /*verilator public_flat_rd*/ ; // -// always @ (*) begin +// always_comb begin // endp_is_active = 1'b0; // if (chan_out.flit_chanel.flit_wr) endp_is_active=1'b1; // if (chan_out.flit_chanel.credit > {V{1'b0}} ) endp_is_active=1'b1; @@ -748,7 +748,7 @@ module injection_ratio_ctrl # reg sent,next_sent,next_inject; - always @(*) begin + always_comb begin next_state =state; next_flit_counter =flit_counter; next_sent =sent; diff --git a/mpsoc/rtl/src_openpiton/piton_mesh.sv b/mpsoc/rtl/src_openpiton/piton_mesh.sv index 91f4bf0..de455d1 100644 --- a/mpsoc/rtl/src_openpiton/piton_mesh.sv +++ b/mpsoc/rtl/src_openpiton/piton_mesh.sv @@ -295,7 +295,7 @@ module piton_mesh_pronoc_wrap ( .valid() ); - always @(*) begin + always_comb begin myLocX[i] = {`XY_WIDTH{1'b0}}; myLocY[i] = {`XY_WIDTH{1'b0}}; myChipID[i] = {`CHIP_ID_WIDTH{1'b0}}; diff --git a/mpsoc/rtl/src_openpiton/wrapper.sv b/mpsoc/rtl/src_openpiton/wrapper.sv index 66ac803..8396b02 100644 --- a/mpsoc/rtl/src_openpiton/wrapper.sv +++ b/mpsoc/rtl/src_openpiton/wrapper.sv @@ -138,12 +138,12 @@ module piton_to_pronoc_endp_addr_converter_diffrent_topology reg [NEw-1 : 0] ProNoC_id; generate if (PITON_NEw < NEw) begin - always @ (*) begin + always_comb begin ProNoC_id =0; ProNoC_id [PITON_NEw-1 : 0] = piton_id; end end else begin - always @ (*) begin + always_comb begin ProNoC_id =0; ProNoC_id = piton_id [ NEw-1 : 0]; end @@ -160,7 +160,7 @@ module piton_to_pronoc_endp_addr_converter_diffrent_topology endp_addr_encoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) encode3 ( .id(CHIP_SET_ID), .code( chipset_endp_addr )); assign pronoc_endp_addr_o = (piton_chipid_i == default_chipid_i ) ? pronoc_endp_addr : chipset_endp_addr; - always @ (*) begin + always_comb begin piton_end_addr_coded_o = {ADDR_CODED{1'b0}}; piton_end_addr_coded_o [Yw+Xw-1 : 0] = {piton_coreid_y_i[Yw-1 : 0], piton_coreid_x_i[Xw-1 : 0]}; if(piton_chipid_i == 8192 ) begin @@ -220,7 +220,7 @@ module piton_to_pronoc_endp_addr_converter_same_topology //coded for FMESH topology generate if(TOPOLOGY == "FMESH") begin - always @ (*) begin + always_comb begin pronoc_endp_addr_o = {EAw{1'b0}}; if(piton_chipid_i == default_chipid_i ) begin pronoc_endp_addr_o [Yw+Xw-1 : 0] = {piton_coreid_y_i[Yw-1 : 0], piton_coreid_x_i[Xw-1 : 0]}; @@ -232,14 +232,14 @@ module piton_to_pronoc_endp_addr_converter_same_topology end end end else begin //"mesh" - always @ (*) begin + always_comb begin pronoc_endp_addr_o = {EAw{1'b0}}; pronoc_endp_addr_o [Yw+Xw-1 : 0] = {piton_coreid_y_i[Yw-1 : 0], piton_coreid_x_i[Xw-1 : 0]}; end end endgenerate - always @ (*) begin + always_comb begin piton_end_addr_coded_o = {ADDR_CODED{1'b0}}; piton_end_addr_coded_o [Yw+Xw-1 : 0] = {piton_coreid_y_i[Yw-1 : 0], piton_coreid_x_i[Xw-1 : 0]}; if(piton_chipid_i == 8192 ) begin @@ -273,7 +273,7 @@ output reg [`NOC_X_WIDTH-1:0] piton_coreid_x_o; output reg [`NOC_Y_WIDTH-1:0] piton_coreid_y_o; input [ADDR_CODED-1 : 0] piton_end_addr_coded_i; - always @(*)begin + always_combbegin piton_coreid_x_o = {`MSG_DST_X_WIDTH{1'b0}}; piton_coreid_y_o = {`MSG_DST_Y_WIDTH{1'b0}}; {piton_coreid_y_o[Yw-1 : 0], piton_coreid_x_o[Xw-1 : 0]}=piton_end_addr_coded_i [Yw+Xw-1 : 0]; @@ -405,7 +405,7 @@ module piton_to_pronoc_wrapper #( wire [Fw-1 : 0] header_flit; reg [WEIGHTw-1 : 0] win; - always @(*) begin + always_comb begin win={WEIGHTw{1'b0}}; win[0]=1'b1; end diff --git a/mpsoc/rtl/src_peripheral/ni/ni_master.sv b/mpsoc/rtl/src_peripheral/ni/ni_master.sv index fa2ea22..f4738ef 100644 --- a/mpsoc/rtl/src_peripheral/ni/ni_master.sv +++ b/mpsoc/rtl/src_peripheral/ni/ni_master.sv @@ -296,7 +296,7 @@ Shared registers for all VCs else assign temp = {{(8-HDw){1'b0}},rsv_hdr_dat [vc_addr]}; endgenerate //read wb registers - always @(*)begin + always_combbegin s_dat_o ={Dw{1'b0}}; case(vc_s_addr_i) GENERAL_REGS_WB_ADDR:begin // This is a general address. check the general address filed @@ -335,7 +335,7 @@ Shared registers for all VCs end //write wb registers - always @ (*)begin + always_combbegin burst_counter_next=burst_counter; burst_size_next= burst_size; if(burst_counter_ld) burst_counter_next = burst_size; @@ -665,7 +665,7 @@ Shared registers for all VCs assign tail_flit_out[31 : 0] = send_crc_out; end else begin : no_crc assign tail_flit_out = m_send_dat_i [Fpay-1 : 0]; - //always @(*) crc_miss_match = {V{1'b0}}; + //always_comb crc_miss_match = {V{1'b0}}; always @(posedge clk) crc_miss_match <= {V{1'b0}}; end From f24b8e4900fb35ee33d95af40b885ddf1c21a242 Mon Sep 17 00:00:00 2001 From: amonemi Date: Fri, 6 Jun 2025 19:25:15 +0200 Subject: [PATCH 039/107] fix UseSVAlways-ML --- mpsoc/rtl/arch/iport_reg_base.sv | 2 +- mpsoc/rtl/src_emulate/rtl/noc_emulator.sv | 8 ++++---- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 2 +- mpsoc/rtl/src_noc/flit_buffer.sv | 12 ++++++------ mpsoc/rtl/src_noc/fmesh.sv | 4 ++-- mpsoc/rtl/src_noc/header_flit.sv | 2 +- mpsoc/rtl/src_noc/inout_ports.sv | 2 +- mpsoc/rtl/src_noc/input_ports.sv | 2 +- mpsoc/rtl/src_noc/mesh_torus.sv | 4 ++-- mpsoc/rtl/src_noc/multicast.sv | 6 +++--- mpsoc/rtl/src_noc/ss_allocator.sv | 6 +++--- mpsoc/rtl/src_noc/traffic_gen_top.sv | 2 +- mpsoc/rtl/src_openpiton/wrapper.sv | 2 +- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 4 ++-- 14 files changed, 29 insertions(+), 29 deletions(-) diff --git a/mpsoc/rtl/arch/iport_reg_base.sv b/mpsoc/rtl/arch/iport_reg_base.sv index 5acd50c..d771ddd 100644 --- a/mpsoc/rtl/arch/iport_reg_base.sv +++ b/mpsoc/rtl/arch/iport_reg_base.sv @@ -238,7 +238,7 @@ module iport_reg_base #( .Q_out(iport_weight )); - always_combbegin + always_comb begin iport_weight_next = iport_weight; if(hdr_flit_wr != {V{1'b0}}) iport_weight_next = (weight_in=={WEIGHTw{1'b0}})? 1 : weight_in; // the minimum weight is 1 end diff --git a/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv b/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv index 5beee7a..4ec10c2 100644 --- a/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv +++ b/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv @@ -412,7 +412,7 @@ module traffic_gen_ram .mcast_dst_num_o() ); - always_combbegin + always_comb begin case (statistic_jtag_addr_b) SENT_PCK_ADDR: statistic_jtag_q_b= total_pck_sent; RSVD_PCK_ADDR: statistic_jtag_q_b= total_pck_recieved; @@ -422,7 +422,7 @@ module traffic_gen_ram endcase end - always_combbegin + always_comb begin ns=ps; addr_a_next = addr_a; pck_number_sent_next = pck_number_sent; @@ -608,13 +608,13 @@ module jtag_emulator_controller #( end end - always_combbegin + always_comb begin wb_addr_next= wb_addr; if(wb_wr_addr_en) wb_addr_next = data_out [Aw-1 : 0]; else if (wb_addr_inc) wb_addr_next = wb_addr + 1'b1; end - always_combbegin + always_comb begin ns=ps; wr_mem_en =1'b0; wb_addr_inc=1'b0; diff --git a/mpsoc/rtl/src_modelsim/traffic_pattern.sv b/mpsoc/rtl/src_modelsim/traffic_pattern.sv index 14e9300..a367d2d 100755 --- a/mpsoc/rtl/src_modelsim/traffic_pattern.sv +++ b/mpsoc/rtl/src_modelsim/traffic_pattern.sv @@ -819,7 +819,7 @@ module hot_spot_dest_gen end logic hotspot_flag; integer i; - always_combbegin + always_comb begin off_flag=0; for (i=0;iSS_PORT) ? SS_PORT : SS_PORT-1; - always_combbegin + always_comb begin destport_temp=destport_in; if(destport_in=={P_1{1'b0}}) begin destport_temp[SS_PORT_CODE]= 1'b1; diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index 99d48d4..e70c24e 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -399,7 +399,7 @@ module traffic_gen_top #( reg not_yet_sent_aflit_next,not_yet_sent_aflit; - always_combbegin + always_comb begin wr_vc_next = wr_vc; cand_wr_vc_en = 1'b0; flit_out_wr = 1'b0; diff --git a/mpsoc/rtl/src_openpiton/wrapper.sv b/mpsoc/rtl/src_openpiton/wrapper.sv index 8396b02..2d2a856 100644 --- a/mpsoc/rtl/src_openpiton/wrapper.sv +++ b/mpsoc/rtl/src_openpiton/wrapper.sv @@ -273,7 +273,7 @@ output reg [`NOC_X_WIDTH-1:0] piton_coreid_x_o; output reg [`NOC_Y_WIDTH-1:0] piton_coreid_y_o; input [ADDR_CODED-1 : 0] piton_end_addr_coded_i; - always_combbegin + always_comb begin piton_coreid_x_o = {`MSG_DST_X_WIDTH{1'b0}}; piton_coreid_y_o = {`MSG_DST_Y_WIDTH{1'b0}}; {piton_coreid_y_o[Yw-1 : 0], piton_coreid_x_o[Xw-1 : 0]}=piton_end_addr_coded_i [Yw+Xw-1 : 0]; diff --git a/mpsoc/rtl/src_peripheral/ni/ni_master.sv b/mpsoc/rtl/src_peripheral/ni/ni_master.sv index f4738ef..3f862d2 100644 --- a/mpsoc/rtl/src_peripheral/ni/ni_master.sv +++ b/mpsoc/rtl/src_peripheral/ni/ni_master.sv @@ -296,7 +296,7 @@ Shared registers for all VCs else assign temp = {{(8-HDw){1'b0}},rsv_hdr_dat [vc_addr]}; endgenerate //read wb registers - always_combbegin + always_comb begin s_dat_o ={Dw{1'b0}}; case(vc_s_addr_i) GENERAL_REGS_WB_ADDR:begin // This is a general address. check the general address filed @@ -335,7 +335,7 @@ Shared registers for all VCs end //write wb registers - always_combbegin + always_comb begin burst_counter_next=burst_counter; burst_size_next= burst_size; if(burst_counter_ld) burst_counter_next = burst_size; From f58a7f0928d6afd050cca6ac90c0a87b193ef6d9 Mon Sep 17 00:00:00 2001 From: amonemi Date: Sat, 7 Jun 2025 01:00:39 +0200 Subject: [PATCH 040/107] fix linting warnings --- mpsoc/rtl/src_noc/flit_buffer.sv | 28 +++++++++++++++++++--------- mpsoc/rtl/src_noc/traffic_gen_top.sv | 15 ++++++++++----- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 9df0f1f..95e800c 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -1020,9 +1020,9 @@ module bram_based_fifo #( input clk; reg [Dw-1 : 0] queue [B-1 : 0] /* synthesis ramstyle = "no_rw_check" */; - reg [Bw- 1 : 0] rd_ptr; - reg [Bw- 1 : 0] wr_ptr; - reg [DEPTHw-1 : 0] depth; + reg [Bw- 1 : 0] rd_ptr,rd_ptr_next; + reg [Bw- 1 : 0] wr_ptr,wr_ptr_next; + reg [DEPTHw-1 : 0] depth,depth_next; // Sample the data always @(posedge clk) begin @@ -1032,17 +1032,27 @@ module bram_based_fifo #( dout <= queue[rd_ptr]; end - always @(posedge clk) begin + always_comb begin + rd_ptr_next = rd_ptr; + wr_ptr_next = wr_ptr; + depth_next = depth; + if (wr_en) wr_ptr_next = (wr_ptr==Bint)? {Bw{1'b0}} : wr_ptr + 1'b1; + if (rd_en) rd_ptr_next = (rd_ptr==Bint)? {Bw{1'b0}} : rd_ptr + 1'b1; + if (wr_en & ~rd_en) depth_next = depth + 1'b1; + else if (~wr_en & rd_en) depth_next = depth - 1'b1; + end + + + always @(`pronoc_clk_reset_edge) begin if (`pronoc_reset) begin rd_ptr <= {Bw{1'b0}}; wr_ptr <= {Bw{1'b0}}; depth <= {DEPTHw{1'b0}}; end else begin - if (wr_en) wr_ptr <= (wr_ptr==Bint)? {Bw{1'b0}} : wr_ptr + 1'b1; - if (rd_en) rd_ptr <= (rd_ptr==Bint)? {Bw{1'b0}} : rd_ptr + 1'b1; - if (wr_en & ~rd_en) depth <= depth + 1'b1; - else if (~wr_en & rd_en) depth <= depth - 1'b1; + rd_ptr <= rd_ptr_next; + wr_ptr <= wr_ptr_next; + depth <= depth_next; end end @@ -1068,4 +1078,4 @@ module bram_based_fifo #( end `endif -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index e70c24e..f85ff19 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -790,12 +790,17 @@ module injection_ratio_ctrl # inject <= 1'b0; sent <= 1'b1; flit_counter <= 0; + pck_size <= pck_size_in; + end else begin + sent <= next_sent; + state <= next_state; + if(ratio!={CNTw{1'b0}}) inject <= next_inject; + flit_counter <= next_flit_counter; + if(flit_counter=={PCK_SIZw{1'b0}}) pck_size<=pck_size_in; end - if(flit_counter=={PCK_SIZw{1'b0}}) pck_size<=pck_size_in; - state <= next_state; - if(ratio!={CNTw{1'b0}}) inject <= next_inject; - sent <= next_sent; - flit_counter <= next_flit_counter; + + + end end From 453f1b45b360fbecd35ba897669eda1635390d3f Mon Sep 17 00:00:00 2001 From: amonemi Date: Sat, 7 Jun 2025 23:42:24 +0200 Subject: [PATCH 041/107] fix linting --- mpsoc/rtl/src_noc/input_ports.sv | 72 ++++++++++++++++------------ mpsoc/rtl/src_noc/output_ports.sv | 5 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 44 +++++++---------- 3 files changed, 61 insertions(+), 60 deletions(-) diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 21eca42..978f6b4 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -292,18 +292,21 @@ module input_queue_per_port #( wire [V-1 : 0] multiple_dest,dst_onhot0; wire [DSTPw-1 : 0] clear_dspt_mulicast [V-1 : 0]; - wire [VV-1 : 0] candidate_ovcs; + logic [V-1 : 0] candidate_ovcs [V-1 : 0]; wire [Cw-1 : 0] class_in; wire [DSTPw-1 : 0] destport_in,destport_in_encoded; wire [VDSTPw-1 : 0] lk_destination_encoded; wire [DAw-1 : 0] dest_e_addr_in; + wire [EAw-1 : 0] dest_e_addr_out [V-1 : 0]; wire [EAw-1 : 0] src_e_addr_in; wire [V-1 : 0] vc_num_in; wire [V-1 : 0] hdr_flit_wr; wire [VV-1 : 0] assigned_ovc_num; - + logic [V-1 : 0] assigned_onc_one_hot [V-1 : 0]; + logic [Vw-1 : 0] assigned_onc_bin [V-1 : 0]; + wire [DSTPw-1 : 0] lk_destination_in_encoded; wire [WEIGHTw-1 : 0] weight_in; wire [Fw-1 : 0] buffer_out; @@ -402,6 +405,9 @@ module input_queue_per_port #( genvar i; generate + for (i=0; i1) && CAST_TYPE== "UNICAST") begin : multi_local /* verilator lint_on WIDTH */ @@ -466,33 +472,40 @@ module input_queue_per_port #( ); end // "MULTI_MESH" + always_comb begin + for (int k=0; k Date: Mon, 9 Jun 2025 15:25:32 +0200 Subject: [PATCH 042/107] change all noc rtl .v files to .sv --- .../src_noc/{comb-spec1.v => comb-spec1.sv} | 6 +- mpsoc/rtl/src_noc/comb_nonspec.sv | 49 ++- .../src_noc/{comb_spec2.v => comb_spec2.sv} | 12 +- mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv | 15 +- ...tion_analyzer.v => congestion_analyzer.sv} | 6 +- mpsoc/rtl/src_noc/{crossbar.v => crossbar.sv} | 0 mpsoc/rtl/src_noc/{debug.v => debug.sv} | 0 .../{fattree_route.v => fattree_route.sv} | 0 mpsoc/rtl/src_noc/flit_buffer.sv | 4 +- mpsoc/rtl/src_noc/header_flit.sv | 21 +- ...orus_routting.v => mesh_torus_routting.sv} | 317 +++++------------- mpsoc/rtl/src_noc/noc_filelist.f | 28 +- .../src_noc/{route_mesh.v => route_mesh.sv} | 0 .../src_noc/{route_torus.v => route_torus.sv} | 0 mpsoc/rtl/src_noc/router_bypass.sv | 6 +- mpsoc/rtl/src_noc/{routing.v => routing.sv} | 12 +- mpsoc/rtl/src_noc/topology_localparam.v | 12 +- .../src_noc/{tree_route.v => tree_route.sv} | 0 mpsoc/rtl/src_noc/{wrra.v => wrra.sv} | 0 19 files changed, 148 insertions(+), 340 deletions(-) rename mpsoc/rtl/src_noc/{comb-spec1.v => comb-spec1.sv} (99%) rename mpsoc/rtl/src_noc/{comb_spec2.v => comb_spec2.sv} (98%) rename mpsoc/rtl/src_noc/{congestion_analyzer.v => congestion_analyzer.sv} (99%) rename mpsoc/rtl/src_noc/{crossbar.v => crossbar.sv} (100%) rename mpsoc/rtl/src_noc/{debug.v => debug.sv} (100%) rename mpsoc/rtl/src_noc/{fattree_route.v => fattree_route.sv} (100%) rename mpsoc/rtl/src_noc/{mesh_torus_routting.v => mesh_torus_routting.sv} (75%) rename mpsoc/rtl/src_noc/{route_mesh.v => route_mesh.sv} (100%) rename mpsoc/rtl/src_noc/{route_torus.v => route_torus.sv} (100%) rename mpsoc/rtl/src_noc/{routing.v => routing.sv} (98%) rename mpsoc/rtl/src_noc/{tree_route.v => tree_route.sv} (100%) rename mpsoc/rtl/src_noc/{wrra.v => wrra.sv} (100%) diff --git a/mpsoc/rtl/src_noc/comb-spec1.v b/mpsoc/rtl/src_noc/comb-spec1.sv similarity index 99% rename from mpsoc/rtl/src_noc/comb-spec1.v rename to mpsoc/rtl/src_noc/comb-spec1.sv index 1b1664d..125f434 100755 --- a/mpsoc/rtl/src_noc/comb-spec1.v +++ b/mpsoc/rtl/src_noc/comb-spec1.sv @@ -468,8 +468,7 @@ module sw_alloc_sub#( //first level arbiter swa_input_port_arbiter #( .ARBITER_WIDTH(V), - .EXT_P_EN(0), - .ARBITER_TYPE(SWA_ARBITER_TYPE) + .EXT_P_EN(0) ) input_arbiter ( .ext_pr_en_i(1'b1),// not used here anyway .request(ivc_masked [i]), @@ -531,8 +530,7 @@ module sw_alloc_sub#( end //second level arbiter swa_output_port_arbiter #( - .ARBITER_WIDTH(P_1), - .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA + .ARBITER_WIDTH(P_1) ) output_arbiter ( .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA .clk(clk), diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index ccdb3e1..1f2a0ff 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -504,8 +504,7 @@ module nonspec_sw_alloc #( //first level arbiter swa_input_port_arbiter #( .ARBITER_WIDTH(V), - .EXT_P_EN(FIRST_ARBITER_EXT_P_EN), - .ARBITER_TYPE(SWA_ARBITER_TYPE) + .EXT_P_EN(FIRST_ARBITER_EXT_P_EN) ) input_arbiter ( .ext_pr_en_i(any_ivc_granted_all[i]), .request(ivc_masked [i]), @@ -580,8 +579,7 @@ module nonspec_sw_alloc #( end //P_ //second level arbiter swa_output_port_arbiter #( - .ARBITER_WIDTH(P_1), - .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA + .ARBITER_WIDTH(P_1) ) output_arbiter ( .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA .clk(clk), @@ -613,8 +611,7 @@ endmodule ********************/ module swa_input_port_arbiter #( parameter ARBITER_WIDTH =4, - parameter EXT_P_EN = 1, - parameter ARBITER_TYPE = "WRRA"// RRA, WRRA + parameter EXT_P_EN = 1 )( ext_pr_en_i, // it is used only if the EXT_P_EN is 1 clk, @@ -625,6 +622,7 @@ module swa_input_port_arbiter #( vc_weight_is_consumed, // only for WRRA winner_weight_consumed // only for WRRA ); + `NOC_CONF input ext_pr_en_i; input [ARBITER_WIDTH-1 : 0] request; output[ARBITER_WIDTH-1 : 0] grant; @@ -635,9 +633,7 @@ module swa_input_port_arbiter #( output winner_weight_consumed; generate - /* verilator lint_off WIDTH */ - if(ARBITER_TYPE != "RRA") begin: wrra_ - /* verilator lint_on WIDTH */ + if(IS_WRRA) begin: wrra_ // one hot mux onehot_mux_1D #( .W(1), @@ -698,8 +694,7 @@ endmodule * ********************/ module swa_output_port_arbiter #( - parameter ARBITER_WIDTH =4, - parameter ARBITER_TYPE = "WRRA" // RRA, WRRA + parameter ARBITER_WIDTH =4 )( weight_consumed, // only used for WRRA clk, @@ -708,7 +703,7 @@ module swa_output_port_arbiter #( grant, any_grant ); - + `NOC_CONF input [ARBITER_WIDTH-1 : 0] request; output [ARBITER_WIDTH-1 : 0] grant; output any_grant; @@ -717,9 +712,7 @@ module swa_output_port_arbiter #( input [ARBITER_WIDTH-1 : 0] weight_consumed; generate - /* verilator lint_off WIDTH */ - if(ARBITER_TYPE == "WRRA") begin : wrra_mine - /* verilator lint_on WIDTH */ + if(IS_WRRA) begin : wrra // second level wrra priority is only changed if the granted request weight is consumed wire pr_en; @@ -742,37 +735,33 @@ module swa_output_port_arbiter #( .any_grant (any_grant ), .priority_en (pr_en) ); - - /* verilator lint_off WIDTH */ - end else if(ARBITER_TYPE == "WRRA_CLASSIC") begin : wrra_classic - /* verilator lint_on WIDTH */ - // use classic WRRA. only for compasrion with propsoed wrra - - wire [ARBITER_WIDTH-1 : 0] masked_req = request & ~weight_consumed; - wire sel = |masked_req; - wire [ARBITER_WIDTH-1 : 0] mux_req = (sel==1'b1)? masked_req : request; + end else if(IS_RRA) begin : rra arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH ) - ) arb ( + ) arb ( .clk (clk), .reset (reset), - .request (mux_req), + .request (request), .grant (grant), .any_grant (any_grant ) ); - end else begin : rra_m + + end else begin : wrra_classic //(ARBITER_TYPE == "WRRA_CLASSIC") + // use classic WRRA. only for compasrion with propsoed wrra + wire [ARBITER_WIDTH-1 : 0] masked_req = request & ~weight_consumed; + wire sel = |masked_req; + wire [ARBITER_WIDTH-1 : 0] mux_req = (sel==1'b1)? masked_req : request; arbiter #( .ARBITER_WIDTH (ARBITER_WIDTH ) - ) arb ( + ) arb ( .clk (clk), .reset (reset), - .request (request), + .request (mux_req), .grant (grant), .any_grant (any_grant ) ); - end endgenerate endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/comb_spec2.v b/mpsoc/rtl/src_noc/comb_spec2.sv similarity index 98% rename from mpsoc/rtl/src_noc/comb_spec2.v rename to mpsoc/rtl/src_noc/comb_spec2.sv index f3ae4ea..9c05206 100755 --- a/mpsoc/rtl/src_noc/comb_spec2.v +++ b/mpsoc/rtl/src_noc/comb_spec2.sv @@ -469,8 +469,7 @@ module sw_alloc_sub2#( //first level arbiter swa_input_port_arbiter #( .ARBITER_WIDTH(V), - .EXT_P_EN(0), - .ARBITER_TYPE(SWA_ARBITER_TYPE) + .EXT_P_EN(0) )input_arbiter ( .ext_pr_en_i(1'b1),// not used here anyway .request(ivc_masked [i]), @@ -535,8 +534,7 @@ module sw_alloc_sub2#( //second level arbiter swa_output_port_arbiter #( - .ARBITER_WIDTH(P_1), - .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA + .ARBITER_WIDTH(P_1) ) output_arbiter( .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA .clk(clk), @@ -653,8 +651,7 @@ module spec_sw_alloc_sub2#( //first level arbiter swa_input_port_arbiter #( .ARBITER_WIDTH(V), - .EXT_P_EN(0), - .ARBITER_TYPE(SWA_ARBITER_TYPE) + .EXT_P_EN(0) ) input_arbiter ( .ext_pr_en_i(1'b1),// not used here anyway .request(ivc_masked [i]), @@ -719,8 +716,7 @@ module spec_sw_alloc_sub2#( end //second level arbiter swa_output_port_arbiter #( - .ARBITER_WIDTH(P_1), - .ARBITER_TYPE(SWA_ARBITER_TYPE) // RRA, WRRA + .ARBITER_WIDTH(P_1) ) output_arbiter ( .weight_consumed(second_arbiter_weight_consumed[i]), // only used for WRRA .clk(clk), diff --git a/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv b/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv index 945a29c..85aa1b4 100755 --- a/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv +++ b/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv @@ -127,9 +127,7 @@ module combined_vc_sw_alloc #( ); end else */ - /* verilator lint_off WIDTH */ - if(COMBINATION_TYPE == "COMB_SPEC1") begin : spec1 - /* verilator lint_on WIDTH */ + if(IS_COMB_SPEC1) begin : spec1 comb_spec1_allocator #( .V(V), .P(P), @@ -137,7 +135,6 @@ module combined_vc_sw_alloc #( .SWA_ARBITER_TYPE (SWA_ARBITER_TYPE), .MIN_PCK_SIZE(MIN_PCK_SIZE), .SELF_LOOP_EN(SELF_LOOP_EN) - )the_comb_spec1( .dest_port_all(dest_port_all), .masked_ovc_request_all(masked_ovc_request_all), @@ -163,9 +160,7 @@ module combined_vc_sw_alloc #( assign spec_granted_dest_port_all = {PP_1{1'bx}}; assign spec_ovc_num_all = {PVV{1'bx}}; - /* verilator lint_off WIDTH */ - end else if (COMBINATION_TYPE == "COMB_SPEC2") begin : spec2 - /* verilator lint_on WIDTH */ + end else if (IS_COMB_SPEC2) begin : spec2 comb_spec2_allocator #( .V(V), .P(P), @@ -251,9 +246,9 @@ module combined_vc_sw_alloc #( .reset(reset) ); end - assign nonspec_granted_dest_port_all = granted_dest_port_all; - assign spec_granted_dest_port_all = {PP_1{1'bx}}; - assign spec_ovc_num_all = {PVV{1'bx}}; + assign nonspec_granted_dest_port_all = granted_dest_port_all; + assign spec_granted_dest_port_all = {PP_1{1'bx}}; + assign spec_ovc_num_all = {PVV{1'bx}}; assign spec_first_arbiter_granted_ivc_all = nonspec_first_arbiter_granted_ivc_all ; end endgenerate diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.v b/mpsoc/rtl/src_noc/congestion_analyzer.sv similarity index 99% rename from mpsoc/rtl/src_noc/congestion_analyzer.v rename to mpsoc/rtl/src_noc/congestion_analyzer.sv index 95c4ca5..1322905 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.v +++ b/mpsoc/rtl/src_noc/congestion_analyzer.sv @@ -342,7 +342,7 @@ module port_pre_sel_gen #( reset, clk ); - + `NOC_CONF localparam P_1 = P-1, PV = P * V, @@ -356,9 +356,7 @@ module port_pre_sel_gen #( input reset,clk; generate - /* verilator lint_off WIDTH */ - if(ROUTE_TYPE == "DETERMINISTIC") begin : detrministic - /* verilator lint_on WIDTH */ + if( IS_DETERMINISTIC ) begin : detrministic assign port_pre_sel = {PPSw{1'b0}}; end else begin : adaptive if(CONGESTION_INDEX==0) begin:indx0 diff --git a/mpsoc/rtl/src_noc/crossbar.v b/mpsoc/rtl/src_noc/crossbar.sv similarity index 100% rename from mpsoc/rtl/src_noc/crossbar.v rename to mpsoc/rtl/src_noc/crossbar.sv diff --git a/mpsoc/rtl/src_noc/debug.v b/mpsoc/rtl/src_noc/debug.sv similarity index 100% rename from mpsoc/rtl/src_noc/debug.v rename to mpsoc/rtl/src_noc/debug.sv diff --git a/mpsoc/rtl/src_noc/fattree_route.v b/mpsoc/rtl/src_noc/fattree_route.sv similarity index 100% rename from mpsoc/rtl/src_noc/fattree_route.v rename to mpsoc/rtl/src_noc/fattree_route.sv diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 95e800c..f43d4ed 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -63,9 +63,7 @@ module flit_buffer RESTw = Fw -2-V , PTRw = ((2**Bw)==B)? Bw : BVw, // if B is power of 2 PTRw is Bw else is BVw ARRAYw = PTRw * V, - /* verilator lint_off WIDTH */ - RAM_DATA_WIDTH = (PCK_TYPE == "MULTI_FLIT")? Fw - V : Fw - V -2; - /* verilator lint_on WIDTH */ + RAM_DATA_WIDTH = (IS_MULTI_FLIT)? Fw - V : Fw - V -2; input [Fw-1 :0] din; // Data in input [V-1 :0] vc_num_wr;//write virtual chanel diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index 69686e0..b8673d6 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -71,9 +71,7 @@ module header_flit_generator #( assign flit_out [CLASS_MSB :CLASS_LSB] = class_in; end - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra_b - /* verilator lint_on WIDTH */ + if(~IS_RRA)begin : wrra_b assign flit_out [WEIGHT_MSB :WEIGHT_LSB] = weight_in; end @@ -160,9 +158,7 @@ module extract_header_flit_info # ( end else begin : no_class assign class_o = {Cw{1'b0}}; end - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra_b - /* verilator lint_on WIDTH */ + if(~IS_RRA)begin : wrra_b assign weight_o = flit_in [WEIGHT_MSB : WEIGHT_LSB]; end else begin : rra_b assign weight_o = {WEIGHTw{1'bX}}; @@ -179,10 +175,9 @@ module extract_header_flit_info # ( assign data_o=offset[Dw-1 : 0]; end endgenerate - /* verilator lint_off WIDTH */ - assign hdr_flg_o = (PCK_TYPE == "MULTI_FLIT") ? flit_in [Fw-1] : 1'b1; - assign tail_flg_o = (PCK_TYPE == "MULTI_FLIT") ? flit_in [Fw-2] : 1'b1; - /* verilator lint_on WIDTH */ + + assign hdr_flg_o = (IS_MULTI_FLIT) ? flit_in [Fw-1] : 1'b1; + assign tail_flg_o = (IS_MULTI_FLIT) ? flit_in [Fw-2] : 1'b1; assign vc_num_o = flit_in [FPAYw+V-1 : FPAYw]; assign hdr_flit_wr_o= (flit_in_wr & hdr_flg_o )? vc_num_o : {V{1'b0}}; endmodule @@ -230,11 +225,7 @@ module header_flit_update_lk_route_ovc #( wire [DSTPw-1 : 0] lk_mux_out; pronoc_register #(.W(V)) reg1 (.D_in(vc_num_in), .Q_out(vc_num_delayed), .reset(reset), .clk(clk)); - - /* verilator lint_off WIDTH */ - assign hdr_flag = ( PCK_TYPE == "MULTI_FLIT")? flit_in[Fw-1]: 1'b1; - /* verilator lint_on WIDTH */ - + assign hdr_flag = (IS_MULTI_FLIT)? flit_in[Fw-1]: 1'b1; onehot_mux_1D #( .W(DSTPw), .N(V) diff --git a/mpsoc/rtl/src_noc/mesh_torus_routting.v b/mpsoc/rtl/src_noc/mesh_torus_routting.sv similarity index 75% rename from mpsoc/rtl/src_noc/mesh_torus_routting.v rename to mpsoc/rtl/src_noc/mesh_torus_routting.sv index 20a6c44..8333d6f 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_routting.v +++ b/mpsoc/rtl/src_noc/mesh_torus_routting.sv @@ -6,14 +6,8 @@ *************************************/ module mesh_torus_look_ahead_routing #( - parameter NX = 4, - parameter NY = 4, - parameter SW_LOC = 0, - parameter TOPOLOGY = "MESH",//"MESH","TORUS" - parameter ROUTE_NAME = "XY",// - parameter ROUTE_TYPE = "DETERMINISTIC"// "DETERMINISTIC", "FULL_ADAPTIVE", "PAR_ADAPTIVE" -) -( + parameter SW_LOC = 0 +)( current_x, //current router x address current_y, //current router y address dest_x, // destination router x address @@ -23,48 +17,27 @@ module mesh_torus_look_ahead_routing #( reset, clk ); - - /* verilator lint_off WIDTH */ - localparam P = (TOPOLOGY == "MESH" || TOPOLOGY == "FMESH" || TOPOLOGY == "TORUS")? 5:3; - /* verilator lint_on WIDTH */ - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 Date: Mon, 9 Jun 2025 15:31:00 +0200 Subject: [PATCH 043/107] fix linting --- mpsoc/rtl/src_noc/flit_buffer.sv | 74 ++++++++++---------------------- 1 file changed, 22 insertions(+), 52 deletions(-) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index f43d4ed..b6b593b 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -110,9 +110,7 @@ module flit_buffer genvar i; generate - /* verilator lint_off WIDTH */ - if (CAST_TYPE != "UNICAST") begin : nouni - /* verilator lint_on WIDTH */ + if (IS_UNICAST) begin : nouni assign sub_rd = (rd_en)? vc_num_rd : ssa_rd; assign sub_restore = sub_rd_ptr_ld; assign rd = (rd_en)? vc_num_rd & ~multiple_dest : ssa_rd & ~multiple_dest; @@ -120,9 +118,7 @@ module flit_buffer assign rd = (rd_en)? vc_num_rd : ssa_rd; end - /* verilator lint_off WIDTH */ - if (PCK_TYPE == "MULTI_FLIT") begin :multi - /* verilator lint_on WIDTH */ + if (IS_MULTI_FLIT) begin :multi assign {flgs_in,vc_in,flit_rest_in}=din; assign fifo_ram_din = {flgs_in,flit_rest_in}; assign {flgs_out,flit_rest_out} = fifo_ram_dout; @@ -134,23 +130,18 @@ module flit_buffer for(i=0;i 0); - + if (~IS_UNICAST) begin + assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = sub_rd_ptr[i]; + localparam RESET_TO = ((2**Bw)==B)? 0 : B*i; + pronoc_register #(.W(PTRw),.RESET_TO(RESET_TO)) reg4 (.D_in(sub_rd_ptr_next[i]), .Q_out(sub_rd_ptr[i]), .reset(reset), .clk(clk)); + pronoc_register #(.W(DEPTHw)) sub_depth_reg (.D_in(sub_depth_next[i] ), .Q_out(sub_depth [i]), .reset(reset), .clk(clk)); + always_comb begin + sub_depth_next [i] = sub_depth [i]; + if(sub_restore[i]) sub_depth_next [i]= depth_next[i]; + else if (wr[i] & ~sub_rd[i]) sub_depth_next [i] = sub_depth[i] + 1'h1; + else if (~wr[i] & sub_rd[i]) sub_depth_next [i] = sub_depth[i] - 1'h1; + end//always + assign vc_not_empty [i] = (sub_depth[i] > 0); end else begin : unicast assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = rd_ptr[i]; assign vc_not_empty [i] = (depth[i] > 0); @@ -233,32 +224,21 @@ module flit_buffer rd_ptr_next [i] = rd_ptr [i]; wr_ptr_next [i] = wr_ptr [i]; depth_next [i] = depth [i]; - if (wr[i] ) wr_ptr_next [i] = wr_ptr [i]+ 1'h1; if (rd[i] ) rd_ptr_next [i] = rd_ptr [i]+ 1'h1; if (wr[i] & ~rd[i]) depth_next [i] = depth[i] + 1'h1; else if (~wr[i] & rd[i]) depth_next [i] = depth[i] - 1'h1; end//always - - /* verilator lint_off WIDTH */ - if (CAST_TYPE != "UNICAST") begin :multicast - /* verilator lint_on WIDTH */ + + if (~IS_UNICAST) begin :multicast always_comb begin sub_rd_ptr_next[i] = sub_rd_ptr[i]; if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i]; else if(sub_rd[i]) sub_rd_ptr_next[i] = sub_rd_ptr[i]+ 1'h1; end - - /* verilator lint_off WIDTH */ - assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][sub_rd_ptr[i]] : 1'b1; - /* verilator lint_on WIDTH */ - - + assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][sub_rd_ptr[i]] : 1'b1; end else begin : unicast - - /* verilator lint_off WIDTH */ - assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][rd_ptr[i]] : 1'b1; - /* verilator lint_on WIDTH */ + assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][rd_ptr[i]] : 1'b1; end end//for V_ @@ -292,11 +272,7 @@ module flit_buffer if (wr[i] & ~rd[i]) depth_next [i] = depth[i] + 1'h1; else if (~wr[i] & rd[i]) depth_next [i] = depth[i] - 1'h1; end//always - - /* verilator lint_off WIDTH */ - if (CAST_TYPE != "UNICAST") begin :multicast - /* verilator lint_on WIDTH */ - + if (~IS_UNICAST) begin :multicast always_comb begin sub_rd_ptr_next[i] = sub_rd_ptr[i]; if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i]; @@ -307,13 +283,11 @@ module flit_buffer /* verilator lint_off WIDTH */ assign ptr_tmp [i] = sub_rd_ptr[i]-(B*i); - assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][ptr_tmp [i]] :1'b1; + assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][ptr_tmp [i]] :1'b1; /* verilator lint_on WIDTH */ end else begin : unicast - /* verilator lint_off WIDTH */ - assign flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][rd_ptr[i]-(B*i)] : 1'b1; - /* verilator lint_on WIDTH */ + assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][rd_ptr[i]-(B*i)] : 1'b1; end end// for V_ @@ -370,11 +344,7 @@ module flit_buffer end //DEBUG_EN for(i=0;i Date: Mon, 9 Jun 2025 15:42:42 +0200 Subject: [PATCH 044/107] fix linting --- mpsoc/rtl/src_noc/flit_buffer.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index b6b593b..521b2b7 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -110,7 +110,7 @@ module flit_buffer genvar i; generate - if (IS_UNICAST) begin : nouni + if (~IS_UNICAST) begin : nouni assign sub_rd = (rd_en)? vc_num_rd : ssa_rd; assign sub_restore = sub_rd_ptr_ld; assign rd = (rd_en)? vc_num_rd & ~multiple_dest : ssa_rd & ~multiple_dest; From b1217b0d735802fc89799e4d759fc0ad09e8e852 Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 9 Jun 2025 16:24:09 +0200 Subject: [PATCH 045/107] fix ci action --- mpsoc/rtl/src_noc/flit_buffer.sv | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 521b2b7..f2d9d0f 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -284,10 +284,9 @@ module flit_buffer /* verilator lint_off WIDTH */ assign ptr_tmp [i] = sub_rd_ptr[i]-(B*i); assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][ptr_tmp [i]] :1'b1; - /* verilator lint_on WIDTH */ - end else begin : unicast assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][rd_ptr[i]-(B*i)] : 1'b1; + /* verilator lint_on WIDTH */ end end// for V_ From 0ddb6b65156ad7c89deea0eaf46f129807a2ff90 Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 12 Jun 2025 12:36:57 +0200 Subject: [PATCH 046/107] Remove including pronoc_pkg instead of importingas an option. --- .../Altera/src/quartus_pronoc.sv | 108 +++--- mpsoc/Integration_test/deafult_noc_param | 2 + mpsoc/perl_gui/lib/perl/emulator.pl | 3 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 20 +- mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl | 11 +- .../perl_gui/lib/perl/topology_verilog_gen.pl | 51 +-- mpsoc/perl_gui/lib/perl/verilog_gen.pl | 4 +- mpsoc/rtl/arch/baseline.v | 2 +- mpsoc/rtl/arch/flit_buffer_reg_bas.v | 2 - mpsoc/rtl/arch/iport_reg_base.sv | 4 - mpsoc/rtl/main_comp.v | 31 +- mpsoc/rtl/pronoc_def.v | 16 - mpsoc/rtl/src_emulate/rtl/noc_emulator.sv | 16 +- mpsoc/rtl/src_modelsim/multicast_injector.sv | 9 +- mpsoc/rtl/src_modelsim/multicast_test.sv | 213 ++++++----- mpsoc/rtl/src_modelsim/noc_sim_statistic.sv | 8 +- mpsoc/rtl/src_modelsim/pck_injector_test.sv | 225 ++++++------ mpsoc/rtl/src_modelsim/testbench_noc.sv | 17 +- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 25 +- mpsoc/rtl/src_noc/comb-spec1.sv | 115 +++--- mpsoc/rtl/src_noc/comb_nonspec.sv | 110 +++--- mpsoc/rtl/src_noc/comb_spec2.sv | 89 ++--- mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv | 31 +- mpsoc/rtl/src_noc/congestion_analyzer.sv | 21 +- mpsoc/rtl/src_noc/crossbar.sv | 24 +- mpsoc/rtl/src_noc/debug.sv | 14 +- mpsoc/rtl/src_noc/fattree_noc_top.sv | 8 +- mpsoc/rtl/src_noc/flit_buffer.sv | 6 +- mpsoc/rtl/src_noc/fmesh.sv | 2 +- mpsoc/rtl/src_noc/header_flit.sv | 17 +- mpsoc/rtl/src_noc/inout_ports.sv | 10 +- mpsoc/rtl/src_noc/input_ports.sv | 16 +- mpsoc/rtl/src_noc/mesh_torus.sv | 2 +- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 10 +- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 26 +- mpsoc/rtl/src_noc/multicast.sv | 67 ++-- mpsoc/rtl/src_noc/noc_localparam.v | 2 + mpsoc/rtl/src_noc/noc_top.sv | 44 +-- mpsoc/rtl/src_noc/output_ports.sv | 16 +- mpsoc/rtl/src_noc/ovc_list.sv | 2 +- mpsoc/rtl/src_noc/packet_injector.sv | 23 +- mpsoc/rtl/src_noc/pronoc_pkg.sv | 13 +- mpsoc/rtl/src_noc/router_bypass.sv | 59 +-- mpsoc/rtl/src_noc/router_top.sv | 26 +- mpsoc/rtl/src_noc/router_two_stage.sv | 23 +- mpsoc/rtl/src_noc/routing.sv | 6 +- mpsoc/rtl/src_noc/ss_allocator.sv | 21 +- mpsoc/rtl/src_noc/star_noc.sv | 9 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 25 +- mpsoc/rtl/src_noc/tree_noc_top.sv | 20 +- mpsoc/rtl/src_noc/wrra.sv | 39 +- mpsoc/rtl/src_openpiton/noc_localparam.v | 2 +- mpsoc/rtl/src_openpiton/piton_mesh.sv | 337 ++++++++---------- mpsoc/rtl/src_openpiton/wrapper.sv | 136 +++---- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 43 +-- mpsoc/rtl/src_synfull/dpi_int_pkg.sv | 22 +- mpsoc/rtl/src_synfull/dpi_interface.sv | 2 +- mpsoc/rtl/src_synfull/synfull_top.sv | 37 +- .../src_topology/common/custom_ni_routing.v | 1 - .../rtl/src_topology/common/custom_noc_top.sv | 18 +- .../Tcustom1Rcustom_conventional_routing.v | 2 +- ...stom1Rcustom_conventional_routing_genvar.v | 2 +- .../Tcustom1Rcustom_look_ahead_routing.v | 2 +- ...custom1Rcustom_look_ahead_routing_genvar.v | 2 +- mpsoc/rtl/src_topology/custom1/custom1.png | Bin 83516 -> 137543 bytes mpsoc/rtl/src_topology/custom1/custom1_noc.sv | 26 +- .../custom1/custom1_noc_genvar.sv | 29 +- mpsoc/rtl/src_topology/param.obj | 52 +-- mpsoc/script/phy_noc_gen/phy_noc.pl | 29 +- .../jtag_ram_test/src_verilog/lib/main_comp.v | 31 +- 70 files changed, 985 insertions(+), 1451 deletions(-) diff --git a/mpsoc/Integration_test/Altera/src/quartus_pronoc.sv b/mpsoc/Integration_test/Altera/src/quartus_pronoc.sv index ab1e546..9a15aca 100644 --- a/mpsoc/Integration_test/Altera/src/quartus_pronoc.sv +++ b/mpsoc/Integration_test/Altera/src/quartus_pronoc.sv @@ -1,67 +1,63 @@ `include "pronoc_def.v" module quartus_pronoc -#( - parameter NOC_ID = 0 -)( - clk, - reset, - chan_in, - chan_out, - sel_in, - sel_out +( + clk, + reset, + chan_in, + chan_out, + sel_in, + sel_out ); - `NOC_CONF - - input [NE-1 : 0] sel_in; - input [NEw-1 : 0] sel_out; - input smartflit_chanel_t chan_in; - output smartflit_chanel_t chan_out; - input reset,clk; - - - smartflit_chanel_t chan_in_all [NE-1 : 0]; - smartflit_chanel_t chan_out_all [NE-1 : 0]; - smartflit_chanel_t chan_out_all_reg [NE-1 : 0]; - - wire noc_reset; - - noc_top #( - .NOC_ID(NOC_ID) - ) top ( - .reset(noc_reset), - .clk(clk), - .chan_in_all(chan_in_all), - .chan_out_all(chan_out_all), - .router_event( ) - ); - - - altera_reset_synchronizer sync( - .reset_in (reset), - .clk (clk), - .reset_out (noc_reset) - ); - - //NoC port assignment - - assign chan_out = chan_out_all_reg[sel_out]; - - always @(posedge clk) begin - chan_out_all_reg <= chan_out_all; - end + import pronoc_pkg::*; + + input [NE-1 : 0] sel_in; + input [NEw-1 : 0] sel_out; + input smartflit_chanel_t chan_in; + output smartflit_chanel_t chan_out; + input reset,clk; + + + smartflit_chanel_t chan_in_all [NE-1 : 0]; + smartflit_chanel_t chan_out_all [NE-1 : 0]; + smartflit_chanel_t chan_out_all_reg [NE-1 : 0]; + + wire noc_reset; + + noc_top top ( + .reset(noc_reset), + .clk(clk), + .chan_in_all(chan_in_all), + .chan_out_all(chan_out_all), + .router_event( ) + ); + + + altera_reset_synchronizer sync( + .reset_in (reset), + .clk (clk), + .reset_out (noc_reset) + ); + + //NoC port assignment + + assign chan_out = chan_out_all_reg[sel_out]; + + always @(posedge clk) begin + chan_out_all_reg <= chan_out_all; + end - genvar IP_NUM; - generate + genvar IP_NUM; + generate for (IP_NUM=0; IP_NUM { + "NOC_ID" => "0", "TOPOLOGY" => "\"MESH\"", "T1" => "8", "T2" => "8", @@ -44,6 +45,7 @@ $model = bless({ 'parameters_order' => { 'noc_param' => [ + 'NOC_ID', 'TOPOLOGY', 'T1', 'T2', diff --git a/mpsoc/perl_gui/lib/perl/emulator.pl b/mpsoc/perl_gui/lib/perl/emulator.pl index c8487d8..7338905 100755 --- a/mpsoc/perl_gui/lib/perl/emulator.pl +++ b/mpsoc/perl_gui/lib/perl/emulator.pl @@ -728,8 +728,7 @@ sub create_emulate_top{ //noc emulator noc_emulator #( .STATISTIC_VJTAG_INDEX(STATISTIC_VJTAG_INDEX), - .PATTERN_VJTAG_INDEX(PATTERN_VJTAG_INDEX), - .NOC_ID(0) + .PATTERN_VJTAG_INDEX(PATTERN_VJTAG_INDEX) ) noc_emulate_top ( diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index 99b4a53..c784c5a 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -640,11 +640,21 @@ sub noc_config{ $label=gen_label_in_center(' '); $table->attach ( $label , 2, 3, $row,$row+1 ,'fill','shrink',2,2); $table->attach ( $b1 , 0, 2, $row,$row+1,'fill','shrink',2,2); - $row++; + $row++; } my $coltmp=0; - + + #NoC_ID + $label='NoC ID'; + $param='NOC_ID'; + $default='0'; + $content='0,255,1'; + $type='Spin-button'; + $info="Unique identifier for the NoC. Will be modified by phy_noc_gen.pl script."; + $noc_param_comment{'NOC_ID'}="Unique identifier for the NoC. Will be modified by phy_noc_gen.pl script"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param,1); + #Router type $label='Router Type'; $param='ROUTER_TYPE'; @@ -675,13 +685,13 @@ sub noc_config{ } else { $noc_param_comment{'V'}="Number of Virtual chanel per each router port. V is equal to 1 means there is no VC."; $mpsoc->object_add_attribute($noc_param,'V',1); - $mpsoc->object_add_attribute($noc_param,'C',0); + $mpsoc->object_add_attribute($noc_param,'C',0); } #buffer width per VC $label=($router_type eq '"VC_BASED"')? 'Buffer flits per VC': "Buffer flits"; $param='B'; - $default='4'; + $default='4'; $content='2,256,1'; $type='Spin-button'; $info=($router_type eq '"VC_BASED"')? 'Buffer queue size per VC in flits' : 'Buffer queue size in flits'; @@ -692,7 +702,7 @@ sub noc_config{ #Local port buffer width per VC $label=($router_type eq '"VC_BASED"')? 'Local port Buffer flits per VC': "Local Port Buffer flits"; $param='LB'; - $default='4'; + $default='4'; $content='2,256,1'; $type='Spin-button'; $info = "Buffer width for local router ports connected to endpoints. diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl index f77bc7d..dc4a644 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_verilog_gen.pl @@ -34,7 +34,7 @@ sub mpsoc_generate_verilog{ $param_as_in_v = (defined $param_as_in_v)? "$param_as_in_v,\nparameter NOC_ID=0\n" : "parameter NOC_ID=0\n"; my $global_localparam=get_golal_param_v(); my $pdef = "`include \"pronoc_def.v\""; - my $mpsoc_v = (defined $param_as_in_v )? " $pdef\nmodule $mpsoc_name\n\t #(\n $param_as_in_v)(\n$io_short\n);\n\t`NOC_CONF": "$pdef\nmodule $mpsoc_name\n \t (\n$io_short\n);\n\t`NOC_CONF"; + my $mpsoc_v = (defined $param_as_in_v )? " $pdef\nmodule $mpsoc_name\n\t #(\n $param_as_in_v)(\n$io_short\n);\n\timport pronoc_pkg::*;": "$pdef\nmodule $mpsoc_name\n \t (\n$io_short\n);\n\timport pronoc_pkg::*;"; $mpsoc_v=$mpsoc_v. " $global_localparam $socs_param @@ -373,25 +373,22 @@ sub gen_noc_v{ //connection wire to NoC smartflit_chanel_t ni_chan_in [NE-1 : 0]; smartflit_chanel_t ni_chan_out [NE-1 : 0]; - wire noc_clk_in,noc_reset_in; + wire noc_clk_in,noc_reset_in; //NoC - noc_top # ( - .NOC_ID(NOC_ID) - ) the_noc ( + noc_top the_noc ( .reset(noc_reset_in), .clk(noc_clk_in), .chan_in_all(ni_chan_out), .chan_out_all(ni_chan_in), .router_event( ) ); - clk_source src ( + clk_source src ( .clk_in($noc_clk), .clk_out(noc_clk_in), .reset_in($noc_reset), .reset_out(noc_reset_in) ); "; -; return $noc_v; } diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index b88e1e5..8187c67 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -101,14 +101,12 @@ sub generate_topology_top_v { print $fd " module ${name}_noc -#( - parameter NOC_ID=0 -)( +( $ports ); - `NOC_CONF + import pronoc_pkg::*; - input reset,clk; + input reset,clk; $wires @@ -146,7 +144,6 @@ sub get_router_instance_v { *******************/ router_config_t ${instance}_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID($current_r), .P($Pnum) ) $instance ( @@ -353,16 +350,15 @@ sub generate_topology_top_genvar_v{ assign router_config [RID].router_id = RID[RAw-1: 0]; assign router_config [RID].router_addr = RID[RAw-1: 0]; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P($i) ) router_${i}_port ( .clk(clk), .reset(reset), .router_config_in(router_config\[RID\]), - .chan_in (router_chan_in \[RID\] \[$p : 0\]), + .chan_in (router_chan_in \[RID\] \[$p : 0\]), .chan_out (router_chan_out\[RID\] \[$p : 0\]), - .router_event(router_event\[RID\] \[$p : 0\]) + .router_event(router_event\[RID\] \[$p : 0\]) ); end "; @@ -379,24 +375,22 @@ sub generate_topology_top_genvar_v{ $offset+= $n; } } - $routers.="endgenerate\n"; + $routers.="endgenerate\n"; print $fd " module ${name}_noc_genvar -#( - parameter NOC_ID=0 -)( +( reset, - clk, + clk, chan_in_all, chan_out_all, - router_event + router_event ); -`NOC_CONF +import pronoc_pkg::*; $ports_def $router_wires $endps_wires $routers -$assign +$assign endmodule "; close $fd; @@ -457,7 +451,6 @@ sub get_router_genvar_instance_v{ assign router_config[$router_pos].router_id = $router_pos; assign router_config[$router_pos].router_addr = $router_pos; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID($router_pos), .P($Pnum) ) router_${Pnum}_port ( @@ -1096,12 +1089,10 @@ sub generate_connection_v{ } print $fd " module ${name}_connection -#( - parameter NOC_ID=0 -)( +( $ports ); - `NOC_CONF + import pronoc_pkg::*; localparam P= MAX_P, @@ -1256,9 +1247,7 @@ sub add_noc_instance_v{ my $str=" //do not modify this line ===${name}=== if(TOPOLOGY == \"$name\" ) begin : T$name - ${name}_connection #( - .NOC_ID(NOC_ID) - ) connection ( + ${name}_connection connection ( $ports ); end @@ -1279,20 +1268,18 @@ sub add_noc_instance_v{ $str=" //do not modify this line ===${name}=== if(TOPOLOGY == \"$name\" ) begin : T$name - ${name}_noc_genvar #( - .NOC_ID(NOC_ID) - ) the_noc ( + ${name}_noc_genvar the_noc ( .reset(reset), - .clk(clk), + .clk(clk), .chan_in_all(chan_in_all), .chan_out_all(chan_out_all), - .router_event(router_event) + .router_event(router_event) ); end endgenerate "; - - my $file = "$dir/../common/custom_noc_top.sv"; + + my $file = "$dir/../common/custom_noc_top.sv"; #check if ***$name**** exist in the file unless (-f $file){ add_colored_info($info,"$file dose not exist\n",'red'); diff --git a/mpsoc/perl_gui/lib/perl/verilog_gen.pl b/mpsoc/perl_gui/lib/perl/verilog_gen.pl index fa4514b..3cdeeb3 100755 --- a/mpsoc/perl_gui/lib/perl/verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/verilog_gen.pl @@ -66,7 +66,7 @@ sub soc_generate_verilog{ $unused_wiers_v="" if(!defined $unused_wiers_v); $sockets_assign_v_all="" if(!defined $sockets_assign_v_all); my $has_ni =check_for_ni($soc); - my $import = ($has_ni)? "\n\t`NOC_CONF\n" : ""; + my $import = ($has_ni)? "\n\timport pronoc_pkg::*;\n" : ""; my $tscale = ($has_ni)? "`include \"pronoc_def.v\"\n" : "`timescale 1ns / 1ps\n"; my $global_localparam=get_golal_param_v(); my $soc_v = (defined $param_as_in_v_all )? "$tscale module $soc_name #(\n $param_as_in_v_all\n)(\n$io_sim_v_all\n);\n$import\n": "$tscale module $soc_name (\n$io_sim_v_all\n);\n $import\n"; @@ -961,7 +961,7 @@ sub soc_generate_verilator{ $top_io_full_all=$top_io_full_all."\n$src_io_full_all"; # $top_io_pass_all=$top_io_pass_all.",\n$clk_assigned_port"; my $has_ni =check_for_ni($soc); - my $import = ($has_ni)? "\n\t`NOC_CONF\n" : ""; + my $import = ($has_ni)? "\n\timport pronoc_pkg::*;\n" : ""; my $verilator_v = " /********************* ${name} diff --git a/mpsoc/rtl/arch/baseline.v b/mpsoc/rtl/arch/baseline.v index 2afb3a2..6ae0b7b 100755 --- a/mpsoc/rtl/arch/baseline.v +++ b/mpsoc/rtl/arch/baseline.v @@ -302,7 +302,7 @@ module canonical_vc_alloc #( ); end - custom_or #( + reduction_or #( .IN_NUM (P_1), .OUT_WIDTH (V) diff --git a/mpsoc/rtl/arch/flit_buffer_reg_bas.v b/mpsoc/rtl/arch/flit_buffer_reg_bas.v index 44bc763..9afca74 100644 --- a/mpsoc/rtl/arch/flit_buffer_reg_bas.v +++ b/mpsoc/rtl/arch/flit_buffer_reg_bas.v @@ -8,7 +8,6 @@ `timescale 1ns / 1ps module flit_buffer_reg_base #( - parameter NOC_ID = 0, parameter V = 4, parameter B = 4, // buffer space :flit per VC parameter Fpay = 32, @@ -183,7 +182,6 @@ module flit_buffer_reg_base #( extract_header_flit_info #( - .NOC_ID(NOC_ID), .DATA_w(0) ) header_extractor ( .flit_in({flit_reg_mux_out[REGFw-1:REGFw-2],flit_reg_wr_en,flit_reg_mux_out[Fpay-1 : 0]}), diff --git a/mpsoc/rtl/arch/iport_reg_base.sv b/mpsoc/rtl/arch/iport_reg_base.sv index d771ddd..40b4078 100644 --- a/mpsoc/rtl/arch/iport_reg_base.sv +++ b/mpsoc/rtl/arch/iport_reg_base.sv @@ -36,7 +36,6 @@ **************************/ module iport_reg_base #( - parameter NOC_ID=0, parameter PCK_TYPE = "MULTI_FLIT", parameter V = 4, // vc_num_per_port parameter P = 5, // router port num @@ -187,7 +186,6 @@ module iport_reg_base #( //extract header flit info extract_header_flit_info #( - .NOC_ID(NOC_ID), .DATA_w(0) ) header_extractor ( .flit_in(flit_in), @@ -582,7 +580,6 @@ generate flit_buffer_reg_base #( - .NOC_ID(NOC_ID), .V(V), .B(B), .SSA_EN(SSA_EN), @@ -691,7 +688,6 @@ endgenerate ); header_flit_update_lk_route_ovc #( - .NOC_ID(NOC_ID), .P(P) ) the_flit_update ( .flit_in (buffer_out), diff --git a/mpsoc/rtl/main_comp.v b/mpsoc/rtl/main_comp.v index f2c18b9..c749063 100755 --- a/mpsoc/rtl/main_comp.v +++ b/mpsoc/rtl/main_comp.v @@ -163,29 +163,24 @@ module one_hot_demux #( endmodule /************************** -* custom_or +* reduction_or ***************************/ -module custom_or #( - parameter IN_NUM = 4, - parameter OUT_WIDTH = 5 +module reduction_or #( + parameter W = 5,//out width + parameter N = 4 //array lenght )( - or_in, - or_out + D_in, + Q_out ); + input [W-1 : 0] D_in [N-1 : 0]; + output reg [W-1 : 0] Q_out; - localparam IN_WIDTH = IN_NUM*OUT_WIDTH; - input [IN_WIDTH-1 : 0] or_in; - output[OUT_WIDTH-1 : 0] or_out; - wire [IN_NUM-1 : 0] in_sep [OUT_WIDTH-1 : 0]; - genvar i,j; - generate - for (i=0;ij)begin - assign nonspec_portsel_granted[i][j] = nonspec_outport_granted_all [j]; + assign nonspec_portsel_granted[i][j] = nonspec_outport_granted_all [j]; end //if(i==j) wires are left disconnected end//j // an speculative grant is acceptable if the non-speculative request is not granted for both inport request and outport grant assign spec_request_acceptable[(i+1)*P_1-1 : i*P_1] = (nonspec_inport_granted_all[i])? {P_1{1'b0}} : ~nonspec_portsel_granted[i]; - assign spec_request_accepted [i]= spec_request_acceptable[(i+1)*P_1-1 : i*P_1] & spec_granted_dest_port_all_pre[(i+1)*P_1-1 : i*P_1]; - assign any_spec_request_accepted [i] = |spec_request_accepted [i]; + assign spec_request_accepted [i]= spec_request_acceptable[(i+1)*P_1-1 : i*P_1] & spec_granted_dest_port_all_pre[(i+1)*P_1-1 : i*P_1]; + assign any_spec_request_accepted [i] = |spec_request_accepted [i]; assign spec_ivc_granted_all_accepted[(i+1)*V-1 : i*V] = (any_spec_request_accepted [i] & valid_speculation[i])? spec_ivc_granted_all[(i+1)*V-1 : i*V]: {V{1'b0}}; assign spec_granted_dest_port_all_accepted[(i+1)*P_1-1 : i*P_1]=(valid_speculation[i])? spec_request_accepted [i]: {P_1{1'b0}}; @@ -383,10 +362,7 @@ endmodule * **********************************/ module sw_alloc_sub#( - parameter V = 4, - parameter P = 5, - parameter SWA_ARBITER_TYPE="RRA", - parameter MIN_PCK_SIZE=2 //minimum packet size in flits. The minimum value is 1. + parameter P = 5 )( ivc_granted_all, ivc_request_all, @@ -403,13 +379,14 @@ module sw_alloc_sub#( pck_is_single_flit_all, granted_dst_is_from_a_single_flit_pck, clk, - reset + reset ); + import pronoc_pkg::*; localparam P_1 = P-1,//assumed that no port request for itself! PV = V * P, - VP_1 = V * P_1, - PVP_1 = P * VP_1, + VP_1 = V * P_1, + PVP_1 = P * VP_1, PP_1 = P_1 * P, PP = P * P; @@ -437,18 +414,18 @@ module sw_alloc_sub#( wire [VP_1-1 : 0] dest_port_ivc [P-1 : 0]; wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; // internal wires - wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and - wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter + wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and + wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer - wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; - wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; + wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; + wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; wire [P_1-1 : 0] second_arbiter_weight_consumed [P-1 : 0]; wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; wire [P-1 : 0] winner_weight_consumed; wire [P_1-1 : 0] single_flit_granted_dst [P-1 : 0]; - wire [PP-1 : 0] single_flit_granted_dst_all; - wire [V-1 : 0] pck_is_single_flit [P-1 : 0]; - wire [P-1 : 0] single_flit_pck_local_grant; + wire [P-1 : 0] single_flit_granted_dst_all [P-1 : 0]; + wire [V-1 : 0] pck_is_single_flit [P-1 : 0]; + wire [P-1 : 0] single_flit_pck_local_grant; genvar i,j; generate @@ -465,7 +442,7 @@ module sw_alloc_sub#( assign vc_weight_is_consumed[i] = vc_weight_is_consumed_all [(i+1)*V-1 : i*V]; //mask assign ivc_masked[i] = ivc_request[i] & ivc_not_full[i]; - //first level arbiter + //first level arbiter swa_input_port_arbiter #( .ARBITER_WIDTH(V), .EXT_P_EN(0) @@ -493,25 +470,25 @@ module sw_alloc_sub#( assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; //single_flit req multiplexer one_hot_mux #( - .IN_WIDTH (V), - .SEL_WIDTH (V) + .IN_WIDTH(V), + .SEL_WIDTH(V) ) mux2 ( - .mux_in (pck_is_single_flit [i]), - .mux_out (single_flit_pck_local_grant[i]), - .sel (first_arbiter_grant[i]) - ); - assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; + .mux_in(pck_is_single_flit[i]), + .mux_out(single_flit_pck_local_grant[i]), + .sel(first_arbiter_grant[i]) + ); + assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i]) ? granted_dest_port[i] : {P_1{1'b0}}; add_sw_loc_one_hot #( .P(P), .SW_LOC(i) ) add_sw_loc ( .destport_in(single_flit_granted_dst[i]), - .destport_out(single_flit_granted_dst_all[(i+1)*P-1 : i*P]) + .destport_out(single_flit_granted_dst_all[i]) ); end else begin : single_flit_notsupported assign single_flit_pck_local_grant[i] = 1'b0; assign single_flit_granted_dst[i] = {P_1{1'b0}}; - assign single_flit_granted_dst_all[(i+1)*P-1 : i*P]={P{1'b0}}; + assign single_flit_granted_dst_all[i] = {P{1'b0}}; end //second arbiter input/output generate for(j=0;j7)begin : cmb_v2 comb_nonspec_v2_allocator #( - .V(V), - .P(P), - .FIRST_ARBITER_EXT_P_EN(FIRST_ARBITER_EXT_P_EN), - .SWA_ARBITER_TYPE (SWA_ARBITER_TYPE), - .MIN_PCK_SIZE(MIN_PCK_SIZE), - .SELF_LOOP_EN(SELF_LOOP_EN) + .P(P) ) nonspec_comb ( .dest_port_all(dest_port_all), .masked_ovc_request_all(masked_ovc_request_all), @@ -224,12 +208,11 @@ module combined_vc_sw_alloc #( ); end else begin :cmb_v1 comb_nonspec_allocator #( - .NOC_ID(NOC_ID), .P(P) ) nonspec_comb ( .ivc_info(ivc_info), .dest_port_all(dest_port_all), - .masked_ovc_request_all(masked_ovc_request_all), + .masked_ovc_request_all(masked_ovc_request_all), .ovc_allocated_all(ovc_allocated_all), .granted_ovc_num_all(granted_ovc_num_all), .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant), diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.sv b/mpsoc/rtl/src_noc/congestion_analyzer.sv index 1322905..3703b1e 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.sv +++ b/mpsoc/rtl/src_noc/congestion_analyzer.sv @@ -311,7 +311,7 @@ module port_presel_based_dst_routers_ovc #( *pre_sel * 0: xdir * 1: ydir - ********************/ + ********************/ wire [P_1-1 : 0] conjestion_cmp; assign conjestion_cmp[Q3] = (cong_from_east_Q3 > cong_from_north_Q3)? YDIR :XDIR; assign conjestion_cmp[Q2] = (cong_from_east_Q2 > cong_from_south_Q2)? YDIR :XDIR; @@ -324,14 +324,7 @@ endmodule * port_pre_sel_gen ************************/ module port_pre_sel_gen #( - parameter PPSw=4, - parameter P=5, - parameter V=4, - parameter B=4, - parameter CONGESTION_INDEX=2, - parameter CONGw=2, - parameter ROUTE_TYPE="ADAPTIVE", - parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001 + parameter P=5 )( port_pre_sel, ovc_status, @@ -342,7 +335,7 @@ module port_pre_sel_gen #( reset, clk ); - `NOC_CONF + import pronoc_pkg::*; localparam P_1 = P-1, PV = P * V, @@ -392,7 +385,7 @@ module port_pre_sel_gen #( .PPSw(PPSw), .P(P), .CONGw(CONGw) - ) port_presel_gen ( + ) port_presel_gen ( .congestion_in_all(congestion_in_all), .port_pre_sel(port_pre_sel), .reset(reset), @@ -431,9 +424,9 @@ module congestion_out_based_ivc_req #( PV = (V*P), CONG_ALw = (CONGw* P); // congestion width per router; - input [PV-1 : 0] ivc_request_all; - output [CONG_ALw-1 : 0] congestion_out_all; - wire [CONGw-1 : 0] congestion_out ; + input [PV-1 : 0] ivc_request_all; + output [CONG_ALw-1 : 0] congestion_out_all; + wire [CONGw-1 : 0] congestion_out ; parallel_count_normalize #( .INw (PV), diff --git a/mpsoc/rtl/src_noc/crossbar.sv b/mpsoc/rtl/src_noc/crossbar.sv index 22b6956..fca34a1 100755 --- a/mpsoc/rtl/src_noc/crossbar.sv +++ b/mpsoc/rtl/src_noc/crossbar.sv @@ -26,7 +26,6 @@ **************************************************************/ module crossbar #( - parameter NOC_ID=0, parameter TOPOLOGY = "MESH", parameter V = 4, // vc_num_per_port parameter P = 5, // router port num @@ -75,7 +74,7 @@ module crossbar #( wire [P_1-1 : 0] mux_sel_pre [P-1 : 0]; wire [P_1-1 : 0] mux_sel [P-1 : 0]; wire [P_1w-1 : 0] mux_sel_bin [P-1 : 0]; - wire [PP-1 : 0] flit_out_wr_gen; + wire [P-1 : 0] flit_out_wr_gen [P-1 : 0]; genvar i,j; generate @@ -100,7 +99,6 @@ module crossbar #( if (SSA_EN) begin : predict //If no output is granted replace the output port with SS port add_ss_port #( - .NOC_ID(NOC_ID), .SW_LOC(i), .P(P) ) ss_port ( @@ -146,19 +144,19 @@ module crossbar #( .SW_LOC(i) ) add_sw_loc ( .destport_in(granted_dest_port_all[(i+1)*P_1-1 : i*P_1]), - .destport_out(flit_out_wr_gen [(i+1)*P-1 : i*P]) + .destport_out(flit_out_wr_gen [i]) ); - end else begin :slp - assign flit_out_wr_gen [(i+1)*P-1 : i*P] = granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; + end else begin :slp + assign flit_out_wr_gen [i] = granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; end - end//for i + end//for i endgenerate - custom_or #( - .IN_NUM(P), - .OUT_WIDTH(P) + reduction_or #( + .W(P), + .N(P) ) wide_or ( - .or_in(flit_out_wr_gen), - .or_out(flit_we_mux_out) + .D_in(flit_out_wr_gen), + .Q_out(flit_we_mux_out) ); - assign flit_out_wr_all = flit_we_mux_out | ssa_flit_wr_all; + assign flit_out_wr_all = flit_we_mux_out | ssa_flit_wr_all; endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index 8c0981a..45fee42 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -316,7 +316,6 @@ endmodule module check_destination_addr #( - parameter NOC_ID=0, parameter TOPOLOGY = "MESH", parameter T1=2, parameter T2=2, @@ -344,9 +343,7 @@ module check_destination_addr #( generate if(CAST_TYPE != "UNICAST") begin wire [NE-1 : 0] dest_mcast_all_endp; - mcast_dest_list_decode #( - .NOC_ID(NOC_ID) - ) decode ( + mcast_dest_list_decode decode ( .dest_e_addr(dest_e_addr), .dest_o(dest_mcast_all_endp), .row_has_any_dest( ), @@ -535,7 +532,6 @@ endmodule module check_pck_size #( - parameter NOC_ID=0, parameter V=2, parameter MIN_PCK_SIZE=2, parameter Fw=36, @@ -609,10 +605,8 @@ module check_pck_size #( .ld (vc_hdr_wr_en [i] ), .Q_out (dest_e_addr[i]) ); - - mcast_dest_list_decode #( - .NOC_ID(NOC_ID) - ) decode ( + + mcast_dest_list_decode decode ( .dest_e_addr(dest_e_addr[i]), .dest_o(dest_mcast_all_endp[i]), .row_has_any_dest(), @@ -620,7 +614,7 @@ module check_pck_size #( ); is_onehot0 #( - .IN_WIDTH(NE) + .IN_WIDTH(NE) ) one_h ( .D_in(dest_mcast_all_endp[i]), .result(onehot[i]) diff --git a/mpsoc/rtl/src_noc/fattree_noc_top.sv b/mpsoc/rtl/src_noc/fattree_noc_top.sv index ad26e2a..4709415 100644 --- a/mpsoc/rtl/src_noc/fattree_noc_top.sv +++ b/mpsoc/rtl/src_noc/fattree_noc_top.sv @@ -38,9 +38,7 @@ ** **************************************************************/ -module fattree_noc_top #( - parameter NOC_ID=0 -) ( +module fattree_noc_top ( reset, clk, chan_in_all, @@ -48,7 +46,7 @@ module fattree_noc_top #( router_event ); - `NOC_CONF + import pronoc_pkg::*; input clk,reset; //Endpoints ports @@ -100,7 +98,6 @@ module fattree_noc_top #( assign router_config_in[RID].router_id = RID [NRw-1 : 0]; assign router_config_in[RID].router_addr = current_r_addr [RID]; router_top # ( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P(K) ) the_router ( @@ -124,7 +121,6 @@ module fattree_noc_top #( assign router_config_in[RID].router_addr = current_r_addr [RID]; router_top # ( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P(2*K) ) the_router ( diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index f2d9d0f..02b3b02 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -32,7 +32,7 @@ module flit_buffer parameter V= 1, parameter B = 4 )( - din, // Data in + din, // Data in vc_num_wr,//write virtual channel vc_num_rd,//read virtual channel wr_en, // Write enable @@ -49,7 +49,7 @@ module flit_buffer flit_is_tail ); - `NOC_CONF + import pronoc_pkg::*; localparam @@ -77,7 +77,7 @@ module flit_buffer input [V-1 :0] ssa_rd; input [V-1 :0] multiple_dest; input [V-1 :0] sub_rd_ptr_ld; - output [V-1 : 0] flit_is_tail; + output [V-1 : 0] flit_is_tail; //pointers wire [PTRw- 1 : 0] rd_ptr [V-1 :0]; diff --git a/mpsoc/rtl/src_noc/fmesh.sv b/mpsoc/rtl/src_noc/fmesh.sv index 81e61a7..dab38d2 100644 --- a/mpsoc/rtl/src_noc/fmesh.sv +++ b/mpsoc/rtl/src_noc/fmesh.sv @@ -362,7 +362,7 @@ module fmesh_distance_gen ( dest_e_addr, distance ); - `NOC_CONF + import pronoc_pkg::*; localparam Xw = log2(T1), // number of node in x axis diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index b8673d6..5ed3a65 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -30,9 +30,8 @@ ***************/ module header_flit_generator #( - parameter NOC_ID=0, parameter DATA_w=9 // header flit can carry Optional data. The data will be placed after control data. Fpay >= DATA_w + CTRL_BITS_w -)( +)( flit_out, src_e_addr_in, dest_e_addr_in, @@ -44,7 +43,7 @@ module header_flit_generator #( data_in ); - `NOC_CONF + import pronoc_pkg::*; localparam HDR_FLAG = 2'b10; localparam Dw = (DATA_w==0)? 1 : DATA_w, @@ -103,7 +102,6 @@ endmodule module extract_header_flit_info # ( - parameter NOC_ID=0, parameter DATA_w = 0 ) ( //inputs @@ -123,7 +121,7 @@ module extract_header_flit_info # ( be_o ); - `NOC_CONF + import pronoc_pkg::*; localparam W = WEIGHTw, @@ -188,7 +186,6 @@ endmodule * update the header flit look ahead routing and output VC *********************************/ module header_flit_update_lk_route_ovc #( - parameter NOC_ID=0, parameter P = 5 )( flit_in , @@ -202,7 +199,7 @@ module header_flit_update_lk_route_ovc #( reset, clk ); - `NOC_CONF + import pronoc_pkg::*; localparam VDSTPw = V * DSTPw, @@ -299,14 +296,12 @@ endmodule /****************** * hdr_flit_weight_update * ****************/ -module hdr_flit_weight_update #( - parameter NOC_ID = 0 -) ( +module hdr_flit_weight_update ( new_weight, flit_in, flit_out ); - `NOC_CONF + import pronoc_pkg::*; input [WEIGHTw-1 : 0] new_weight; input [Fw-1 : 0] flit_in; diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index cc65f7b..c610cca 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -26,7 +26,6 @@ **************************************************************/ module inout_ports #( - parameter NOC_ID=0, parameter ROUTER_ID=0, parameter P=5 )( @@ -87,7 +86,7 @@ module inout_ports #( smart_ctrl_in ); - `NOC_CONF + import pronoc_pkg::*; localparam PV = V * P, @@ -169,7 +168,6 @@ module inout_ports #( ssa_ctrl_t ssa_ctrl [P-1 : 0]; input_ports #( - .NOC_ID(NOC_ID), .ROUTER_ID(ROUTER_ID), .P(P) ) the_input_port ( @@ -209,7 +207,6 @@ module inout_ports #( ); output_ports #( - .NOC_ID(NOC_ID), .P (P) ) output_ports ( .vsa_ovc_allocated_all (vsa_ovc_allocated_all), @@ -242,7 +239,6 @@ module inout_ports #( ); vc_alloc_request_gen #( - .NOC_ID(NOC_ID), .P(P) ) vc_alloc_req_gen ( .ivc_info(ivc_info), @@ -282,7 +278,6 @@ module inout_ports #( if( SSA_EN == 1 ) begin : ssa ss_allocator #( - .NOC_ID(NOC_ID), .P(P) ) the_ssa ( .ivc_info(ivc_info), @@ -429,7 +424,6 @@ endmodule vc_alloc_request_gen ************************/ module vc_alloc_request_gen #( - parameter NOC_ID=0, parameter P=5 ) ( ivc_info, @@ -448,7 +442,7 @@ module vc_alloc_request_gen #( ctrl_in ); - `NOC_CONF + import pronoc_pkg::*; localparam P_1 = (SELF_LOOP_EN )? P : P-1, diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 978f6b4..bd1f216 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -29,7 +29,6 @@ **************************************************************/ module input_ports #( - parameter NOC_ID=0, parameter ROUTER_ID=0, parameter P=5 )( @@ -69,7 +68,7 @@ module input_ports #( clk ); - `NOC_CONF + import pronoc_pkg::*; localparam PV = V * P, @@ -131,7 +130,6 @@ module input_ports #( input_queue_per_port // iport_reg_base #( - .NOC_ID(NOC_ID), .ROUTER_ID(ROUTER_ID), .SW_LOC(i), .P(P) @@ -179,7 +177,6 @@ endmodule input_queue_per_port **************************/ module input_queue_per_port #( - parameter NOC_ID=0, parameter ROUTER_ID=0, parameter P = 5, // router port num parameter SW_LOC = 0 @@ -218,7 +215,7 @@ module input_queue_per_port #( ctrl_in ); - `NOC_CONF + import pronoc_pkg::*; localparam PORT_B = port_buffer_size(SW_LOC), @@ -385,7 +382,6 @@ module input_queue_per_port #( //extract header flit info extract_header_flit_info #( - .NOC_ID(NOC_ID), .DATA_w(0) ) header_extractor ( .flit_in(flit_in), @@ -705,13 +701,11 @@ module input_queue_per_port #( assign clear_dspt_mulicast [i] = (reset_ivc[i] & multiple_dest[i]) ? dest_port_encoded[i] : {DSTPw{1'b0}}; // a fix priority arbiter. - multicast_dst_sel #( - .NOC_ID(NOC_ID) - ) sel_arb( + multicast_dst_sel sel_arb( .destport_in(dest_port_multi[i]), .destport_out(dest_port_encoded[i]) ); - + //check if we have multiple port to send a packet to is_onehot0 #( .IN_WIDTH(DSTPw) @@ -959,7 +953,6 @@ module input_queue_per_port #( if(CAST_TYPE== "UNICAST") begin : unicast /* verilator lint_on WIDTH */ look_ahead_routing #( - .NOC_ID(NOC_ID), .T1(T1), .T2(T2), .T3(T3), @@ -986,7 +979,6 @@ module input_queue_per_port #( end // unicast endgenerate header_flit_update_lk_route_ovc #( - .NOC_ID(NOC_ID), .P(P) ) the_flit_update ( .flit_in (buffer_out), diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 8023dfe..05f2d29 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -667,7 +667,7 @@ module mesh_torus_distance_gen ( dest_e_addr, distance ); - `NOC_CONF + import pronoc_pkg::*; localparam NYY =(IS_RING | IS_LINE )? 1 : T2, diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index b6ce77c..8da550b 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -26,9 +26,7 @@ ** **************************************************************/ -module mesh_torus_noc_top #( - parameter NOC_ID=0 -) ( +module mesh_torus_noc_top ( reset, clk, chan_in_all, @@ -36,7 +34,7 @@ module mesh_torus_noc_top #( router_event ); - `NOC_CONF + import pronoc_pkg::*; input clk,reset; //Endpoints ports @@ -64,11 +62,10 @@ module mesh_torus_noc_top #( assign router_config_in[x].router_addr = RID[RAw-1: 0]; assign router_config_in[x].router_id = RID[NRw-1: 0]; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P (MAX_P) ) the_router ( - .router_config_in(router_config_in[RID]), + .router_config_in(router_config_in[RID]), .chan_in(router_chan_in [RID]), .chan_out(router_chan_out[RID]), .router_event(router_event[RID]), @@ -108,7 +105,6 @@ module mesh_torus_noc_top #( assign router_config_in[RID].router_id = RID[NRw-1: 0]; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P(MAX_P) ) the_router ( diff --git a/mpsoc/rtl/src_noc/mesh_torus_routting.sv b/mpsoc/rtl/src_noc/mesh_torus_routting.sv index 8333d6f..db0506b 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_routting.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_routting.sv @@ -10,19 +10,19 @@ module mesh_torus_look_ahead_routing #( )( current_x, //current router x address current_y, //current router y address - dest_x, // destination router x address - dest_y, // destination router y address - destport_encoded, // current router destination port number + dest_x, // destination router x address + dest_y, // destination router y address + destport_encoded, // current router destination port number lkdestport_encoded, // look ahead destination port number reset, clk ); - `NOC_CONF + import pronoc_pkg::*; localparam P = ( IS_MESH || IS_FMESH || IS_TORUS ) ? 5 : 3; localparam P_1 = P-1; input [NXw-1 : 0] current_x; - input [NYw-1 : 0] current_y; + input [NYw-1 : 0] current_y; input [NXw-1 : 0] dest_x; input [NYw-1 : 0] dest_y; input [P_1-1 : 0] destport_encoded; @@ -81,11 +81,11 @@ module mesh_torus_deterministic_look_ahead_routing #( destport, // current router destination port number lkdestport // look ahead destination port number ); - `NOC_CONF + import pronoc_pkg::*; localparam P_1 = P-1; input [NXw-1 : 0] current_x; - input [NYw-1 : 0] current_y; + input [NYw-1 : 0] current_y; input [NXw-1 : 0] dest_x; input [NYw-1 : 0] dest_y; input [P_1-1 : 0] destport; @@ -138,7 +138,7 @@ endmodule * adaptive_look_ahead_routing **********************************************/ module mesh_torus_adaptive_look_ahead_routing #( - parameter P =5 + parameter P =5 )( current_x, //current router x address current_y, //current router y address @@ -147,7 +147,7 @@ module mesh_torus_adaptive_look_ahead_routing #( destport_encoded, // current router destination port lkdestport_encoded // look ahead destination port ); - `NOC_CONF + import pronoc_pkg::*; localparam P_1 = P-1; input [NXw-1 : 0] current_x; input [NYw-1 : 0] current_y; @@ -237,7 +237,7 @@ module mesh_torus_next_router_addr_predictor #( next_x, next_y ); - `NOC_CONF + import pronoc_pkg::*; localparam [NXw-1 : 0] LAST_X_ADDR =(NX[NXw-1 : 0]-1'b1); localparam [NYw-1 : 0] LAST_Y_ADDR =(NY[NYw-1 : 0]-1'b1); @@ -298,7 +298,7 @@ module mesh_torus_next_router_inport_predictor #( destport, receive_port ); - `NOC_CONF + import pronoc_pkg::*; input [P-1 : 0] destport; output [P-1 : 0] receive_port; @@ -360,7 +360,7 @@ module remove_receive_port_one_hot #( destport_in, destport_out ); - `NOC_CONF + import pronoc_pkg::*; localparam P_1 = P-1, @@ -465,7 +465,7 @@ module mesh_torus_conventional_routing #( destport ); - `NOC_CONF + import pronoc_pkg::*; localparam P = (IS_RING || IS_LINE ) ? 3 : 5, diff --git a/mpsoc/rtl/src_noc/multicast.sv b/mpsoc/rtl/src_noc/multicast.sv index 3f55306..94f3b3f 100644 --- a/mpsoc/rtl/src_noc/multicast.sv +++ b/mpsoc/rtl/src_noc/multicast.sv @@ -13,7 +13,6 @@ * look_ahead_routing *************************************/ module multicast_routing # ( - parameter NOC_ID=0, parameter SW_LOC=0, parameter P=5 )( @@ -21,14 +20,13 @@ module multicast_routing # ( dest_e_addr, // destination endpoint address destport ); - `NOC_CONF + import pronoc_pkg::*; input [RAw-1 : 0] current_r_addr; input [DAw-1 : 0] dest_e_addr; output [DSTPw-1 : 0] destport; generate if(IS_MESH) begin: mesh multicast_routing_mesh #( - .NOC_ID(NOC_ID), .P(P) , .SW_LOC(SW_LOC) ) routing ( @@ -38,7 +36,6 @@ module multicast_routing # ( ); end else if (IS_FMESH) begin : fmesh multicast_routing_fmesh #( - .NOC_ID(NOC_ID), .P(P) , .SW_LOC(SW_LOC) ) routing ( @@ -48,7 +45,6 @@ module multicast_routing # ( ); end else if (IS_STAR) begin : star multicast_routing_star #( - .NOC_ID(NOC_ID), .P(P) , .SW_LOC(SW_LOC) ) routing ( @@ -70,7 +66,6 @@ endmodule module multicast_routing_mesh #( - parameter NOC_ID=0, parameter SW_LOC=0, parameter P=5 )( @@ -79,7 +74,7 @@ module multicast_routing_mesh #( destport ); - `NOC_CONF + import pronoc_pkg::*; input [RAw-1 : 0] current_r_addr; input [DAw-1 : 0] dest_e_addr; @@ -113,9 +108,7 @@ module multicast_routing_mesh #( ); wire [NX-1 : 0] row_has_any_dest; wire [NE-1 : 0] dest_mcast_all_endp; - mcast_dest_list_decode #( - .NOC_ID(NOC_ID) - ) decode ( + mcast_dest_list_decode decode ( .dest_e_addr(dest_e_addr), .dest_o(dest_mcast_all_endp), .row_has_any_dest(row_has_any_dest), @@ -188,7 +181,6 @@ module multicast_routing_mesh #( endmodule module multicast_routing_star #( - parameter NOC_ID=0, parameter SW_LOC=0, parameter P=5 )( @@ -196,14 +188,12 @@ module multicast_routing_star #( dest_e_addr, // destination endpoint address destport ); - `NOC_CONF + import pronoc_pkg::*; input [RAw-1 : 0] current_r_addr; input [DAw-1 : 0] dest_e_addr; output [DSTPw-1 : 0] destport; - mcast_dest_list_decode # ( - .NOC_ID(NOC_ID) - ) decode ( + mcast_dest_list_decode decode ( .dest_e_addr(dest_e_addr), .dest_o(destport), .row_has_any_dest(), @@ -213,7 +203,6 @@ endmodule module multicast_routing_fmesh #( - parameter NOC_ID=0, parameter SW_LOC=0, parameter P=5 ) ( @@ -222,7 +211,7 @@ module multicast_routing_fmesh #( destport ); - `NOC_CONF + import pronoc_pkg::*; input [RAw-1 : 0] current_r_addr; input [DAw-1 : 0] dest_e_addr; output [DSTPw-1 : 0] destport; @@ -256,18 +245,16 @@ module multicast_routing_fmesh #( wire [NX-1 : 0] row_has_any_dest; wire [NE-1 : 0] dest_mcast_all_endp; - - mcast_dest_list_decode # ( - .NOC_ID(NOC_ID) - ) decode ( + + mcast_dest_list_decode decode ( .dest_e_addr(dest_e_addr), .dest_o(dest_mcast_all_endp), .row_has_any_dest(row_has_any_dest), .is_unicast() ); - + genvar i,j; - generate + generate for(i=0; i< NX; i=i+1) begin : X_ assign x_plus[i] = (current_rx > i); /* verilator lint_off UNSIGNED */ @@ -342,16 +329,14 @@ module multicast_routing_fmesh #( endmodule -module mcast_dest_list_decode #( - parameter NOC_ID=0 -) ( +module mcast_dest_list_decode ( dest_e_addr, dest_o, row_has_any_dest, is_unicast ); - `NOC_CONF + import pronoc_pkg::*; input [DAw-1 :0] dest_e_addr; output [NE-1 : 0] dest_o; output [NX-1 : 0] row_has_any_dest; @@ -389,7 +374,7 @@ module mcast_dest_list_decode #( .NE(NE) ) decoder ( .code(unicast_code), - .id(unicast_id) + .id(unicast_id) ); always_comb begin @@ -462,7 +447,6 @@ endmodule module multicast_chan_in_process #( - parameter NOC_ID=0, parameter SW_LOC=0, parameter P=5 )( @@ -473,7 +457,7 @@ module multicast_chan_in_process #( clk ); - `NOC_CONF + import pronoc_pkg::*; input endp_port; input [RAw-1 : 0] current_r_addr; input flit_chanel_t chan_in; @@ -486,17 +470,13 @@ module multicast_chan_in_process #( wire [DSTPw-1 : 0] destport,destport_o; hdr_flit_t hdr_flit; - header_flit_info #( - .NOC_ID (NOC_ID) - ) extract ( + header_flit_info extract ( .flit(chan_in.flit), .hdr_flit(hdr_flit), .data_o() ); - - mcast_dest_list_decode #( - .NOC_ID(NOC_ID) - ) decoder ( + + mcast_dest_list_decode decoder ( .dest_e_addr(hdr_flit.dest_e_addr), .dest_o(dest_mcast_all_endp), .row_has_any_dest(row_has_any_dest_in), @@ -580,7 +560,6 @@ module multicast_chan_in_process #( multicast_routing #( - .NOC_ID(NOC_ID), .P(P) , .SW_LOC(SW_LOC) )routing( @@ -621,17 +600,15 @@ module multicast_chan_in_process #( endmodule -module multicast_dst_sel # ( - parameter NOC_ID=0 -)( +module multicast_dst_sel ( destport_in, - destport_out + destport_out ); - `NOC_CONF + import pronoc_pkg::*; input [DSTPw-1 : 0] destport_in; - output [DSTPw-1 : 0] destport_out; + output [DSTPw-1 : 0] destport_out; wire [DSTPw-1 : 0] arb_in, arb_out; - + function integer mesh_tori_pririty_order; input integer x; begin diff --git a/mpsoc/rtl/src_noc/noc_localparam.v b/mpsoc/rtl/src_noc/noc_localparam.v index 97aa607..9af3342 100644 --- a/mpsoc/rtl/src_noc/noc_localparam.v +++ b/mpsoc/rtl/src_noc/noc_localparam.v @@ -33,6 +33,8 @@ //NoC parameters + localparam NOC_ID=0; + //NOC_ID : Unique identifier for the NoC. Will be modified by phy_noc_gen.pl script localparam TOPOLOGY="MESH"; //TOPOLOGY : Specifies the NoC topology. // Options include "MESH","FMESH","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM" diff --git a/mpsoc/rtl/src_noc/noc_top.sv b/mpsoc/rtl/src_noc/noc_top.sv index 5d700fd..3ed15f6 100644 --- a/mpsoc/rtl/src_noc/noc_top.sv +++ b/mpsoc/rtl/src_noc/noc_top.sv @@ -27,9 +27,7 @@ ** **************************************************************/ -module noc_top #( - parameter NOC_ID=0 -) ( +module noc_top ( reset, clk, chan_in_all, @@ -37,7 +35,7 @@ module noc_top #( router_event ); - `NOC_CONF + import pronoc_pkg::*; input clk,reset; //Endpoints ports @@ -48,9 +46,7 @@ module noc_top #( generate if (IS_MESH | IS_FMESH | IS_TORUS | IS_RING | IS_LINE) begin : tori_noc - mesh_torus_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( + mesh_torus_noc_top noc_top ( .reset (reset ), .clk (clk ), .chan_in_all (chan_in_all ), @@ -58,9 +54,7 @@ module noc_top #( .router_event (router_event ) ); end else if (IS_FATTREE) begin : fat_ - fattree_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( + fattree_noc_top noc_top ( .reset (reset ), .clk (clk ), .chan_in_all (chan_in_all ), @@ -68,9 +62,7 @@ module noc_top #( .router_event (router_event ) ); end else if (IS_TREE) begin : tree_ - tree_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( + tree_noc_top noc_top ( .reset (reset ), .clk (clk ), .chan_in_all (chan_in_all ), @@ -78,9 +70,7 @@ module noc_top #( .router_event (router_event ) ); end else if (IS_STAR) begin : star_ - star_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( + star_noc_top noc_top ( .reset (reset ), .clk (clk ), .chan_in_all (chan_in_all ), @@ -89,9 +79,7 @@ module noc_top #( ); end else if (IS_MULTI_MESH) begin : multimesh /* - multi_mesh #( - .NOC_ID(NOC_ID) - ) noc_top ( + multi_mesh noc_top ( .reset (reset ), .clk (clk ), .chan_in_all (chan_in_all ), @@ -100,10 +88,8 @@ module noc_top #( ); */ end else begin :custom_ - - custom_noc_top #( - .NOC_ID(NOC_ID) - ) noc_top ( + + custom_noc_top noc_top ( .reset (reset ), .clk (clk ), .chan_in_all (chan_in_all ), @@ -122,9 +108,7 @@ endmodule * noc_top being used in another module, * preventing it from being defined as the top module. **************************/ -module noc_top_v #( - parameter NOC_ID=0 -)( +module noc_top_v ( flit_out_all, flit_out_wr_all, credit_in_all, @@ -135,7 +119,7 @@ module noc_top_v #( clk ); - `NOC_CONF + import pronoc_pkg::*; input clk,reset; output [NEFw-1 : 0] flit_out_all; @@ -148,10 +132,8 @@ module noc_top_v #( //struct typed array ports which cannot be caled in verilog smartflit_chanel_t chan_in_all [NE-1 : 0]; smartflit_chanel_t chan_out_all [NE-1 : 0]; - - noc_top #( - .NOC_ID(NOC_ID) - ) the_top( + + noc_top the_top( .reset(reset), .clk(clk), .chan_in_all(chan_in_all), diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index ef97207..bb75a4a 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -27,7 +27,6 @@ module output_ports #( - parameter NOC_ID=0, parameter P=5 ) ( vsa_ovc_allocated_all, @@ -57,7 +56,7 @@ module output_ports #( smart_ctrl_in, credit_init_val_in ); - `NOC_CONF + import pronoc_pkg::*; localparam PV = V * P, @@ -242,7 +241,6 @@ module output_ports #( assign assigned_ovc_num_all[(i+1)*V-1 : i*V] = ivc_info[i/V][i%V].assigned_ovc_num; assign ovc_is_assigned_all[i]=ivc_info[i/V][i%V].ovc_is_assigned; credit_monitor_per_ovc #( - .NOC_ID(NOC_ID), .SW_LOC(i/V) ) credit_monitor ( .credit_init_val_i(credit_init_val_in[i/V][i%V]), @@ -294,14 +292,7 @@ module output_ports #( pronoc_register #(.W(PV)) reg2 (.D_in(ovc_status_next ), .Q_out(ovc_status), .reset(reset), .clk(clk)); port_pre_sel_gen #( - .PPSw(PPSw), - .P(P), - .V(V), - .B(B), - .CONGESTION_INDEX(CONGESTION_INDEX), - .CONGw(CONGw), - .ROUTE_TYPE(ROUTE_TYPE), - .ESCAP_VC_MASK(ESCAP_VC_MASK) + .P(P) ) port_pre_sel_top ( .port_pre_sel(port_pre_sel), .ovc_status(ovc_status), @@ -394,7 +385,6 @@ endmodule * credit_monitor_per_ovc ********************/ module credit_monitor_per_ovc #( - parameter NOC_ID=0, parameter SW_LOC=0 ) ( credit_init_val_i, @@ -408,7 +398,7 @@ module credit_monitor_per_ovc #( clk ); - `NOC_CONF + import pronoc_pkg::*; localparam PORT_B = port_buffer_size(SW_LOC), DEPTHw = log2(PORT_B+1); diff --git a/mpsoc/rtl/src_noc/ovc_list.sv b/mpsoc/rtl/src_noc/ovc_list.sv index 2da26fd..4272ad5 100755 --- a/mpsoc/rtl/src_noc/ovc_list.sv +++ b/mpsoc/rtl/src_noc/ovc_list.sv @@ -27,7 +27,7 @@ module ovc_list ( class_in, ovcs_out ); - `NOC_CONF + import pronoc_pkg::*; input [Cw-1 : 0] class_in; output[V-1 : 0] ovcs_out; diff --git a/mpsoc/rtl/src_noc/packet_injector.sv b/mpsoc/rtl/src_noc/packet_injector.sv index 6ce5aa2..2c01da3 100644 --- a/mpsoc/rtl/src_noc/packet_injector.sv +++ b/mpsoc/rtl/src_noc/packet_injector.sv @@ -32,9 +32,7 @@ ** application traces. **************************************************************/ -module packet_injector #( - parameter NOC_ID=0 -) ( +module packet_injector ( //general current_e_addr, reset, @@ -47,7 +45,7 @@ module packet_injector #( pck_injct_out ); - `NOC_CONF + import pronoc_pkg::*; //general input reset,clk; @@ -71,7 +69,6 @@ module packet_injector #( generate if(CAST_TYPE == "UNICAST") begin : uni conventional_routing #( - .NOC_ID(NOC_ID), .TOPOLOGY(TOPOLOGY), .ROUTE_NAME(ROUTE_NAME), .ROUTE_TYPE(ROUTE_TYPE), @@ -115,7 +112,6 @@ module packet_injector #( wire [Fw-1 : 0] hdr_flit_out; header_flit_generator #( - .NOC_ID(NOC_ID), .DATA_w(HDR_DATA_w) ) the_header_flit_generator ( .flit_out(hdr_flit_out), @@ -244,7 +240,6 @@ module packet_injector #( hdr_flit_t hdr_flit_i; header_flit_info #( - .NOC_ID (NOC_ID), .DATA_w (HDR_DATA_w) ) extractor ( .flit(chan_in.flit_chanel.flit), @@ -272,9 +267,7 @@ module packet_injector #( generate if(CAST_TYPE != "UNICAST") begin - mcast_dest_list_decode #( - .NOC_ID(NOC_ID) - ) decode ( + mcast_dest_list_decode decode ( .dest_e_addr(hdr_flit_i.dest_e_addr), .dest_o(dest_mcast_all_endp), .row_has_any_dest(), @@ -493,9 +486,7 @@ endmodule * * packet_injector_verilator * ***********************************/ -module packet_injector_verilator #( - parameter NOC_ID=0 -)( +module packet_injector_verilator ( //general current_e_addr, reset, @@ -527,7 +518,7 @@ module packet_injector_verilator #( ); - `NOC_CONF + import pronoc_pkg::*; //general input reset,clk; @@ -586,9 +577,7 @@ module packet_injector_verilator #( assign pck_injct_out_h2t_delay = pck_injct_out.h2t_delay; - packet_injector #( - .NOC_ID(NOC_ID) - ) injector ( + packet_injector injector ( .current_e_addr (current_e_addr ), .reset (reset ), .clk (clk ), diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index dd4887a..b0520a7 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -4,11 +4,8 @@ * pronoc_pkg.sv ****************************************************************************/ -`ifdef PRONOC_PKG - -`ifdef IMPORT_PRONOC_PCK package pronoc_pkg; -`endif + `define NOC_LOCAL_PARAM `include "noc_localparam.v" @@ -352,8 +349,6 @@ package pronoc_pkg; localparam ROUTER_EVENT_w = $bits(router_event_t); -`ifdef IMPORT_PRONOC_PCK -endpackage : pronoc_pkg -`endif - -`endif //PRONOC_PKG + +endpackage : pronoc_pkg + diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index a6b9667..2128e56 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -19,25 +19,6 @@ * lk-ahead routing, The packet can by-pass the next router once the bypassing condition are met ***************************/ - -module reduction_or #( - parameter W = 5,//out width - parameter N = 4 //array lenght -)( - D_in, - Q_out -); - input [W-1 : 0] D_in [N-1 : 0]; - output reg [W-1 : 0] Q_out; - - // assign Q_out = D_in.or(); //it is not synthesizable able by some compiler - always_comb begin - Q_out = {W{1'b0}}; - for (int i = 0; i < N; i++) - Q_out |= D_in[i]; - end -endmodule - module onehot_mux_2D #( parameter W = 5,//out width parameter N = 4 //sel width @@ -118,7 +99,6 @@ endmodule module header_flit_info #( - parameter NOC_ID = 0, parameter DATA_w = 0 )( flit, @@ -126,7 +106,7 @@ module header_flit_info #( data_o ); - `NOC_CONF + import pronoc_pkg::*; localparam Dw = (DATA_w==0)? 1 : DATA_w; @@ -160,29 +140,25 @@ module header_flit_info #( endmodule `ifdef SIMULATION -module smart_chanel_check #( - parameter NOC_ID=0 -) ( +module smart_chanel_check ( flit_chanel, smart_chanel, reset, - clk + clk ); - `NOC_CONF - + import pronoc_pkg::*; + input flit_chanel_t flit_chanel; - input smart_chanel_t smart_chanel; + input smart_chanel_t smart_chanel; input reset,clk; smart_chanel_t smart_chanel_delay; always @(posedge clk) smart_chanel_delay<=smart_chanel; hdr_flit_t hdr_flit; - header_flit_info #( - .NOC_ID (NOC_ID) - ) extract ( + header_flit_info extract ( .flit(flit_chanel.flit), - .hdr_flit(hdr_flit), + .hdr_flit(hdr_flit), .data_o() ); @@ -207,9 +183,8 @@ endmodule module smart_forward_ivc_info #( - parameter NOC_ID=0, parameter P=5 -) ( +) ( ivc_info, iport_info, oport_info, @@ -217,7 +192,7 @@ module smart_forward_ivc_info #( ovc_locally_requested, reset,clk ); - `NOC_CONF + import pronoc_pkg::*; //ivc info input reset,clk; @@ -311,7 +286,6 @@ endmodule module smart_bypass_chanels #( - parameter NOC_ID=0, parameter P=5 ) ( ivc_info, @@ -325,7 +299,7 @@ module smart_bypass_chanels #( clk ); - `NOC_CONF + import pronoc_pkg::*; input reset,clk; input smart_chanel_t smart_chanel_new [P-1 : 0]; input smart_chanel_t smart_chanel_in [P-1 : 0]; @@ -381,7 +355,7 @@ module check_straight_oport #( destport_coded_i, goes_straight_o ); - `NOC_CONF + import pronoc_pkg::*; input [DSTPw-1 : 0] destport_coded_i; output goes_straight_o; @@ -419,7 +393,6 @@ endmodule module smart_validity_check_per_ivc #( - parameter NOC_ID=0, parameter IVC_NUM = 0 ) ( reset, @@ -455,7 +428,7 @@ module smart_validity_check_per_ivc #( smart_ivc_reset_o, smart_ivc_granted_ovc_num_o ); - `NOC_CONF + import pronoc_pkg::*; input reset, clk; //smart channel @@ -532,7 +505,6 @@ endmodule module smart_allocator_per_iport # ( - parameter NOC_ID=0, parameter P=5, parameter SW_LOC=0, parameter SS_PORT_LOC=1 @@ -567,7 +539,7 @@ module smart_allocator_per_iport # ( smart_ivc_single_flit_pck_o, smart_ovc_single_flit_pck_o ); - `NOC_CONF + import pronoc_pkg::*; //general input clk, reset; input [RAw-1 :0] current_r_addr_i; @@ -608,7 +580,6 @@ module smart_allocator_per_iport # ( // does the route computation for the current router conventional_routing #( - .NOC_ID (NOC_ID), .TOPOLOGY (TOPOLOGY), .ROUTE_NAME (ROUTE_NAME), .ROUTE_TYPE (ROUTE_TYPE), @@ -640,7 +611,6 @@ module smart_allocator_per_iport # ( //look ahead routing. take straight next router address as input conventional_routing #( - .NOC_ID(NOC_ID), .TOPOLOGY (TOPOLOGY), .ROUTE_NAME (ROUTE_NAME), .ROUTE_TYPE (ROUTE_TYPE), @@ -672,7 +642,6 @@ module smart_allocator_per_iport # ( generate for (i=0;i0)begin :not_first_x - assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; + assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; end else begin :first_x if(IS_LINE) begin : line_first_x - assign router_chan_in[x][BACKWARD]={PITON_CHANEL_w{1'b0}}; + assign router_chan_in[x][BACKWARD]={PITON_CHANEL_w{1'b0}}; end else begin : ring_first_x - assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; + assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; end - end + end // connect other local ports for (l=0; l0) begin : not_first_y - assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; + assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; end else begin :first_y if(IS_MESH) begin : first_y_mesh - assign router_chan_in[`router_id(x,y)][NORTH] = {PITON_CHANEL_w{1'b0}}; + assign router_chan_in[`router_id(x,y)][NORTH] = {PITON_CHANEL_w{1'b0}}; end else if(IS_TORUS) begin :first_y_torus - assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(NY-1))][SOUTH]; + assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(NY-1))][SOUTH]; end else if(IS_FMESH) begin : first_y_fmesh //connect to endp - localparam NORTH_ID = NX*NY*NL + x; + localparam NORTH_ID = NX*NY*NL + x; assign router_chan_in [`router_id(x,y)][NORTH] = chan_in_all [NORTH_ID]; assign chan_out_all [NORTH_ID] = router_chan_out [`router_id(x,y)][NORTH]; end//topology end//y>0 if(x>0)begin :not_first_x - assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; + assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; end else begin :first_x if(IS_MESH) begin :first_x_mesh - assign router_chan_in[`router_id(x,y)][WEST] = {PITON_CHANEL_w{1'b0}}; + assign router_chan_in[`router_id(x,y)][WEST] = {PITON_CHANEL_w{1'b0}}; end else if(IS_TORUS) begin :first_x_torus - assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; + assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; end else if(IS_FMESH) begin : first_x_fmesh //connect to endp - localparam WEST_ID = NX*NY*NL +2*NX + y; + localparam WEST_ID = NX*NY*NL +2*NX + y; assign router_chan_in [`router_id(x,y)][WEST] = chan_in_all [WEST_ID]; - assign chan_out_all [WEST_ID] = router_chan_out [`router_id(x,y)][WEST]; + assign chan_out_all [WEST_ID] = router_chan_out [`router_id(x,y)][WEST]; end//topology - end + end if(y < NY-1) begin : firsty - assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; + assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; end else begin : lasty if(IS_MESH) begin :ly_mesh - assign router_chan_in[`router_id(x,y)][SOUTH]= {PITON_CHANEL_w{1'b0}}; + assign router_chan_in[`router_id(x,y)][SOUTH]= {PITON_CHANEL_w{1'b0}}; end else if(IS_TORUS) begin :ly_torus - assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; + assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; end else if(IS_FMESH) begin : ly_fmesh //connect to endp - localparam SOUTH_ID = NX*NY*NL + NX + x; + localparam SOUTH_ID = NX*NY*NL + NX + x; assign router_chan_in [`router_id(x,y)][SOUTH] = chan_in_all [SOUTH_ID]; assign chan_out_all [SOUTH_ID] = router_chan_out [`router_id(x,y)][SOUTH]; end//topology - end + end // endpoint(s) connection // connect other local ports for (l=0; l= DATA_w + CTRL_BITS_w )head_gen( - .flit_out(header_flit), + .flit_out(header_flit), .src_e_addr_in(src_e_addr), .dest_e_addr_in(dest_e_addr), .destport_in(destport), @@ -467,7 +455,6 @@ endmodule * pronoc_to_piton_wrapper * ***************************/ module pronoc_to_piton_wrapper #( - parameter NOC_ID=0, parameter PORT_NUM=0, parameter TILE_NUM =0, parameter FLATID_WIDTH=8 @@ -478,7 +465,7 @@ module pronoc_to_piton_wrapper #( current_r_addr_o, chan_in ); - `NOC_CONF + import pronoc_pkg::*; localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH ), HEAD_DATw = (64-MSB_BE-1), @@ -508,12 +495,11 @@ module pronoc_to_piton_wrapper #( wire [DATA_w-1 : 0] head_dat; //extract ProNoC header flit data header_flit_info #( - .NOC_ID(NOC_ID), .DATA_w(DATA_w) )extract( .flit(chan_in.flit_chanel.flit), - .hdr_flit(hdr_flit), - .data_o(head_dat) + .hdr_flit(hdr_flit), + .data_o(head_dat) ); wire [Fpay-1:0] header_flit; @@ -528,20 +514,18 @@ module pronoc_to_piton_wrapper #( wire [ADDR_CODED-1 : 0] dest_coded; assign {dest_coded, length, msg_type, mshrid, option1} = head_dat [HEAD_DATw-1 : 0]; - pronoc_to_piton_endp_addr_converter#( - .NOC_ID(NOC_ID) - )addr_conv ( - .piton_end_addr_coded_i(dest_coded), + pronoc_to_piton_endp_addr_converter addr_conv ( + .piton_end_addr_coded_i(dest_coded), .piton_chipid_o (dest_chipid), .piton_coreid_x_o(dest_x), - .piton_coreid_y_o(dest_y) + .piton_coreid_y_o(dest_y) ); wire [MAX_P-1:0] destport_one_hot; // FBITS coding localparam [3: 0] FBITS_WEST = 4'b0010, - FBITS_SOUTH = 4'b0011, - FBITS_EAST = 4'b0100, + FBITS_SOUTH = 4'b0011, + FBITS_EAST = 4'b0100, FBITS_NORTH = 4'b0101, FBITS_PROCESSOR = 4'b0000; /* @@ -654,15 +638,13 @@ endmodule /********************* * pack noc_top ports * ******************/ -module noc_top_packed #( - parameter NOC_ID=0 -)( +module noc_top_packed ( reset, - clk, + clk, chan_in_all, - chan_out_all + chan_out_all ); - `NOC_CONF + import pronoc_pkg::*; localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH ), HEAD_DATw = (64-MSB_BE-1), @@ -670,7 +652,7 @@ module noc_top_packed #( input clk,reset; //local ports input smartflit_chanel_t [NE-1 : 0] chan_in_all ; - output smartflit_chanel_t [NE-1 : 0] chan_out_all ; + output smartflit_chanel_t [NE-1 : 0] chan_out_all ; smartflit_chanel_t chan_in_all_unpacked [NE-1 : 0]; smartflit_chanel_t chan_out_all_unpacked [NE-1 : 0]; @@ -682,36 +664,33 @@ module noc_top_packed #( end//for endgenerate - noc_top #( - .NOC_ID(NOC_ID) - )unpacked ( + noc_top unpacked ( .reset(reset), - .clk(clk), + .clk(clk), .chan_in_all(chan_in_all_unpacked), - .chan_out_all(chan_out_all_unpacked) + .chan_out_all(chan_out_all_unpacked) ); //synthesis translate_off initial begin - display_noc_parameters(); - end + display_noc_parameters(); + end //synthesis translate_on -endmodule +endmodule -module ground_pronoc_end_port +module ground_pronoc_end_port #( - parameter TILE_NUM=0, - parameter NOC_ID=0 + parameter TILE_NUM=0 )( clk, reset, chan_in, - chan_out + chan_out ); - `NOC_CONF + import pronoc_pkg::*; input reset,clk; input smartflit_chanel_t chan_in; output smartflit_chanel_t chan_out; @@ -729,9 +708,8 @@ endmodule -module pronoc_noc +module pronoc_noc #( - parameter NOC_ID=0, parameter CHIP_SET_PORT=3, parameter FLATID_WIDTH=8 )( @@ -749,7 +727,7 @@ module pronoc_noc clk ); - `NOC_CONF + import pronoc_pkg::*; input clk,reset; input [Fpay*NE-1:0] dataIn_flatten; input [NE-1 : 0] validIn; @@ -782,15 +760,14 @@ module pronoc_noc assign flat_tileid[i]=flat_tileid_flatten[(i+1)*FLATID_WIDTH-1 : i*FLATID_WIDTH]; pronoc_to_piton_wrapper #( - .NOC_ID(NOC_ID), .PORT_NUM(0), .TILE_NUM(i), .FLATID_WIDTH(FLATID_WIDTH) - )pr2pi ( + ) pr2pi ( .default_chipid(default_chipid), .default_coreid_x(default_coreid_x[i]), .default_coreid_y(default_coreid_y[i]), - .flat_tileid(flat_tileid[i]), + .flat_tileid(flat_tileid[i]), .reset(reset), .clk(clk), .dataOut(dataOut[i]), @@ -798,19 +775,18 @@ module pronoc_noc .yummyOut(yummyOut[i]), .current_r_addr_o(current_r_addr[i]), .chan_in(pronoc_chan_out[i]) - ); + ); - piton_to_pronoc_wrapper + piton_to_pronoc_wrapper #( - .NOC_ID(NOC_ID), .TILE_NUM(i), .CHIP_SET_PORT(CHIP_SET_PORT), .FLATID_WIDTH(FLATID_WIDTH) - )pi2pr ( + ) pi2pr ( .default_chipid (default_chipid), .default_coreid_x(default_coreid_x[i]), .default_coreid_y(default_coreid_y[i]), - .flat_tileid(flat_tileid[i]), + .flat_tileid(flat_tileid[i]), .reset(reset), .clk(clk), .dataIn(dataIn[i]), @@ -818,17 +794,15 @@ module pronoc_noc .yummyIn(yummyIn[i]), .current_r_addr_i(current_r_addr[i]), .chan_out(pronoc_chan_in[i]) - ); + ); end//for endgenerate - noc_top #( - .NOC_ID(NOC_ID) - )noc ( + noc_top noc ( .reset(reset), - .clk(clk), + .clk(clk), .chan_in_all (pronoc_chan_in ), .chan_out_all(pronoc_chan_out), - .router_event() + .router_event( ) ); endmodule diff --git a/mpsoc/rtl/src_peripheral/ni/ni_master.sv b/mpsoc/rtl/src_peripheral/ni/ni_master.sv index 3f862d2..2e16163 100644 --- a/mpsoc/rtl/src_peripheral/ni/ni_master.sv +++ b/mpsoc/rtl/src_peripheral/ni/ni_master.sv @@ -34,8 +34,7 @@ module ni_master - #( - parameter NOC_ID=0, + #( parameter MAX_TRANSACTION_WIDTH=10, // Maximum transaction size will be 2 power of MAX_DMA_TRANSACTION_WIDTH words parameter MAX_BURST_SIZE =256, // in words parameter CRC_EN= "NO",// "YES","NO" if CRC is enable then the CRC32 of all packet data is calculated and sent via tail flit. @@ -44,11 +43,11 @@ module ni_master // by the NI before saving the packet in a memory buffer. This can give some hints to the software regarding the incoming // packet such as its type, or source port so the software can store the packet in its appropriate buffer. //wishbone port parameters - parameter Dw = 32, - parameter S_Aw = 7, - parameter M_Aw = 32, - parameter TAGw = 3, - parameter SELw = 4 + parameter Dw = 32, + parameter S_Aw = 7, + parameter M_Aw = 32, + parameter TAGw = 3, + parameter SELw = 4 ) ( //general @@ -91,8 +90,8 @@ module ni_master irq ); -`NOC_CONF - input reset,clk; +import pronoc_pkg::*; + input reset,clk; // NOC interfaces input [RAw-1 : 0] current_r_addr; input [EAw-1 : 0] current_e_addr; @@ -387,11 +386,10 @@ Shared registers for all VCs wire [V-1 : 0 ] precap_valid; //capture data before saving the actual flit in memory - if(HDATA_PRECAPw > 0 ) begin : precap + if(HDATA_PRECAPw > 0 ) begin : precap wire [EAw-1 : 0] src_endp_addr; extract_header_flit_info #( - .NOC_ID(NOC_ID), - .DATA_w(HDATA_PRECAPw) + .DATA_w(HDATA_PRECAPw) ) data_extractor ( .flit_in(flit_in), .flit_in_wr(flit_in_wr), @@ -713,7 +711,6 @@ Shared registers for all VCs endgenerate conventional_routing #( - .NOC_ID(NOC_ID), .TOPOLOGY(TOPOLOGY), .ROUTE_NAME(ROUTE_NAME), .ROUTE_TYPE(ROUTE_TYPE), @@ -735,8 +732,7 @@ Shared registers for all VCs ); header_flit_generator #( - .NOC_ID(NOC_ID), - .DATA_w(HDw) + .DATA_w(HDw) ) hdr_flit_gen ( .flit_out(hdr_flit_out), .class_in(pck_class), @@ -749,7 +745,7 @@ Shared registers for all VCs .data_in(hdr_data) ); - wire [V-1 : 0] wr_vc_send = (fifo_wr) ? send_vc_enable : {V{1'b0}}; + wire [V-1 : 0] wr_vc_send = (fifo_wr) ? send_vc_enable : {V{1'b0}}; ovc_status #( .V(V), @@ -802,10 +798,10 @@ Shared registers for all VCs .V(V), .B(LB) ) the_ififo ( - .din(flit_in), // Data in - .vc_num_wr(flit_in_vc_num),//write virtual chanel + .din(flit_in), // Data in + .vc_num_wr(flit_in_vc_num),//write virtual chanel .wr_en(flit_in_wr), // Write enable - .vc_num_rd(receive_vc_enable),//read virtual chanel + .vc_num_rd(receive_vc_enable),//read virtual chanel .rd_en(fifo_rd), // Read the next word .dout(fifo_dout), // Data out .vc_not_empty(ififo_vc_not_empty), @@ -817,8 +813,7 @@ Shared registers for all VCs ); extract_header_flit_info #( - .NOC_ID(NOC_ID), - .DATA_w (HDw) + .DATA_w (HDw) ) extractor ( .flit_in(fifo_dout), .flit_in_wr(), @@ -839,9 +834,9 @@ Shared registers for all VCs assign received_flit_is_hdr = fifo_dout[Fw-1]; // assign any_vc_got_pck = |receive_vc_got_packet; localparam [1:0] - HDR_FLAG = 2'b10, - BDY_FLAG = 2'b00, - TAIL_FLAG = 2'b01; + HDR_FLAG = 2'b10, + BDY_FLAG = 2'b00, + TAIL_FLAG = 2'b01; assign credit_out = vc_fifo_rd; assign flit_out_wr= fifo_wr; assign flit_out [Fpay+V-1 : Fpay] = send_vc_enable; diff --git a/mpsoc/rtl/src_synfull/dpi_int_pkg.sv b/mpsoc/rtl/src_synfull/dpi_int_pkg.sv index 2a1b8b6..2b01bb0 100644 --- a/mpsoc/rtl/src_synfull/dpi_int_pkg.sv +++ b/mpsoc/rtl/src_synfull/dpi_int_pkg.sv @@ -2,21 +2,19 @@ package dpi_int_pkg; -parameter NOC_ID=0; - -`NOC_CONF +import pronoc_pkg::*; typedef struct packed { - logic [NEw-1 : 0] dest ; - logic [PCK_SIZw-1 : 0] size ; - logic [NEw-1 : 0] src ; - logic [31:0] id ; - logic valid ; -} req_t; + logic [NEw-1 : 0] dest; + logic [PCK_SIZw-1 : 0] size; + logic [NEw-1 : 0] src; + logic [31:0] id; + logic valid; +} req_t; typedef struct packed { - logic [31:0] id ; - logic valid ; -} deliver_t; + logic [31:0] id; + logic valid; +} deliver_t; endpackage diff --git a/mpsoc/rtl/src_synfull/dpi_interface.sv b/mpsoc/rtl/src_synfull/dpi_interface.sv index b47582e..10487bb 100644 --- a/mpsoc/rtl/src_synfull/dpi_interface.sv +++ b/mpsoc/rtl/src_synfull/dpi_interface.sv @@ -1,6 +1,6 @@ `include "pronoc_def.v" parameter NOC_ID=0; -`NOC_CONF +import pronoc_pkg::*; import dpi_int_pkg::*; module top_dpi_interface ( input logic clk_i, rst_i , diff --git a/mpsoc/rtl/src_synfull/synfull_top.sv b/mpsoc/rtl/src_synfull/synfull_top.sv index 1905e12..fa6f2ec 100755 --- a/mpsoc/rtl/src_synfull/synfull_top.sv +++ b/mpsoc/rtl/src_synfull/synfull_top.sv @@ -2,8 +2,7 @@ `ifdef SIMULATION module synfull_top; - parameter NOC_ID=0; - `NOC_CONF + import pronoc_pkg::*; import dpi_int_pkg::*; reg reset ,clk; @@ -31,11 +30,9 @@ module synfull_top; req_t [NE-1 : 0] synfull_pronoc_req_all ; deliver_t [NE-1 : 0] pronoc_synfull_del_all ; - noc_top #( - .NOC_ID(NOC_ID) - ) the_noc ( + noc_top the_noc ( .reset(reset), - .clk(clk), + .clk(clk), .chan_in_all(chan_in_all), .chan_out_all(chan_out_all), .router_event(router_event) @@ -117,21 +114,19 @@ module synfull_top; assign pck_injct_in[i].vc = _pck_injct_in[i].vc; endp_addr_encoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) encode1 ( .id(i[NEw-1 :0]), .code(current_e_addr[i])); - packet_injector #( - .NOC_ID(NOC_ID) - ) pck_inj ( + packet_injector pck_inj ( //general .current_e_addr(current_e_addr[i]), .reset(reset), - .clk(clk), + .clk(clk), //noc port .chan_in(chan_out_all[i]), - .chan_out(chan_in_all[i]), + .chan_out(chan_in_all[i]), //control interafce .pck_injct_in(pck_injct_in[i]), - .pck_injct_out(pck_injct_out[i]) - ); - endp_addr_encoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) encode2 ( .id(dest_id[i]), .code(pck_injct_in[i].endp_addr)); + .pck_injct_out(pck_injct_out[i]) + ); + endp_addr_encoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) encode2 ( .id(dest_id[i]), .code(pck_injct_in[i].endp_addr)); reg [31:0]k; initial begin @@ -196,24 +191,22 @@ module synfull_top; for(k=0; k< NE; k=k+1) begin : endpoints if(pck_injct_out[k].pck_wr) begin total_rsv_pck_count++; - total_rsv_flit_count+=pck_injct_out[k].size; + total_rsv_flit_count+=pck_injct_out[k].size; end if(pck_injct_in[k].pck_wr) begin total_sent_pck_count++; - total_sent_flit_count+=pck_injct_in[k].size; + total_sent_flit_count+=pck_injct_in[k].size; end if(synfull_pronoc_req_all[k].valid) begin total_queued_pck_count++; - end - end + end + end end end - routers_statistic_collector # ( - .NOC_ID(NOC_ID) - ) router_stat ( + routers_statistic_collector router_stat ( .reset(reset), - .clk(clk), + .clk(clk), .router_event(router_event), .print(print_router_st) ); diff --git a/mpsoc/rtl/src_topology/common/custom_ni_routing.v b/mpsoc/rtl/src_topology/common/custom_ni_routing.v index dfd8e4b..069c2ce 100644 --- a/mpsoc/rtl/src_topology/common/custom_ni_routing.v +++ b/mpsoc/rtl/src_topology/common/custom_ni_routing.v @@ -1,6 +1,5 @@ `timescale 1ns / 1ps module custom_ni_routing #( - parameter NOC_ID = 0, parameter TOPOLOGY = "CUSTOM_NAME", parameter ROUTE_NAME = "CUSTOM_NAME", parameter ROUTE_TYPE = "DETERMINISTIC", diff --git a/mpsoc/rtl/src_topology/common/custom_noc_top.sv b/mpsoc/rtl/src_topology/common/custom_noc_top.sv index aed0cfc..bd314dd 100644 --- a/mpsoc/rtl/src_topology/common/custom_noc_top.sv +++ b/mpsoc/rtl/src_topology/common/custom_noc_top.sv @@ -1,16 +1,14 @@ `include "pronoc_def.v" module custom_noc_top - #( - parameter NOC_ID=0 - )( + ( reset, - clk, + clk, chan_in_all, chan_out_all, - router_event + router_event ); - `NOC_CONF + import pronoc_pkg::*; input clk,reset; //local ports @@ -23,11 +21,9 @@ module custom_noc_top //do not modify this line ===custom1=== if(TOPOLOGY == "custom1" ) begin : Tcustom1 - custom1_noc_genvar #( - .NOC_ID(NOC_ID) - ) the_noc ( + custom1_noc_genvar the_noc ( .reset(reset), - .clk(clk), + .clk(clk), .chan_in_all(chan_in_all), .chan_out_all(chan_out_all), .router_event(router_event) @@ -35,4 +31,4 @@ module custom_noc_top end endgenerate -endmodule +endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v index 46e6a3e..50b377c 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v ** ** Copyright (C) 2014-2022 Alireza Monemi ** diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v index 1ad3a54..b3c1254 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v ** ** Copyright (C) 2014-2022 Alireza Monemi ** diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v index c933352..1a9fd35 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v ** ** Copyright (C) 2014-2022 Alireza Monemi ** diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v index 94ecf6a..13aa2b1 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v ** ** Copyright (C) 2014-2022 Alireza Monemi ** diff --git a/mpsoc/rtl/src_topology/custom1/custom1.png b/mpsoc/rtl/src_topology/custom1/custom1.png index 4cdeaf08ef2b15af35f7a8d9c1dfc5fb3bee2ada..584d953c128037c26f6cbc962ad5bf1c94fcf6ec 100644 GIT binary patch literal 137543 zcmYJbbwF0x_dQIDq=3>564IcwAR!^CNOvRM9U>)yAU+}uq6jERcZYPB2uKM?hjjDq z$N7AJ@BM>u9PYj6?z3aJHCNPvPT54GGp+fGNxebk=~MW z`C_2&koQB+k8VtH_eH zd47paPx|gQLRordK+=1zH%TCaC^7ZuB(Pz&u!|Q@_P+}Q#VsHA2GPHZLiQcv;eUTU zWBu9#l@XnLSjLNn#&1W{OpU>Xv%tV!(d3nfB_r}8_UrEAwy(I3GBxZ`N+^q=X;^oS;F zFHFf)Eq4z7UFA(`Zi;)f>;0sk$$>IGvP#}2R5v`#nUyB~Zeg=NDptB;mP)JP%L&@` zZlp!9UbvQ|V&b(J9v`}{(2dr|G{zLjgkG4SI0A*9_a*GPJbRGEb_^U_xgaa}pFH!*F|Smn_FZToz8YkIWe`h3@$Th|9i9xO}g z{V2KenG_`1MJ105k{q_cDiT&qQtr33=>4wwz<`ux>cKcCykL0X9l{cO?U&Mm*xkZR z52hI$v~SKIdrmLS`OW!BjFoqVpRgcA@dso#(t|l3WW`3`xYX18F;exSg6nSK?NOIw zx*^3NwnSKp@USASeD~AgepUz3n7gleqh7x3)Rhs@4aY!dlFm(Q_nJ7mOCz=_{@?>X z6Gp&#{#MjXfqfp8yy)MytPHiSj=%5nZfjx{V+RW+kE_?d3%}()K4R$i_3!a4^;S_4 zaYCd($Ubh@nQ*$|&)?0z=sv^qU*eI2dA>*A2qqOJ94rZ*{5;wqmrFH5VK{OmgrGoN zN5qE`yB0G0ac>a`yA=tW8zy0gPOg5<^bk1c`4WJC#em1FT5*2%j8C7hrAq#d2j9e= zf_Ov~^#<*<05SMkCiofF=LZ5@RL_iL_VntuhpGu%$p`z_1V+SK?4NVd4q%8Q6qEcd zGEL<3qY(3~ql#1D$U_xjKVG|Uu>3;55K+wZ%JeQJ@j_*<54y@h@GAygK`2?+JXU?* z+}iYVZo0jB`I(N?vP2Elb+49Zv9u9PZvm#rZqL?H`O%=VK5&E|?LQ!A^86yo>?W9~!ropN=6m+AXiyY+7h@ zrQLrQOMmZjhp*N)Nv}7^D75YSTNP@1h8tO8FDIf4Q{Hlts##}oXN9h-XvaKUc4tcZ`?$_Xed%g3E(Oj zy0OqX^>v(qfGk10(_VdI1y{bz=L7u~PyfuztuvG1_Ae1S71?v#`xeUh^W(iO zJ8}~f{vjXdH|^vU{EYi|hss{9wcRcJloPil7fp}XaC<9e>}R>Cae zB#=)Ztj>7vG0K%Q&xOWiA{yeyeU_4&-$5tbW%^h36+fH8MN^0$)x^}x*6v(ReiF5# zv|uJh32J%+H8u2aR1*77G$qX|2^v z3eo64r#geJNLA;5h-^1Hd(lXGM=p=6C-($syDnul1m-h+nl*hvL+za&!t;hVdGWeM zKZ~2-b@S76ELa1hwX}$?nWMV0ithG!QPrA0LZqn(7 zzfIPjIKUMpe30?JYJI85Rh3(4z`}NDUVd$A;&JPS+wnf;qA$wKbepl3d1d|8*Ga*K zJ;ri}thS7~)W;^Wyo_bqgGN$QRu4pU!S-ekA>bo))V{jwbSW|LV9s?b`ft;n?|SHo zR16 z`_4K!B4qkeZHAXuu_=$+qv}oKZrqOsPncU8ST0XGI!4@H-KSNPmX?0<@CZ|U3zc?JlaUOfCJ~ZasV=>&xtNQmqX<8hTM)^-dBqTf z@nhYMXCG?9VjT6v_)@B>qEoD&BrAQ)Gv*#^#kyBszFxU;c;cUymKNAJ>sV=RX}JW~ zpFe*V7Z>3V%ge0H%!z$#$8U_Xg9l!}rl~85WYy-)dFOO-u%qB=NHt}L9e&&=>9cvi z|H~SVMZQY%n2`YqwGCQkM@4>ihlRAPv#we_dXBmbwOH6c%dwcovr>gOV#bz&t@vFt&9>movpGW@Z+ zIG@Yb`gv5+h>4d%DZR-237SX*0Gvfr+B464Ny?tJ_irOFOg0XV+S9eX;Qs#pfU`q~$+Blt6%LKZ zZ9J5el*Giua<3`xS$4ns`0?ZU`FVbRepOYKO&|t^$ps13Y(_>94nIkka&#a**pxBk zjcZBgn`O`1o^IsD7^fgF-*I_ymiP7R9S)9JpXIc+C^C7*IM}e^;o&bDIq%=UXJJm& zyYsf$@)*B>pivD8u0kSQOTH&Z&U-!lWt=f?FUWfPwn`%M!>?zm=YIP1slGk{oGnkg zaLZvpRaI4DyKc{_KUKuC`)1C_sSdBm!*iq~y@Q9Pa=$za8?!y|7N?E1 z{{E7v)OsLBmJuHxpGwf)dpXT3@US$ayrSaI^0HcnM16j~eQzS)>gp;%1k;b(NWkm=}_;GvWT@cQc@ zx^B`TuM7mjZRjDHPyNin`Z$k%#ReH{Puca@SXMBu1_%XT}_!i&+b^L2AlFU9RJ?fuutf@way>GfY0_1sZzgYjp|g~ zm@K!OfJjK-ak8^Z0asW`FqUxn{k`n&^d$KMvB2;B@~fiWRUTLQ3Bt*IS8Z%?7i2Me zHn_QqB7ErQ&nnob${FAF&B|HN+G%YAmo`mp!}#>{0-D5Y(wljs^>QB^=4K~&@q)Z| zs3d*=E+nLjdH82?^h=;@M+&5DR9p0JT^#|qB@#hhvLF)C3^(21-=`M$-uVWPJ^$O$ zXSElvZ6p$OdH(p5oJd-~j<%Op6vj&ovwI>U#E~~|#s{t*>N{1RWcT()2YV|aC`!>w z9q4D2z&#d)!MR*nYHDhX0#BC6jQxu%Dm)X|$Yi@|Nk3wUq_)Zggae577y#vEW1&~}dG#p+Sx)y3iA;XuHa+w8@b zm)G_T4NjPuVVbPGi;GJ@K>h4?tOvtCN0vHcjZ$#0n%;utL_^%Py}G3){`Wgq{9xS@!zNGANl%r_!mFsLh2Ou;{xjOuliBi@vbs*JhbltT z`;b~84PDM&UCg!;O4dCaVJSByH1zTDfh9u;prN5DENS+mc?b!AVLTwQlhmNOvG zO8rlEmwFPW>?`7!wOD4o0=siA?bKcm5`oJyY32i%AO{)BOYeaRZnk0 zT%T`POQziSJ1h)5$gAC|$@}<`kvQ^u4Y!EH#KeSyg9Fs_Vs7MJS+ne5qbvR-W!MYj z)8T}M%Y#BM508uSpo{U352IS~Bu+UHuT^9UFy;h}TwjQ<9^Ugncqd!?=V};B+3lm3@hnrST3Gnmt3kb-^Q0p2X zuhjSNNg;V9BzQqKexHyac{~>)=CyS`Io=@Xx~LGX>b^499HOG4@*g6yEe9yzE1url+Y2sYVPTP#ljA2&o6xi5S-Y^X zKts^+mo-|J5ex;s1sF!i9KLaTs?zD=^uVZa+^W>l(lY+tJLN>)%&e@%A$hv`?S`|h z`lFe%ty(82Mw7NSJ3YO<8*6L3C;o8?vaeBK16(}?XlMwC<4TRJt(T!52s-|%dNz`c zevP24yu7WW!`jLUstnn!Tb9<=u$b5mL@M&4jt~2S-@0?+|N8Z703Uvb8xu7i>p#Bf z*Bfm^)^3lbyXxjBMDdypID$Y0Xf->ldOGl@FU6^P={*u3;2IylnA(i-5J3jl1@zyG z`M2<}#Kgqvjhr+!$KW@GU?mWb3e0a45`>-&XO)zcKn>2yVvcBq{rIM37eq)b#~5eA z`*Uc>WoND#B6+*#J=glymZPn0cURX*w|0Z;gk=JI0KOG0aooVI?{XQ%Y5!P;3EI+ng+iZvY(d=Z{rFkEXi1x}KhIzsNF#yCC3>ANSC_>t{YI zB{b|0D>*fsAj`nXpA^ZxqygA0WIzIV1pi*0kVvq%2l_w6Ab_7g)^(A3nt zI$xI5{-#&%G}{0f89vEp?++lBJCc%;_wF5pB3_xZv9qt%tQVvRSoe3wa|G=oGS1hu z8%rkay?(jKLj;kO>V2b)&8e-`SMrHO(l2TNlCbxXz}D+%YZ~B1|EpUZ$tfvOuU<(U z7RTNP=Y00;nPcUYRVn`N?F4Y;0w{{d$Hy7xi>$C~V(u&IMn*>YQEy3Ba4Qn!yG7@Oh1nnFf|^&07LcsqT3=g(3}B}IDmD50_wO^` zD$EU$OIEmgqWXS5w>G6MO1IqhgPZHSM0&D7+`n@xD@7Z#bnCBFGrB_C(44z&GqalW zCs7l~dwF@mGV_%Xgz@0l*cf-yk%`IrK2T2Cz7d`goFsTB9+@gEcncT$x408}%!=LJ z-M^Qyov=}=Avpw7Gj*OFCdO8IfB(9X)u&igy?{YqG=I2^hNxf6&w)G_BK_#mtB!^1 z7-(^s;)6k+N~)>^5v|}3?SrYsNO14^YSfF1pE)!W^RP+6ChSHP15G#mHLUUWPHPq} zE-ogfPkDKHnVAg#9Jlj2GYiY4eMJHC;;x*c`CrbCf}9;5s6w4(H>l`W|5JR1QDNvSUYNvAUiG)m;iV?1DOP_aY&dmrax^U z8tO539qIb+M|ya_fI#V|Pv%$Z2918+3XdMSil#|q3@q=p{omaUc5w{z;=}`8JQRx(=;}wTi09s{-0f2Ly@a27#qZPGkucJ5s6kiJyRRzYHn_x zZx=^WI<*NX{|5H{eky*Y6|$yCL?eIyBd>j^Q)}3cPa^rc@5d(F^2yCZKn9R6b;cR# zy62rSLZkrYK%uRL5`@Qv<=#wZN?~yQ3N@*io86X^R7sfH(atW)gJCxlk`Xg8Y{ma- z7Tv!a?(GQt#4`?Cy+H=g?=mY+RL%xiphL$0)WgfGvZA7*tZbjVd<+WSSss*%ls>_f zKF3P^Z(2DcNpIe~N&a`Gr#lwws9tbU6GWJjL(%!ypR1Bm-0?5My2SP=BDa^Py`rp| zvmz&I{r&Ny7keReFh721#deUayJDq5_01R9cYZO>?XiV_<0B^rQ+Wij;lPY{E;97bXoI_41yFhsVMGerW6byLay(w?O*? zNwcM;1=^RgvNA}Wc?TGh^r@;juE>@(^#JJp@K6?SqDvG*bqq=2KVRaVrFz$1-Km}4 za;^6D^|iINeTP78Jmcr$B!SU{tXJuW`Ze(+}fU=o~EYrS&9g8 zTD3=y9>GnnuC72M7#RGzuCeua-nj}eSbcqc@xLoO`wtX74y}BhGMmT3)T$~f;9zOu zKCZgDx^i;u#XMy?oZ+US(wTvmD_}v!;(xwr|AN)@HcCpYpXcs_gb_*DLny*(YHAQe za9@5;Bt_$FqxC>KvIZH}dM@{;)qh$C6ar}*P^m6-T|jR9KYpXnO6-Ip*1TBfzf=M+ z->QOtA0`)JyWj7x9PT@;?>2Ow>EX$czd8L~rK>b3z6SQ!6LK~$PK&VNa952KsBqRi_X=Ee|IwYF{4uP!= z^0EJ9lGDlh?;e#O(LPa#bSQ^x?dKG|E2rM+JR z`wxNKSo&8U7>*jKVb*=g<(56~$&9?`fiw7<`}h;MF()Z9k3i#axz})ONVG6l89C%AxijlbU5G7I7ARo3*T7R`}n1{wieLY z*RQq*Yh&OhHja+8BCd;oBkFd_YdApJ6;`k zNTvfaTOUTIj*n0lWwD}W?gui(bxsU<(L~BZO@z{W09bKrvYg`v_DxdKKzK;%-Dkrq zL!W2}bN4s4WF=?S3b*|KLN(1J;%Y8wE19akC;k%LDHG=^g(RrpZtEoX2; zb0#XG;fbzdnuhSdkFO?<(D4>_oMI%rv7AsbLYmXWDkZMY)!baOV=3J9rKA*neQSD_ zzJBG`)Vw%rW)*Lhf9Kv}E>S~x+Dot!u&#*c>}s}RBFAI7eVa?C2(s^H7i&h{LX23$ z!8fPABmw#RKaq(=@UbdsTyu+A@lSg}K%3YY1hnG9!11W0^j1!{H+h*Jg||w`OJ3^@ z7SXTVowR$*#;*1FF7f<$;~$cYrUeFayySm05`d3*fUk!?&An!PmXR$HY|}k1u0DIg zj%-!L`xx_f$R0rqD2uCW)6Q?=qC`=L`+q(2a~@}{a<%gKeeBd)PF z&N>zA02Oz+=@Q$qH@zL`1-#6F#MuUkn)qXFZ8F5J#R{La`}jg3=ECANXkhVfsxXs) z-FfkvR^796a>hqT$=h$#J35Br7g1Ko2z-|!HNYm5A;p{b$OJm^Jg~86$+g;`Lo(&< zTi1d6N9Tu?jRAk#$fl;I8qb$_fGNWFkK>n>U3r!{uVQPQ>4D3F%Z})*f3Y8H>aohw z0DMp?P*m(V4``mgp!;*M+?aNwjv#J9PFvX|Otv%Z1);3HH8&roKasO+9_(#nz zGO6OHCMRoZYez;#px03Ieh%PvIo%I>o(#XOYDoBn{!1KC{?HAw@QmaV9|+KBmN{hp zv80@3SZRA{B8!r&t#P7n-(@jy+mBZ9a}{oJj!DV)8b=}`iWo>$s$Z!*TT+T>jlx)L z!Y`@Va9as-!zF{M{z&tY&qdh DP0>y;pWBsQn(jsBZ~j&m*o-z415l-5G7wuOEp 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

p*2B9Oa_e2N82`Gnz@el9MT#%POscdYIBi;6Dw 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 vMnP0E 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 T`NLQLG5~?6tDnm{r-UW|NmVo* diff --git a/mpsoc/rtl/src_topology/custom1/custom1_noc.sv b/mpsoc/rtl/src_topology/custom1/custom1_noc.sv index 7eab79a..c61287f 100644 --- a/mpsoc/rtl/src_topology/custom1/custom1_noc.sv +++ b/mpsoc/rtl/src_topology/custom1/custom1_noc.sv @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/custom1_noc.sv +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/custom1_noc.sv ** ** Copyright (C) 2014-2022 Alireza Monemi ** @@ -29,9 +29,7 @@ `include "pronoc_def.v" module custom1_noc -#( - parameter NOC_ID=0 -)( +( reset, clk, //T0, @@ -99,9 +97,9 @@ module custom1_noc T15_chan_out, T15_router_event ); - `NOC_CONF + import pronoc_pkg::*; - input reset,clk; + input reset,clk; /******************* @@ -367,7 +365,6 @@ module custom1_noc *******************/ router_config_t R0_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(0), .P(3) ) R0 ( @@ -397,7 +394,6 @@ module custom1_noc *******************/ router_config_t R1_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(1), .P(3) ) R1 ( @@ -427,7 +423,6 @@ module custom1_noc *******************/ router_config_t R2_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(2), .P(3) ) R2 ( @@ -457,7 +452,6 @@ module custom1_noc *******************/ router_config_t R3_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(3), .P(3) ) R3 ( @@ -487,7 +481,6 @@ module custom1_noc *******************/ router_config_t R4_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(4), .P(4) ) R4 ( @@ -519,7 +512,6 @@ module custom1_noc *******************/ router_config_t R5_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(5), .P(4) ) R5 ( @@ -551,7 +543,6 @@ module custom1_noc *******************/ router_config_t R6_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(6), .P(4) ) R6 ( @@ -583,7 +574,6 @@ module custom1_noc *******************/ router_config_t R7_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(7), .P(4) ) R7 ( @@ -615,7 +605,6 @@ module custom1_noc *******************/ router_config_t R12_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(8), .P(4) ) R12 ( @@ -647,7 +636,6 @@ module custom1_noc *******************/ router_config_t R13_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(9), .P(4) ) R13 ( @@ -679,7 +667,6 @@ module custom1_noc *******************/ router_config_t R14_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(10), .P(4) ) R14 ( @@ -711,7 +698,6 @@ module custom1_noc *******************/ router_config_t R15_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(11), .P(4) ) R15 ( @@ -743,7 +729,6 @@ module custom1_noc *******************/ router_config_t R8_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(12), .P(5) ) R8 ( @@ -777,7 +762,6 @@ module custom1_noc *******************/ router_config_t R9_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(13), .P(5) ) R9 ( @@ -811,7 +795,6 @@ module custom1_noc *******************/ router_config_t R10_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(14), .P(5) ) R10 ( @@ -845,7 +828,6 @@ module custom1_noc *******************/ router_config_t R11_router_config_in; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(15), .P(5) ) R11 ( diff --git a/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv b/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv index fda7a65..d128c5b 100644 --- a/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv +++ b/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/custom1_noc_genvar.sv ** ** Copyright (C) 2014-2022 Alireza Monemi ** @@ -29,16 +29,14 @@ `include "pronoc_def.v" module custom1_noc_genvar -#( - parameter NOC_ID=0 -)( +( reset, - clk, + clk, chan_in_all, chan_out_all, - router_event + router_event ); -`NOC_CONF +import pronoc_pkg::*; input reset; input clk; @@ -63,16 +61,15 @@ module custom1_noc_genvar assign router_config [RID].router_id = RID[RAw-1: 0]; assign router_config [RID].router_addr = RID[RAw-1: 0]; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P(3) ) router_3_port ( .clk(clk), .reset(reset), .router_config_in(router_config[RID]), - .chan_in (router_chan_in [RID] [2 : 0]), + .chan_in (router_chan_in [RID] [2 : 0]), .chan_out (router_chan_out[RID] [2 : 0]), - .router_event(router_event[RID] [2 : 0]) + .router_event(router_event[RID] [2 : 0]) ); end @@ -81,16 +78,15 @@ module custom1_noc_genvar assign router_config [RID].router_id = RID[RAw-1: 0]; assign router_config [RID].router_addr = RID[RAw-1: 0]; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P(4) ) router_4_port ( .clk(clk), .reset(reset), .router_config_in(router_config[RID]), - .chan_in (router_chan_in [RID] [3 : 0]), + .chan_in (router_chan_in [RID] [3 : 0]), .chan_out (router_chan_out[RID] [3 : 0]), - .router_event(router_event[RID] [3 : 0]) + .router_event(router_event[RID] [3 : 0]) ); end @@ -99,16 +95,15 @@ module custom1_noc_genvar assign router_config [RID].router_id = RID[RAw-1: 0]; assign router_config [RID].router_addr = RID[RAw-1: 0]; router_top #( - .NOC_ID(NOC_ID), .ROUTER_ID(RID), .P(5) ) router_5_port ( .clk(clk), .reset(reset), .router_config_in(router_config[RID]), - .chan_in (router_chan_in [RID] [4 : 0]), + .chan_in (router_chan_in [RID] [4 : 0]), .chan_out (router_chan_out[RID] [4 : 0]), - .router_event(router_event[RID] [4 : 0]) + .router_event(router_event[RID] [4 : 0]) ); end endgenerate @@ -257,5 +252,5 @@ endgenerate assign router_chan_in [15][3] = router_chan_out [13][1]; //Connect R11 input ports 4 to R5 output ports 1 assign router_chan_in [15][4] = router_chan_out [5][1]; - + endmodule diff --git a/mpsoc/rtl/src_topology/param.obj b/mpsoc/rtl/src_topology/param.obj index f184957..79e8679 100644 --- a/mpsoc/rtl/src_topology/param.obj +++ b/mpsoc/rtl/src_topology/param.obj @@ -1,5 +1,5 @@ ####################################################################### -## File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/param.obj +## File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/param.obj ## ## Copyright (C) 2014-2022 Alireza Monemi ## @@ -9,14 +9,21 @@ ## MAY CAUSE UNEXPECTED BEHAVIOR. ################################################################################ $Topology = { - '"mesh4x4"' => { + '"custom1"' => { + 'T3' => 5, + 'ROUTE_NAME' => '"custom"', + 'T1' => 16, + 'T2' => 16, 'ROUTER_Ps' => { - '5' => 16 + '3' => 4, + '5' => 4, + '4' => 8 }, - 'T1' => 16, - 'T3' => 5, - 'ROUTE_NAME' => '"custom","m4"', 'er_addr' => [ + 0, + 1, + 2, + 3, 4, 5, 6, @@ -25,31 +32,14 @@ $Topology = { 9, 10, 11, - 0, - 1, - 2, - 3, 12, 13, 14, 15 - ], - 'T2' => 16 + ] }, - '"custom1"' => { - 'T3' => 5, - 'T1' => 16, - 'ROUTER_Ps' => { - '4' => 8, - '5' => 4, - '3' => 4 - }, - 'T2' => 16, + '"mesh4x4"' => { 'er_addr' => [ - 0, - 1, - 2, - 3, 4, 5, 6, @@ -58,11 +48,21 @@ $Topology = { 9, 10, 11, + 0, + 1, + 2, + 3, 12, 13, 14, 15 ], - 'ROUTE_NAME' => '"custom"' + 'ROUTER_Ps' => { + '5' => 16 + }, + 'T2' => 16, + 'T1' => 16, + 'ROUTE_NAME' => '"custom","m4"', + 'T3' => 5 } }; diff --git a/mpsoc/script/phy_noc_gen/phy_noc.pl b/mpsoc/script/phy_noc_gen/phy_noc.pl index 1e1fa4e..4ae90e3 100644 --- a/mpsoc/script/phy_noc_gen/phy_noc.pl +++ b/mpsoc/script/phy_noc_gen/phy_noc.pl @@ -35,15 +35,15 @@ #check that NoC ID is valid verilog syntac #Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ $ ) if ($noc_id =~ /[^a-zA-Z0-9_\$]+/){ - #print "use of illegal character after\n" ; - my @w= split /([^a-zA-Z0-9_\$]+)/, $noc_id; - die "NOC_ID ($noc_id) contains the illegal character of \"$w[1]\" after $w[0]. Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ \$ )\n"; + #print "use of illegal character after\n" ; + my @w= split /([^a-zA-Z0-9_\$]+)/, $noc_id; + die "NOC_ID ($noc_id) contains the illegal character of \"$w[1]\" after $w[0]. Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ \$ )\n"; } my %replace; -$replace{"`NOC_CONF"} = "import pronoc_pkg_${noc_id}::*;"; +$replace{"import pronoc_pkg::*;"} = "import pronoc_pkg_${noc_id}::*;"; $replace{"noc_localparam.v"} = "noc_localparam_${noc_id}.v"; $replace{"topology_localparam.v"} = "topology_localparam_${noc_id}.v"; $replace{"pronoc_pkg"} = "pronoc_pkg_${noc_id}"; @@ -68,8 +68,6 @@ @common_file = grep { $_ ne '.' && $_ ne '..' && -f "$noc_dir/../$_" } @common_file; closedir($dir); - - #get list of all modules my @module_names; foreach my $file (@files) { @@ -78,10 +76,10 @@ # Read the file line by line while (my $line = <$fh>) { # Match module keyword followed by name until encountering space, #, ;, or ( - while ($line =~ /^\s*module\s+(\w+)[\s#;\(]/g) { - push @module_names, $1; + while ($line =~ /^\s*module\s+(\w+)[\s#;\(]/g) { + push @module_names, $1; } - } + } } #get the list of all parameters/localparam @@ -125,8 +123,8 @@ $file_content =~ s/"(?:[^"\\]|\\.)*"//g; # Find all structs while ($file_content =~ /typedef\s+struct\s+packed\s*{.*?}\s*(\w+)\s*;/sg) { - my $struct_name = $1; - push @replaces, $struct_name; + my $struct_name = $1; + push @replaces, $struct_name; } @@ -141,8 +139,8 @@ $file_content =~ s/"(?:[^"\\]|\\.)*"//g; # Find all structs while ($file_content =~ /function\s+automatic\s+integer\s+(\w+)\s*;/sg) { - my $func = $1; - push @replaces, $func; + my $func = $1; + push @replaces, $func; } @@ -181,9 +179,8 @@ # Open a new file for writing the modified content open(my $output_fh, '>', $output_filename) or die "Could not create file '$output_filename' $!"; if($file eq "pronoc_pkg.sv"){ - print $output_fh "`define IMPORT_PRONOC_PCK\n`define PRONOC_PKG\n"; + print $output_fh "`define IMPORT_PRONOC_PCK\n`define PRONOC_PKG\n"; } - # Read the input file line by line while (my $line = <$input_fh>) { @@ -203,7 +200,7 @@ # Write the modified line to the output file print $output_fh $line; } - + # Close the input and output files close($input_fh); diff --git a/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/main_comp.v b/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/main_comp.v index de31cc8..baadff4 100644 --- a/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/main_comp.v +++ b/mpsoc/src_c/jtag/test_rtl/jtag_ram_test/src_verilog/lib/main_comp.v @@ -163,29 +163,24 @@ module one_hot_demux #( endmodule /************************** -* custom_or +* reduction_or ***************************/ -module custom_or #( - parameter IN_NUM = 4, - parameter OUT_WIDTH = 5 +module reduction_or #( + parameter W = 5,//out width + parameter N = 4 //array lenght )( - or_in, - or_out + D_in, + Q_out ); + input [W-1 : 0] D_in [N-1 : 0]; + output reg [W-1 : 0] Q_out; - localparam IN_WIDTH = IN_NUM*OUT_WIDTH; - input [IN_WIDTH-1 : 0] or_in; - output[OUT_WIDTH-1 : 0] or_out; - wire [IN_NUM-1 : 0] in_sep [OUT_WIDTH-1 : 0]; - genvar i,j; - generate - for (i=0;i Date: Thu, 12 Jun 2025 16:19:04 +0200 Subject: [PATCH 047/107] use package instead of parameter passing --- mpsoc/rtl/arch/iport_reg_base.sv | 26 +-- mpsoc/rtl/src_emulate/rtl/noc_emulator.sv | 13 +- mpsoc/rtl/src_modelsim/multicast_injector.sv | 26 +-- mpsoc/rtl/src_modelsim/multicast_test.sv | 50 ++--- mpsoc/rtl/src_modelsim/pck_injector_test.sv | 53 ++---- mpsoc/rtl/src_modelsim/testbench_noc.sv | 26 +-- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 179 ++++------------- mpsoc/rtl/src_noc/comb_nonspec.sv | 2 +- mpsoc/rtl/src_noc/crossbar.sv | 21 +- mpsoc/rtl/src_noc/debug.sv | 149 ++++----------- mpsoc/rtl/src_noc/fattree_route.sv | 93 ++------- mpsoc/rtl/src_noc/fmesh.sv | 40 +--- mpsoc/rtl/src_noc/input_ports.sv | 48 +---- mpsoc/rtl/src_noc/mesh_torus.sv | 101 +++------- mpsoc/rtl/src_noc/multicast.sv | 82 +++----- mpsoc/rtl/src_noc/noc_filelist.f | 4 +- mpsoc/rtl/src_noc/packet_injector.sv | 14 +- mpsoc/rtl/src_noc/router_bypass.sv | 42 ++-- mpsoc/rtl/src_noc/router_two_stage.sv | 8 +- mpsoc/rtl/src_noc/routing.sv | 190 ++++--------------- mpsoc/rtl/src_noc/ss_allocator.sv | 7 +- mpsoc/rtl/src_noc/star_noc.sv | 2 +- mpsoc/rtl/src_noc/topology_localparam.v | 3 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 22 +-- mpsoc/rtl/src_noc/tree_route.sv | 47 +---- mpsoc/rtl/src_openpiton/piton_mesh.sv | 8 +- mpsoc/rtl/src_openpiton/wrapper.sv | 42 +--- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 12 +- mpsoc/rtl/src_synfull/synfull_top.sv | 4 +- mpsoc/rtl/src_topology/custom_flist.f | 12 +- mpsoc/rtl/src_topology/param.obj | 48 ++--- 31 files changed, 308 insertions(+), 1066 deletions(-) diff --git a/mpsoc/rtl/arch/iport_reg_base.sv b/mpsoc/rtl/arch/iport_reg_base.sv index 40b4078..2fe4a18 100644 --- a/mpsoc/rtl/arch/iport_reg_base.sv +++ b/mpsoc/rtl/arch/iport_reg_base.sv @@ -258,14 +258,7 @@ generate /* verilator lint_off WIDTH */ if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1)) begin : multi_local /* verilator lint_on WIDTH */ - mesh_tori_endp_addr_decode #( - .TOPOLOGY("MESH"), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) - endp_addr_decode + mesh_tori_endp_addr_decode endp_addr_decode ( .e_addr(dest_e_addr_in), .ex( ), @@ -273,7 +266,7 @@ generate .el(endp_l_in), .valid( ) ); - end + end /* verilator lint_off WIDTH */ if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat @@ -664,18 +657,9 @@ generate endgenerate look_ahead_routing #( - .T1(T1), - .T2(T2), - .T3(T3), - .T4(T4), - .P(P), - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw), - .SW_LOC(SW_LOC), - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE) + .P(P), + .SW_LOC(SW_LOC) + ) lk_routing ( .current_r_addr(current_r_addr), .neighbors_r_addr(neighbors_r_addr), diff --git a/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv b/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv index 49121f4..3a295ed 100644 --- a/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv +++ b/mpsoc/rtl/src_emulate/rtl/noc_emulator.sv @@ -193,16 +193,9 @@ module Jtag_traffic_gen generate for (i=0; i= NY? 0 : (current_y + 1); assign dest_l = current_l; assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - endp_addr_decoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - )enc( - .code(dest_e_addr), - .id(dest_ip_num) + endp_addr_decoder enc( + .code_in(dest_e_addr), + .id_out(dest_ip_num) ); end else if( TRAFFIC == "SHUFFLE") begin: shuffle //di = si−1 mod b for(i=1; i<(EAw); i=i+1'b1) begin :lp//reverse the address assign dest_ip_num[i] = current_e_addr [i-1]; end - assign dest_ip_num[0] = current_e_addr [EAw-1]; - endp_addr_encoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - ) addr_encoder( + assign dest_ip_num[0] = current_e_addr [EAw-1]; + endp_addr_encoder addr_encoder( .id(dest_ip_num), .code(dest_e_addr) ); @@ -548,31 +472,17 @@ module two_dimension_pck_dst_gen for(i=0; i<(EAw-1); i=i+1'b1) begin :lp//reverse the address assign dest_ip_num[i] = current_e_addr [i+1]; end - assign dest_ip_num[EAw-1] = current_e_addr [0]; - endp_addr_encoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - ) addr_encoder( - .id(dest_ip_num), - .code(dest_e_addr) + assign dest_ip_num[EAw-1] = current_e_addr [0]; + endp_addr_encoder addr_encoder( + .id_in(dest_ip_num), + .code_out(dest_e_addr) ); end else if(TRAFFIC == "CUSTOM" )begin assign dest_ip_num = custom_traffic_t; - endp_addr_encoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - ) addr_encoder ( - .id(dest_ip_num), - .code(dest_e_addr) + endp_addr_encoder addr_encoder ( + .id_in(dest_ip_num), + .code_out(dest_e_addr) ); assign off_flag = ~custom_traffic_en; @@ -685,16 +595,9 @@ module one_dimension_pck_dst_gen #( assign dest_ip_num = custom_traffic_t; end - endp_addr_encoder #( - .T1(T1), - .T2(T2), - .T3(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - ) addr_encoder ( - .id(dest_ip_num), - .code(dest_e_addr) + endp_addr_encoder addr_encoder ( + .id_in(dest_ip_num), + .code_out(dest_e_addr) ); wire valid_temp = (dest_ip_num <= (NE-1)); diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index 1f7e930..38e83a7 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -146,7 +146,7 @@ module comb_nonspec_allocator # ( //if(VC_ARBITER_TYPE=="RRA")begin :round_robin arbiter #( .ARBITER_WIDTH(V) - ) ovc_arbiter ( + ) ovc_arbiter ( .clk (clk), .reset (reset), .request (masked_non_assigned_request [i]), diff --git a/mpsoc/rtl/src_noc/crossbar.sv b/mpsoc/rtl/src_noc/crossbar.sv index fca34a1..6e15928 100755 --- a/mpsoc/rtl/src_noc/crossbar.sv +++ b/mpsoc/rtl/src_noc/crossbar.sv @@ -26,13 +26,7 @@ **************************************************************/ module crossbar #( - parameter TOPOLOGY = "MESH", - parameter V = 4, // vc_num_per_port - parameter P = 5, // router port num - parameter Fw = 36, - parameter MUX_TYPE="BINARY", //"ONE_HOT" or "BINARY" - parameter SSA_EN= 1, // 1: enable SSA, 0: disable SSA - parameter SELF_LOOP_EN= 0 + parameter P = 5// router port num )( granted_dest_port_all, flit_in_all, @@ -40,14 +34,7 @@ module crossbar #( flit_out_wr_all, ssa_flit_wr_all ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log21) && CAST_TYPE== "UNICAST") begin : multi_local - /* verilator lint_on WIDTH */ - mesh_tori_endp_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) endp_addr_decode ( + if (( IS_RING | IS_LINE | IS_MESH | IS_TORUS) & (T3 > 1) & IS_UNICAST) begin : multi_local + mesh_tori_endp_addr_decode endp_addr_decode ( .e_addr(dest_e_addr_in), .ex( ), .ey( ), @@ -421,16 +413,8 @@ module input_queue_per_port #( .valid( ) ); end :multi_local - /* verilator lint_off WIDTH */ - if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST" ) begin : fmesh - /* verilator lint_on WIDTH */ - - fmesh_endp_addr_decode #( - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) endp_addr_decode ( + if ( IS_FMESH & IS_UNICAST ) begin : fmesh + fmesh_endp_addr_decode endp_addr_decode ( .e_addr(dest_e_addr_in), .ex(), .ey(), @@ -438,9 +422,9 @@ module input_queue_per_port #( .valid() ); - end + end /* verilator lint_off WIDTH */ - if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat + if(IS_FATTREE & (ROUTE_NAME == "NCA_STRAIGHT_UP")) begin : fat /* verilator lint_on WIDTH */ fattree_destport_up_select #( @@ -500,8 +484,7 @@ module input_queue_per_port #( one_hot_to_bin #(.ONE_HOT_WIDTH(V),.BIN_WIDTH(Vw)) conv ( .one_hot_code(assigned_onc_one_hot[i]), .bin_code(assigned_onc_bin[i]) - ); - + ); `ifdef SIMULATION //check ivc info @@ -949,23 +932,10 @@ module input_queue_per_port #( end end - /* verilator lint_off WIDTH */ - if(CAST_TYPE== "UNICAST") begin : unicast - /* verilator lint_on WIDTH */ + if( IS_UNICAST ) begin : unicast look_ahead_routing #( - .T1(T1), - .T2(T2), - .T3(T3), - .T4(T4), .P(P), - .RAw(RAw), - .EAw(EAw), - .DAw(DAw), - .DSTPw(DSTPw), - .SW_LOC(SW_LOC), - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE) + .SW_LOC(SW_LOC) ) lk_routing ( .current_r_addr(current_r_addr), .neighbors_r_addr(neighbors_r_addr), diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 05f2d29..370b0f8 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -669,25 +669,12 @@ module mesh_torus_distance_gen ( ); import pronoc_pkg::*; - localparam - NYY =(IS_RING | IS_LINE )? 1 : T2, - Xw = log2(T1), // number of node in x axis - Yw = log2(NYY); // number of node in y axis - localparam [Xw : 0] NX = T1; - localparam [Yw : 0] NY = NYY [Yw : 0]; - input [EAw-1 : 0] src_e_addr; - input [EAw-1 : 0] dest_e_addr; - output[DISTw-1: 0]distance; - wire [Xw-1 : 0]src_x,dest_x; - wire [Yw-1 : 0]src_y,dest_y; - mesh_tori_endp_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(NYY), - .T3(T3), - .EAw(EAw) - ) src_addr_decode ( + input [EAw-1 : 0] dest_e_addr; + output[DISTw-1: 0]distance; + wire [NXw-1 : 0]src_x,dest_x; + wire [NYw-1 : 0]src_y,dest_y; + mesh_tori_endp_addr_decode src_addr_decode ( .e_addr(src_e_addr), .ex(src_x), .ey(src_y), @@ -695,13 +682,7 @@ module mesh_torus_distance_gen ( .valid() ); - mesh_tori_endp_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(NYY), - .T3(T3), - .EAw(EAw) - ) dest_addr_decode ( + mesh_tori_endp_addr_decode dest_addr_decode ( .e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), @@ -709,8 +690,8 @@ module mesh_torus_distance_gen ( .valid() ); - reg [Xw-1 : 0] x_offset; - reg [Yw-1 : 0] y_offset; + reg [NXw-1 : 0] x_offset; + reg [NYw-1 : 0] y_offset; generate if( IS_MESH | IS_LINE) begin : oneD always_comb begin @@ -721,10 +702,10 @@ module mesh_torus_distance_gen ( wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y; /* verilator lint_off WIDTH */ always_comb begin - x_offset= {Xw{1'b0}}; - y_offset= {Yw{1'b0}}; + x_offset= {NXw{1'b0}}; + y_offset= {NYw{1'b0}}; //x_offset - if(same_x) x_offset= {Xw{1'b0}}; + if(same_x) x_offset= {NXw{1'b0}}; else if(tranc_x_plus) begin if(dest_x > src_x) x_offset= dest_x-src_x; else x_offset= (NX-src_x)+dest_x; @@ -734,7 +715,7 @@ module mesh_torus_distance_gen ( else x_offset= src_x+(NX-dest_x); end //y_offset - if(same_y) y_offset= {Yw{1'b0}}; + if(same_y) y_offset= {NYw{1'b0}}; else if(tranc_y_plus) begin if(dest_y > src_y) y_offset= dest_y-src_y; else y_offset= (NY-src_y)+dest_y; @@ -874,33 +855,17 @@ module line_ring_ssa_check_destport #( endmodule -module mesh_tori_router_addr_decode #( - parameter TOPOLOGY = "MESH", - parameter T1=4, - parameter T2=4, - parameter T3=4, - parameter RAw=6 -)( +module mesh_tori_router_addr_decode ( r_addr, rx, ry, valid ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 i); + assign x_plus[i] = (current_rx > i); /* verilator lint_off UNSIGNED */ - assign x_minus[i] = (current_rx < i); + assign x_minus[i] = (current_rx < i); /* verilator lint_on UNSIGNED */ end //get all endp addresses located in the same x @@ -365,17 +354,10 @@ module mcast_dest_list_decode ( reg [NE-1 : 0] dest_o_uni; wire [NEw-1 : 0] unicast_id; assign is_unicast = not_in_cast_list; - endp_addr_decoder #( - .TOPOLOGY (TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw), - .NE(NE) - ) decoder ( - .code(unicast_code), - .id(unicast_id) - ); + endp_addr_decoder decoder ( + .code_in(unicast_code), + .id_out(unicast_id) + ); always_comb begin dest_o_uni = {NE{1'b0}}; @@ -396,18 +378,11 @@ module mcast_dest_list_decode ( assign is_unicast =not_broad_casted; wire [NE-1 : 0] dest_o_multi; reg [NE-1 : 0] dest_o_uni; - wire [NEw-1 : 0] unicast_id; - endp_addr_decoder #( - .TOPOLOGY (TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw), - .NE(NE) - ) decoder ( - .code(unicast_code), - .id(unicast_id) - ); + wire [NEw-1 : 0] unicast_id; + endp_addr_decoder decoder ( + .code_in(unicast_code), + .id_out(unicast_id) + ); always_comb begin dest_o_uni = {NE{1'b0}}; @@ -424,17 +399,10 @@ module mcast_dest_list_decode ( reg [NE-1 : 0] dest_o_uni; wire [NEw-1 : 0] unicast_id; - endp_addr_decoder #( - .TOPOLOGY (TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw), - .NE(NE) - ) decoder ( - .code(unicast_code), - .id(unicast_id) - ); + endp_addr_decoder decoder ( + .code_in(unicast_code), + .id_out(unicast_id) + ); always_comb begin dest_o_uni = {NE{1'b0}}; @@ -442,7 +410,7 @@ module mcast_dest_list_decode ( end assign dest_o = (not_broad_casted)? dest_o_uni : MCAST_ENDP_LIST; end - endgenerate + endgenerate endmodule @@ -654,4 +622,4 @@ module multicast_dst_sel ( .grant (arb_out), .any_grant ( ) ); -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/noc_filelist.f b/mpsoc/rtl/src_noc/noc_filelist.f index 803a5b1..82684e2 100644 --- a/mpsoc/rtl/src_noc/noc_filelist.f +++ b/mpsoc/rtl/src_noc/noc_filelist.f @@ -1,8 +1,8 @@ +incdir+./ +incdir+./../ ./pronoc_pkg.sv -./../main_comp.sv -./../arbiter.sv +./../main_comp.v +./../arbiter.v ./ovc_list.sv ./ss_allocator.sv ./route_torus.sv diff --git a/mpsoc/rtl/src_noc/packet_injector.sv b/mpsoc/rtl/src_noc/packet_injector.sv index 2c01da3..573fd84 100644 --- a/mpsoc/rtl/src_noc/packet_injector.sv +++ b/mpsoc/rtl/src_noc/packet_injector.sv @@ -69,16 +69,6 @@ module packet_injector ( generate if(CAST_TYPE == "UNICAST") begin : uni conventional_routing #( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .T1(T1), - .T2(T2), - .T3(T3), - .RAw(RAw), - .EAw(EAw), - .DAw(DAw), - .DSTPw(DSTPw), .LOCATED_IN_NI(1) ) routing_module ( .reset(reset), @@ -259,8 +249,8 @@ module packet_injector ( `ifdef SIMULATION wire [NEw-1 : 0] current_id; wire [NEw-1 : 0] sendor_id; - endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) encode1 ( .id(current_id), .code(current_e_addr)); - endp_addr_decoder #( .TOPOLOGY(TOPOLOGY), .T1(T1), .T2(T2), .T3(T3), .EAw(EAw), .NE(NE)) encode2 ( .id(sendor_id), .code(pck_injct_out.endp_addr[EAw-1 : 0])); + endp_addr_decoder encode1 ( .id_out(current_id), .code_in(current_e_addr)); + endp_addr_decoder encode2 ( .id_out(sendor_id), .code_in(pck_injct_out.endp_addr[EAw-1 : 0])); `endif wire [NE-1 :0] dest_mcast_all_endp; diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index 2128e56..5ef7a6b 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -580,24 +580,14 @@ module smart_allocator_per_iport # ( // does the route computation for the current router conventional_routing #( - .TOPOLOGY (TOPOLOGY), - .ROUTE_NAME (ROUTE_NAME), - .ROUTE_TYPE (ROUTE_TYPE), - .T1 (T1), - .T2 (T2), - .T3 (T3), - .RAw (RAw), - .EAw (EAw), - .DAw (DAw), - .DSTPw (DSTPw), .LOCATED_IN_NI (LOCATED_IN_NI) ) routing ( - .reset (reset), - .clk (clk), - .current_r_addr (current_r_addr_i), - .src_e_addr ( ),// needed only for custom routing - .dest_e_addr (smart_chanel_i.dest_e_addr), - .destport (destport) + .reset (reset), + .clk (clk), + .current_r_addr (current_r_addr_i), + .src_e_addr ( ),// needed only for custom routing + .dest_e_addr (smart_chanel_i.dest_e_addr), + .destport (destport) ); pronoc_register #(.W(DSTPw)) reg1 (.D_in(destport), .reset(reset), .clk(clk), .Q_out(smart_destport_o)); @@ -611,24 +601,14 @@ module smart_allocator_per_iport # ( //look ahead routing. take straight next router address as input conventional_routing #( - .TOPOLOGY (TOPOLOGY), - .ROUTE_NAME (ROUTE_NAME), - .ROUTE_TYPE (ROUTE_TYPE), - .T1 (T1), - .T2 (T2), - .T3 (T3), - .RAw (RAw), - .EAw (EAw), - .DAw (DAw), - .DSTPw (DSTPw), .LOCATED_IN_NI (LOCATED_IN_NI) ) lkrouting ( - .reset (reset), - .clk (clk), + .reset (reset), + .clk (clk), .current_r_addr (neighbors_r_addr_i[SS_PORT_LOC]), - .src_e_addr ( ),// needed only for custom routing - .dest_e_addr (smart_chanel_i.dest_e_addr), - .destport (lkdestport) + .src_e_addr ( ),// needed only for custom routing + .dest_e_addr (smart_chanel_i.dest_e_addr), + .destport (lkdestport) ); pronoc_register #(.W(DSTPw)) reg2 (.D_in(lkdestport), .reset(reset), .clk(clk), .Q_out(smart_lk_destport_o)); diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index a66f743..2404f13 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -340,13 +340,7 @@ module router_two_stage #( pronoc_register #(.W(PP_1)) reg2 (.D_in(granted_dest_port_all ), .Q_out(granted_dest_port_all_delayed), .reset(reset), .clk(clk)); crossbar #( - .TOPOLOGY(TOPOLOGY), - .V (V), // vc_num_per_port - .P (P), // router port num - .Fw (Fw), - .MUX_TYPE (MUX_TYPE), - .SSA_EN (SSA_EN), - .SELF_LOOP_EN(SELF_LOOP_EN) + .P (P) // router port num ) the_crossbar ( .granted_dest_port_all (granted_dest_port_all_delayed), .flit_in_all (iport_flit_out_all), diff --git a/mpsoc/rtl/src_noc/routing.sv b/mpsoc/rtl/src_noc/routing.sv index fbd7f0c..c19d84c 100755 --- a/mpsoc/rtl/src_noc/routing.sv +++ b/mpsoc/rtl/src_noc/routing.sv @@ -28,17 +28,7 @@ module conventional_routing #( - parameter TOPOLOGY = "MESH", - parameter ROUTE_NAME = "XY", - parameter ROUTE_TYPE = "DETERMINISTIC", - parameter T1 = 4, - parameter T2 = 4, - parameter T3 = 4, - parameter RAw = 3, - parameter EAw = 3, - parameter DAw = EAw, - parameter DSTPw = 4, - parameter LOCATED_IN_NI = 1 // only needed for mesh and odd-even routing + parameter LOCATED_IN_NI = 1 // only needed for mesh and odd-even routing )( reset, clk, @@ -48,14 +38,7 @@ module conventional_routing #( destport ); - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 P-T3) ? 0 : SW_LOC; //single_local - mesh_tori_router_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .RAw(RAw) - ) router_addr_decode ( + mesh_tori_router_addr_decode router_addr_decode ( .r_addr(current_r_addr), .rx(current_rx), .ry(current_ry), .valid( ) ); - /* verilator lint_off WIDTH */ - if(TOPOLOGY == "FMESH") begin :fmesh - /* verilator lint_on WIDTH */ - fmesh_endp_addr_decode #( - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) end_addr_decode ( + if(IS_FMESH) begin :fmesh + fmesh_endp_addr_decode end_addr_decode ( .e_addr(dest_e_addr), .ex(dest_ex), .ey(dest_ey), @@ -317,13 +211,7 @@ module look_ahead_routing #( .valid() ); end else begin :mesh - mesh_tori_endp_addr_decode #( - .TOPOLOGY(TOPOLOGY), - .T1(T1), - .T2(T2), - .T3(T3), - .EAw(EAw) - ) end_addr_decode ( + mesh_tori_endp_addr_decode end_addr_decode ( .e_addr(dest_e_addr), .ex(dest_ex), .ey(dest_ey), @@ -343,9 +231,7 @@ module look_ahead_routing #( .reset(reset), .clk(clk) ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "FATTREE") begin: fat - /* verilator lint_on WIDTH */ + end else if (IS_FATTREE) begin: fat wire [PLKw-1 : 0] neighbors_rx; wire [PLw-1 : 0] neighbors_ry; for (i=0; i { - 'T3' => 5, - 'ROUTE_NAME' => '"custom"', - 'T1' => 16, - 'T2' => 16, - 'ROUTER_Ps' => { - '3' => 4, - '5' => 4, - '4' => 8 - }, + '"mesh4x4"' => { 'er_addr' => [ - 0, - 1, - 2, - 3, 4, 5, 6, @@ -32,14 +19,31 @@ $Topology = { 9, 10, 11, + 0, + 1, + 2, + 3, 12, 13, 14, 15 - ] + ], + 'ROUTER_Ps' => { + '5' => 16 + }, + 'T1' => 16, + 'T2' => 16, + 'ROUTE_NAME' => '"custom","m4"', + 'T3' => 5 }, - '"mesh4x4"' => { + '"custom1"' => { + 'ROUTE_NAME' => '"custom"', + 'T3' => 5, 'er_addr' => [ + 0, + 1, + 2, + 3, 4, 5, 6, @@ -48,21 +52,17 @@ $Topology = { 9, 10, 11, - 0, - 1, - 2, - 3, 12, 13, 14, 15 ], 'ROUTER_Ps' => { - '5' => 16 + '3' => 4, + '4' => 8, + '5' => 4 }, 'T2' => 16, - 'T1' => 16, - 'ROUTE_NAME' => '"custom","m4"', - 'T3' => 5 + 'T1' => 16 } }; From a8efacb48260e7fcd55320ceb875d4f37d0fa033 Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 12 Jun 2025 18:37:46 +0200 Subject: [PATCH 048/107] add Questasim lint to intigration test --- .../Questa_lint/Questa_Starter_21.sh | 5 ++ .../Questa_lint/configurations/line4_smart3 | 16 ++++ mpsoc/Integration_test/Questa_lint/run.sh | 54 ++++++++++++ .../Questa_lint/src/file_list.f | 6 ++ .../Questa_lint/src/param_gen.pl | 46 ++++++++++ mpsoc/rtl/src_noc/fattree_noc_top.sv | 11 +-- mpsoc/rtl/src_noc/inout_ports.sv | 14 ++-- mpsoc/rtl/src_noc/input_ports.sv | 83 ++++++++++--------- mpsoc/rtl/src_noc/ovc_list.sv | 38 ++++----- mpsoc/rtl/src_noc/ss_allocator.sv | 36 +++----- mpsoc/rtl/src_noc/topology_localparam.v | 5 +- mpsoc/rtl/src_noc/tree_noc_top.sv | 7 +- 12 files changed, 220 insertions(+), 101 deletions(-) create mode 100644 mpsoc/Integration_test/Questa_lint/Questa_Starter_21.sh create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/line4_smart3 create mode 100644 mpsoc/Integration_test/Questa_lint/run.sh create mode 100644 mpsoc/Integration_test/Questa_lint/src/file_list.f create mode 100644 mpsoc/Integration_test/Questa_lint/src/param_gen.pl diff --git a/mpsoc/Integration_test/Questa_lint/Questa_Starter_21.sh b/mpsoc/Integration_test/Questa_lint/Questa_Starter_21.sh new file mode 100644 index 0000000..f61cb8a --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/Questa_Starter_21.sh @@ -0,0 +1,5 @@ +export QUESTA_ST=$HOME/intelFPGA_lite/Questa_starter21 +export MGLS_LICENSE_FILE=; +export LM_LICENSE_FILE=$QUESTA_ST/LR-173241_License.dat; +export MODELSIM_HOME=$QUESTA_ST/questa_fse; +export PATH=$PATH:$MODELSIM_HOME/bin; diff --git a/mpsoc/Integration_test/Questa_lint/configurations/line4_smart3 b/mpsoc/Integration_test/Questa_lint/configurations/line4_smart3 new file mode 100644 index 0000000..548c123 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/line4_smart3 @@ -0,0 +1,16 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + TOPOLOGY=>"\"LINE\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "1", + "MCAST_ENDP_LIST" => "'b11", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/run.sh b/mpsoc/Integration_test/Questa_lint/run.sh new file mode 100644 index 0000000..bd8b0bc --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/run.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) +SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) + +# Source the environment variables +conf_dir="${SCRPT_DIR_PATH}/configurations" +log_dir="${SCRPT_DIR_PATH}/result_logs" +conf_dir="${SCRPT_DIR_PATH}/configurations" +work="${SCRPT_DIR_PATH}/work" +file_list_f="${SCRPT_DIR_PATH}/src/file_list.f" +lint_file="${SCRPT_DIR_PATH}/src/lint.tcl" + +mkdir -p $work +mkdir -p $log_dir + +questa_lint () { + conf=$1 + conf_file="${conf_dir}/$conf" + log_file="${log_dir}/${conf}.log" + + if [[ ! -f "$conf_file" ]]; then + echo "Configuration file $conf_file does not exist" + exit 1 + fi + + perl "${SCRPT_DIR_PATH}/src/param_gen.pl" "$conf_file" + export REPORT_FILENAME="${log_dir}/${conf}.txt" + export FILE_LIST=$file_list_f + + # Clean old work library + rm -rf work + vlib work + # Lint the design + vlog -sv -lint -f ${file_list_f} + vsim -c work.noc_top -do "quit" +} + +for f in "$conf_dir"/*; do + [[ -d "$f" ]] && continue + conf=$(basename "$f") + log_file="${log_dir}/${conf}.log" + echo "▶️ Compiling configuration: $conf" + questa_lint "$conf" |& tee $log_file + if [[ $? -ne 0 ]]; then + echo "❌ Compilation failed for $conf (check $log_file)" + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + exit 1 + else + echo "✅ Compilation successful for $conf" + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + fi + +done diff --git a/mpsoc/Integration_test/Questa_lint/src/file_list.f b/mpsoc/Integration_test/Questa_lint/src/file_list.f new file mode 100644 index 0000000..1f5742d --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/src/file_list.f @@ -0,0 +1,6 @@ ++incdir+./src + +-F ./../../rtl/src_noc/noc_filelist.f +-F ./../../rtl/src_topology/custom_flist.f + + diff --git a/mpsoc/Integration_test/Questa_lint/src/param_gen.pl b/mpsoc/Integration_test/Questa_lint/src/param_gen.pl new file mode 100644 index 0000000..1ad4763 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/src/param_gen.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl +package ProNOC; +use strict; +use warnings; +use File::Basename; + + +#add home dir in perl 5.6 +use FindBin; +use lib $FindBin::Bin; +use Cwd qw(realpath); + + + + +use File::Path qw(make_path); + + +use strict; +use warnings; + + + + +my $script_path = dirname(__FILE__); + +require "$script_path/../../synthetic_sim/src/src.pl"; +use lib "../synthetic_sim/src/perl_lib"; + +use constant::boolean; +use base 'Class::Accessor::Fast'; + +my $conf_file=$ARGV[0]; + + +sub create_noc_param_vv { + my ($conf_file)=@_; + my $o = do $conf_file; + die "Could not parse $conf_file: $@" if $@; + die "Could not read $conf_file: $!" unless defined $o; + my $param = $o->{'noc_param'}; + my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); + save_file("$script_path/noc_localparam.v",$param_v); +} + +create_noc_param_vv ($conf_file); diff --git a/mpsoc/rtl/src_noc/fattree_noc_top.sv b/mpsoc/rtl/src_noc/fattree_noc_top.sv index 4709415..dbe4a56 100644 --- a/mpsoc/rtl/src_noc/fattree_noc_top.sv +++ b/mpsoc/rtl/src_noc/fattree_noc_top.sv @@ -95,6 +95,7 @@ module fattree_noc_top ( generate for( pos=0; pos K)? K : MAX_P; assign router_config_in[RID].router_id = RID [NRw-1 : 0]; assign router_config_in[RID].router_addr = current_r_addr [RID]; router_top # ( @@ -102,11 +103,11 @@ module fattree_noc_top ( .P(K) ) the_router ( .router_config_in(router_config_in[RID]), - .chan_in (router_chan_in [RID][K-1 : 0]), - .chan_out (router_chan_out[RID][K-1 : 0]), - .router_event (router_event[RID][K-1 : 0]), - .clk (clk), - .reset (reset ) + .chan_in (router_chan_in [RID][BOUND-1 : 0]), + .chan_out(router_chan_out[RID][BOUND-1 : 0]), + .router_event (router_event[RID][BOUND-1 : 0]), + .clk (clk), + .reset (reset) ); end diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index c610cca..2e6e1e5 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -371,6 +371,14 @@ module output_vc_status #( wire [V-1 : 0] cand_vc_next; wire [V-1 :0] request; + always_comb begin + for(int k=0;k 1) & IS_UNICAST) begin : multi_local mesh_tori_endp_addr_decode endp_addr_decode ( @@ -463,7 +462,7 @@ module input_queue_per_port #( ivc_info[k].assigned_ovc_not_full = assigned_ovc_not_full[k]; ivc_info[k].candidate_ovc = candidate_ovcs [k]; ivc_info[k].ovc_is_assigned = ovc_is_assigned[k]; - ivc_info[k].assigned_ovc_num = assigned_onc_one_hot[k]; + ivc_info[k].assigned_ovc_num = assigned_ovc_one_hot[k]; ivc_info[k].dest_port_encoded = dest_port_encoded[k]; //ivc_info[k].getting_swa_first_arbiter_grant=nonspec_first_arbiter_granted_ivc[k]; //ivc_info[k].getting_swa_grant=ivc_num_getting_sw_grant[k]; @@ -473,16 +472,46 @@ module input_queue_per_port #( ivc_info[k].dest_e_addr = dest_e_addr_out[k]; end //for k for (int k=PORT_IVC; k V )begin :b2 - for (i=0;i V) begin + // P_1 > V + for (int i = 0; i < V; i++) begin + vc_pririty_init[i] = |dest_port[((i+1)*P_1)/V - 1 -: ((P_1)/V)]; + // Note: Using part-select with width (P_1/V) for clarity + end + end else begin + // P_1 < V + vc_pririty_init = '0; + for (int j = 0; j < P_1; j++) begin + vc_pririty_init[j + OFFSET] = dest_port[j]; end - end - end else begin :b3 - always_comb begin //P_1 < V - vc_pririty_init={V{1'b0}}; - for (j=0;jSS_PORT) ? SS_PORT : SS_PORT-1; - always_comb begin - destport_temp=destport_in; - if(destport_in=={P_1{1'b0}}) begin - destport_temp[SS_PORT_CODE]= 1'b1; - end - end - assign destport_out = destport_temp; + output [P_1-1 : 0] destport_out; + logic [P_1-1 : 0] destport_temp; + localparam SS_PORT_CODE = + (SS_PORT == DISABLED) ? 0 : + (SELF_LOOP_EN) ? SS_PORT : + (SW_LOC > SS_PORT) ? SS_PORT : SS_PORT - 1; + always_comb begin + destport_temp = destport_in; + if (destport_in == {P_1{1'b0}}) begin + if((SS_PORT != DISABLED)) destport_temp[SS_PORT_CODE] = 1'b1; end - end //ss - endgenerate + end + assign destport_out = (SS_PORT == DISABLED)? destport_in : destport_temp; endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 96f221b..ccb35e3 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -34,7 +34,6 @@ IS_BROADCAST_PARTIAL = (CAST_TYPE == "BROADCAST_PARTIAL"), IS_UNICAST = (CAST_TYPE == "UNICAST"), IS_BROADCAST_FULL = (CAST_TYPE == "BROADCAST_FULL"), - IS_DETERMINISTIC = (ROUTE_TYPE == "DETERMINISTIC"), IS_ONE_HOT_MUX = (MUX_TYPE=="ONE_HOT"); /* verilator lint_on WIDTH */ @@ -328,7 +327,9 @@ (IS_FMESH)? ROUTE_TYPE_MESH_TORI: (IS_STAR) ? ROUTE_TYPE_STAR: ROUTE_TYPE_CUSTOM; - /* verilator lint_on WIDTH */ + + localparam [0:0] IS_DETERMINISTIC = (ROUTE_TYPE == "DETERMINISTIC"); + /* verilator lint_on WIDTH */ function automatic integer mcast_id_to_endp_id; input integer mcast_id; reg [NE-1 : 0] mcast_list; diff --git a/mpsoc/rtl/src_noc/tree_noc_top.sv b/mpsoc/rtl/src_noc/tree_noc_top.sv index ace80ac..b697db0 100644 --- a/mpsoc/rtl/src_noc/tree_noc_top.sv +++ b/mpsoc/rtl/src_noc/tree_noc_top.sv @@ -97,6 +97,7 @@ module tree_noc_top ( *****************/ localparam [Lw-1 : 0] ROOT_L = L-1; localparam ROOT_ID = 0; + localparam BOUND=(MAX_P > K)? K : MAX_P; assign current_layer_addr [ROOT_ID] = ROOT_L; assign current_pos_addr [ROOT_ID] = {LKw{1'b0}}; @@ -108,9 +109,9 @@ module tree_noc_top ( .P(K) ) root_router ( .router_config_in(router_config_in[ROOT_ID]), - .chan_in (router_chan_in [ROOT_ID][K-1:0]), - .chan_out (router_chan_out[ROOT_ID][K-1:0]), - .router_event (router_event[ROOT_ID][K-1 : 0]), + .chan_in (router_chan_in [ROOT_ID][BOUND-1:0]), + .chan_out (router_chan_out[ROOT_ID][BOUND-1:0]), + .router_event (router_event[ROOT_ID][BOUND-1 : 0]), .clk (clk), .reset (reset) ); From dd64c785fbddc6bc19f12067f96630e8973c4408 Mon Sep 17 00:00:00 2001 From: amonemi Date: Fri, 13 Jun 2025 17:24:17 +0200 Subject: [PATCH 049/107] fix questasim linting --- .../configurations/Fattree_k3_L3_st | 9 + .../configurations/bintree_k3_L3_st | 9 + .../configurations/custom1_topology | 10 + .../configurations/fmesh_1x1_openpiton | 15 ++ .../configurations/fmesh_2x2_openpiton | 14 ++ .../configurations/fmesh_8x8_2cycle_xy | 6 + .../configurations/fmesh_8x8_openpiton | 14 ++ .../configurations/mesh_2x2_openpiton | 13 ++ .../configurations/mesh_3x3_v2_ssa | 12 ++ .../configurations/mesh_4x4_2cycle_mcast_f | 8 + .../configurations/mesh_4x4_smart3 | 15 ++ .../configurations/mesh_4x4_v1_B15 | 13 ++ .../configurations/mesh_4x4x3_2cycle_xy | 9 + .../configurations/mesh_8x8_2cycle_adaptive | 6 + .../configurations/mesh_8x8_2cycle_west_first | 5 + .../configurations/mesh_8x8_2cycle_xy | 5 + .../configurations/mesh_8x8_4vc_4c | 9 + .../Questa_lint/configurations/mesh_8x8_b2 | 7 + .../configurations/mesh_8x8_sbp6_xy | 5 + .../configurations/mesh_8x8_single_flit | 8 + .../configurations/mesh_8x8_ssa_xy | 5 + .../Questa_lint/configurations/star_6 | 8 + .../configurations/torus_8x8_2cycle_xy | 6 + .../perl_gui/lib/perl/topology_verilog_gen.pl | 11 +- mpsoc/rtl/src_noc/debug.sv | 22 +-- mpsoc/rtl/src_noc/flit_buffer.sv | 55 +++--- mpsoc/rtl/src_noc/fmesh.sv | 56 +++--- mpsoc/rtl/src_noc/mesh_torus.sv | 183 ++++++++---------- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 14 +- mpsoc/rtl/src_noc/multicast.sv | 46 ++--- mpsoc/rtl/src_noc/output_ports.sv | 30 +-- mpsoc/rtl/src_noc/router_bypass.sv | 20 +- mpsoc/rtl/src_noc/router_top.sv | 93 ++++----- mpsoc/rtl/src_noc/traffic_gen_top.sv | 13 +- mpsoc/rtl/src_noc/tree_noc_top.sv | 5 +- .../Tcustom1Rcustom_conventional_routing.v | 2 +- ...stom1Rcustom_conventional_routing_genvar.v | 2 +- .../Tcustom1Rcustom_look_ahead_routing.v | 2 +- ...custom1Rcustom_look_ahead_routing_genvar.v | 2 +- mpsoc/rtl/src_topology/custom1/custom1.png | Bin 137543 -> 83516 bytes mpsoc/rtl/src_topology/custom1/custom1_noc.sv | 2 +- .../custom1/custom1_noc_genvar.sv | 8 +- mpsoc/rtl/src_topology/custom_flist.f | 12 +- mpsoc/rtl/src_topology/param.obj | 48 ++--- 44 files changed, 510 insertions(+), 327 deletions(-) create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/Fattree_k3_L3_st create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/bintree_k3_L3_st create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/custom1_topology create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/fmesh_1x1_openpiton create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/fmesh_2x2_openpiton create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_openpiton create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_2x2_openpiton create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_3x3_v2_ssa create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_2cycle_mcast_f create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_smart3 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_v1_B15 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_west_first create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_sbp6_xy create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_single_flit create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_ssa_xy create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/star_6 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy diff --git a/mpsoc/Integration_test/Questa_lint/configurations/Fattree_k3_L3_st b/mpsoc/Integration_test/Questa_lint/configurations/Fattree_k3_L3_st new file mode 100644 index 0000000..e8816f6 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/Fattree_k3_L3_st @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"FATTREE\"", + "T1" => "3", + "T2" => "3", + "B" => "5", + "ROUTE_NAME" => "\"NCA_STRAIGHT_UP\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/bintree_k3_L3_st b/mpsoc/Integration_test/Questa_lint/configurations/bintree_k3_L3_st new file mode 100644 index 0000000..85fc4b5 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/bintree_k3_L3_st @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TREE\"", + "T1" => "3", + "T2" => "3", + "B" => "5", + "ROUTE_NAME" => "\"NCA\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/custom1_topology b/mpsoc/Integration_test/Questa_lint/configurations/custom1_topology new file mode 100644 index 0000000..8b17d0e --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/custom1_topology @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=>"\"custom1\"", + "CUSTOM_TOPOLOGY_NAME"=>"\"custom1\"", + "T1" => "16", + "T2" => "16", + "T3" => "5", + "ROUTE_NAME" =>"\"custom\"" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/fmesh_1x1_openpiton b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_1x1_openpiton new file mode 100644 index 0000000..f80a7c7 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_1x1_openpiton @@ -0,0 +1,15 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "1", + "T2" => "1", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + "MIN_PCK_SIZE" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/fmesh_2x2_openpiton b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_2x2_openpiton new file mode 100644 index 0000000..449f321 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_2x2_openpiton @@ -0,0 +1,14 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "2", + "T2" => "2", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy new file mode 100644 index 0000000..ff79533 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy @@ -0,0 +1,6 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"FMESH\"", + "ROUTE_NAME" => "\"XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_openpiton b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_openpiton new file mode 100644 index 0000000..37c19a2 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_openpiton @@ -0,0 +1,14 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "8", + "T2" => "8", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_2x2_openpiton b/mpsoc/Integration_test/Questa_lint/configurations/mesh_2x2_openpiton new file mode 100644 index 0000000..4b61b2e --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_2x2_openpiton @@ -0,0 +1,13 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "2", + "T2" => "2", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/Questa_lint/configurations/mesh_3x3_v2_ssa new file mode 100644 index 0000000..1383775 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_3x3_v2_ssa @@ -0,0 +1,12 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "3", + "T2" => "3", + "SELF_LOOP_EN" => "1", + "SSA_EN"=> "1", + "LB" => 16, + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", + "Fpay" => "64", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_2cycle_mcast_f new file mode 100644 index 0000000..975dea2 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_2cycle_mcast_f @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64" + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_smart3 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_smart3 new file mode 100644 index 0000000..ad8749e --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_smart3 @@ -0,0 +1,15 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_v1_B15 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_v1_B15 new file mode 100644 index 0000000..a07a491 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_v1_B15 @@ -0,0 +1,13 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "15", + "LB" => "15", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "0", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy new file mode 100644 index 0000000..f0c8499 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive new file mode 100644 index 0000000..20550e3 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive @@ -0,0 +1,6 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"DUATO\"", + "ESCAP_VC_MASK" => "2'b01" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_west_first b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_west_first new file mode 100644 index 0000000..a794210 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_west_first @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"WEST_FIRST\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy new file mode 100644 index 0000000..4af7e61 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c new file mode 100644 index 0000000..d2f38c8 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "V" => 4, + "C" => 4, + "CLASS_SETTING" => "16'b1000010000100001", + "ESCAP_VC_MASK" => "4'b1000" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 new file mode 100644 index 0000000..8ad895e --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "B"=> "2", + "LB"=> 2 + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_sbp6_xy b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_sbp6_xy new file mode 100644 index 0000000..8e2119a --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_sbp6_xy @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "6", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_single_flit b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_single_flit new file mode 100644 index 0000000..fb793b8 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_single_flit @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "B" => "5", + "LB" => "5", + "MIN_PCK_SIZE" => "1", + "PCK_TYPE" => " \"SINGLE_FLIT\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_ssa_xy b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_ssa_xy new file mode 100644 index 0000000..02cf843 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_ssa_xy @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "SSA_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/star_6 b/mpsoc/Integration_test/Questa_lint/configurations/star_6 new file mode 100644 index 0000000..06cc862 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/star_6 @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"STAR\"", + "T1" => "6", + "T2" => "1", + "B" => "5", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy new file mode 100644 index 0000000..5ade6a7 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy @@ -0,0 +1,6 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index 8187c67..a141067 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -305,10 +305,11 @@ sub generate_topology_top_genvar_v{ } #step 2 add routers my $Tnum=1; - my $routers=' + my $routers=" genvar i; - generate - '; + generate + if (TOPOLOGY == \"$name\" ) begin + "; my $offset=0; my $assign=""; my $assign_r2r=""; @@ -375,7 +376,7 @@ sub generate_topology_top_genvar_v{ $offset+= $n; } } - $routers.="endgenerate\n"; + # $routers.="endgenerate\n"; print $fd " module ${name}_noc_genvar ( @@ -391,6 +392,8 @@ sub generate_topology_top_genvar_v{ $endps_wires $routers $assign +end // topology +endgenerate endmodule "; close $fd; diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index 8390c14..094b99a 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -354,8 +354,8 @@ module endp_addr_encoder ( import pronoc_pkg::*; localparam NEw= log2(NE); - input [NEw-1 :0] id; - output [EAw-1 : 0] code; + input [NEw-1 :0] id_in; + output [EAw-1 : 0] code_out; generate if( IS_FATTREE | IS_TREE ) begin : tree @@ -363,8 +363,8 @@ module endp_addr_encoder ( .K(T1), .L(T2) ) addr_encoder ( - .id(id), - .code(code) + .id(id_in), + .code(code_out) ); end else if (IS_MESH | IS_TORUS | IS_RING | IS_LINE) begin : tori mesh_tori_addr_encoder #( @@ -375,8 +375,8 @@ module endp_addr_encoder ( .EAw(EAw), .TOPOLOGY(TOPOLOGY) ) addr_encoder ( - .id(id), - .code(code) + .id(id_in), + .code(code_out) ); end else if (IS_FMESH) begin :fmesh fmesh_addr_encoder #( @@ -386,16 +386,16 @@ module endp_addr_encoder ( .NE(NE), .EAw(EAw) ) addr_encoder ( - .id(id), - .code(code) + .id(id_in), + .code(code_out) ); end else if ( IS_MULTI_MESH) begin :mmesh multimesh_address_encoder addr_encoder ( - .rid_in(id), - .addr_st_o(code) + .rid_in(id_in), + .addr_st_o(code_out) ); end else begin :custom - assign code =id; + assign code_out =id_in; end endgenerate endmodule diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 02b3b02..ae754f4 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -148,6 +148,25 @@ module flit_buffer end end//for + always_comb begin + for(int k=0;k1) begin :multi assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ { {(NL-1){1'b0}} ,portout}; @@ -325,14 +315,14 @@ module fmesh_destp_decoder #( end if(SELF_LOOP_EN == 0) begin :nslp remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) remove_sw_loc ( - .destport_in(destport_onehot), - .destport_out(dest_port_out) - ); + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(destport_onehot), + .destport_out(dest_port_out) + ); end else begin: slp - assign dest_port_out = destport_onehot; + assign dest_port_out = destport_onehot; end endgenerate endmodule diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 370b0f8..23abdcc 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -662,88 +662,87 @@ endmodule /******************** * distance_gen ********************/ -module mesh_torus_distance_gen ( +module mesh_line_distance_gen ( src_e_addr, dest_e_addr, distance ); import pronoc_pkg::*; - input [EAw-1 : 0] src_e_addr; input [EAw-1 : 0] dest_e_addr; output[DISTw-1: 0]distance; wire [NXw-1 : 0]src_x,dest_x; wire [NYw-1 : 0]src_y,dest_y; - mesh_tori_endp_addr_decode src_addr_decode ( - .e_addr(src_e_addr), - .ex(src_x), - .ey(src_y), - .el(), - .valid() - ); - - mesh_tori_endp_addr_decode dest_addr_decode ( - .e_addr(dest_e_addr), - .ex(dest_x), - .ey(dest_y), - .el(), - .valid() - ); - - reg [NXw-1 : 0] x_offset; - reg [NYw-1 : 0] y_offset; - generate - if( IS_MESH | IS_LINE) begin : oneD - always_comb begin - x_offset = (src_x> dest_x)? src_x - dest_x : dest_x - src_x; - y_offset = (src_y> dest_y)? src_y - dest_y : dest_y - src_y; + mesh_tori_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); + mesh_tori_endp_addr_decode dst_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); + logic [NXw-1 : 0] x_offset; + logic [NYw-1 : 0] y_offset; + always_comb begin + x_offset = (src_x > dest_x) ? src_x - dest_x : dest_x - src_x; + y_offset = (src_y > dest_y) ? src_y - dest_y : dest_y - src_y; + end + /* verilator lint_off WIDTH */ + assign distance = x_offset+y_offset+1'b1; + /* verilator lint_on WIDTH */ +endmodule + +module ring_torus_distance_gen ( + src_e_addr, + dest_e_addr, + distance +); + import pronoc_pkg::*; + input [EAw-1 : 0] src_e_addr; + input [EAw-1 : 0] dest_e_addr; + output[DISTw-1: 0]distance; + wire [NXw-1 : 0]src_x,dest_x; + wire [NYw-1 : 0]src_y,dest_y; + mesh_tori_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); + mesh_tori_endp_addr_decode dest_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); + logic [NXw-1 : 0] x_offset; + logic [NYw-1 : 0] y_offset; + wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y; + /* verilator lint_off WIDTH */ + always_comb begin + x_offset= {NXw{1'b0}}; + y_offset= {NYw{1'b0}}; + //x_offset + if(same_x) x_offset= {NXw{1'b0}}; + else if(tranc_x_plus) begin + if(dest_x > src_x) x_offset= dest_x-src_x; + else x_offset= (NX-src_x)+dest_x; end - end else begin : twoD //torus ring - wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y; - /* verilator lint_off WIDTH */ - always_comb begin - x_offset= {NXw{1'b0}}; - y_offset= {NYw{1'b0}}; - //x_offset - if(same_x) x_offset= {NXw{1'b0}}; - else if(tranc_x_plus) begin - if(dest_x > src_x) x_offset= dest_x-src_x; - else x_offset= (NX-src_x)+dest_x; - end - else if(tranc_x_min) begin - if(dest_x < src_x) x_offset= src_x-dest_x; - else x_offset= src_x+(NX-dest_x); - end - //y_offset - if(same_y) y_offset= {NYw{1'b0}}; - else if(tranc_y_plus) begin - if(dest_y > src_y) y_offset= dest_y-src_y; - else y_offset= (NY-src_y)+dest_y; - end - else if(tranc_y_min) begin - if(dest_y < src_y) y_offset= src_y-dest_y; - else y_offset= src_y+(NY-dest_y); - end - end - /* verilator lint_on WIDTH */ - - tranc_dir #( - .NX(NX), - .NY(NY) - ) tranc_dir ( - .tranc_x_plus(tranc_x_plus), - .tranc_x_min(tranc_x_min), - .tranc_y_plus(tranc_y_plus), - .tranc_y_min(tranc_y_min), - .same_x(same_x), - .same_y(same_y), - .current_x(src_x), - .current_y(src_y), - .dest_x(dest_x), - .dest_y(dest_y) - ); - end - endgenerate + else if(tranc_x_min) begin + if(dest_x < src_x) x_offset= src_x-dest_x; + else x_offset= src_x+(NX-dest_x); + end + //y_offset + if(same_y) y_offset= {NYw{1'b0}}; + else if(tranc_y_plus) begin + if(dest_y > src_y) y_offset= dest_y-src_y; + else y_offset= (NY-src_y)+dest_y; + end + else if(tranc_y_min) begin + if(dest_y < src_y) y_offset= src_y-dest_y; + else y_offset= src_y+(NY-dest_y); + end + end + /* verilator lint_on WIDTH */ + tranc_dir #( + .NX(NX), + .NY(NY) + ) tranc_dir ( + .tranc_x_plus(tranc_x_plus), + .tranc_x_min(tranc_x_min), + .tranc_y_plus(tranc_y_plus), + .tranc_y_min(tranc_y_min), + .same_x(same_x), + .same_y(same_y), + .current_x(src_x), + .current_y(src_y), + .dest_x(dest_x), + .dest_y(dest_y) + ); /* verilator lint_off WIDTH */ assign distance = x_offset+y_offset+1'b1; /* verilator lint_on WIDTH */ @@ -1166,32 +1165,22 @@ module mesh_torus_destp_decoder #( wire [NL-1 : 0] endp_localp_onehot; reg [4:0] portout; - generate - if( ROUTE_TYPE == "DETERMINISTIC") begin :dtrmn - wire x,y,a,b; - assign {x,y,a,b} = dest_port_coded; - always_comb begin - case({a,b}) - 2'b10 : portout = {1'b0,~x,1'b0,x,1'b0}; - 2'b01 : portout = {~y,1'b0,y,1'b0,1'b0}; - 2'b00 : portout = 5'b00001; - 2'b11 : portout = {~y,1'b0,y,1'b0,1'b0}; //invalid condition in determinstic routing - endcase - end //always - end else begin : adpv - wire x,y,a,b; - assign {x,y,a,b} = dest_port_coded; - wire [PPSw-1:0] port_pre_sel_final; - assign port_pre_sel_final= (swap_port_presel)? ~port_pre_sel: port_pre_sel; - always_comb begin - case({a,b}) - 2'b10 : portout = {1'b0,~x,1'b0,x,1'b0}; - 2'b01 : portout = {~y,1'b0,y,1'b0,1'b0}; - 2'b11 : portout = (port_pre_sel_final[{x,y}])? {~y,1'b0,y,1'b0,1'b0} : {1'b0,~x,1'b0,x,1'b0}; - 2'b00 : portout = 5'b00001; - endcase - end //always - end + wire x,y,a,b; + assign {x,y,a,b} = dest_port_coded; + wire [PPSw-1:0] port_pre_sel_final; + assign port_pre_sel_final = + ( ROUTE_TYPE == "DETERMINISTIC") ? {PPSw{1'b1}}: + (swap_port_presel) ? ~port_pre_sel : port_pre_sel; + always_comb begin + case({a,b}) + 2'b10 : portout = {1'b0,~x,1'b0,x,1'b0}; + 2'b01 : portout = {~y,1'b0,y,1'b0,1'b0}; + 2'b00 : portout = 5'b00001; + 2'b11 : portout = (port_pre_sel_final[{x,y}]) ? {~y,1'b0,y,1'b0,1'b0} : {1'b0,~x,1'b0,x,1'b0}; + endcase + end //always + + generate if(NL==1) begin :slp if(SELF_LOOP_EN == 0) begin :nslp remove_sw_loc_one_hot #( diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 8da550b..7160d9f 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -34,7 +34,7 @@ module mesh_torus_noc_top ( router_event ); - import pronoc_pkg::*; + import pronoc_pkg::*; input clk,reset; //Endpoints ports @@ -72,14 +72,12 @@ module mesh_torus_noc_top ( .clk(clk), .reset(reset) ); - + localparam XFWD=(x < NX-1)? x+1 : 0; assign router_chan_in[x][FORWARD] = - (x < NX-1) ? router_chan_out[x+1][BACKWARD] : - (IS_LINE) ? is_grounded : router_chan_out[0][BACKWARD]; - - assign router_chan_in[x][BACKWARD] = - (x > 0) ? router_chan_out[x-1][FORWARD] : - (IS_LINE) ? is_grounded : router_chan_out[NX-1][FORWARD]; + (IS_LINE & (x == NX-1))? is_grounded : router_chan_out[XFWD][BACKWARD]; + localparam XBCK=(x > 0)? x-1 : NX-1; + assign router_chan_in[x][BACKWARD] = + (IS_LINE & (x==0))? is_grounded : router_chan_out[XBCK][FORWARD]; // connect other local ports for (l=0; lIT`^02^Ad){>FtVCIbG4>?)O>c{>>vw-J|-83#F`Yl>tCKhSLyU}KpCG0we zUv!L0+-u)P)o3tBX;EmWO4Jqv*-aYqV}yNdo-nRIO+UO?Mv}#%t*>8PWyn~|ekbm* zBe)jlRe$Q=qM2R9B85&HhA&k`W)Mh11AjoL{r>LGzea@NDW>011;6F&afgv#Z$yj# zntzA^|1it{Ll_H!dfF&ut{)boc-{uuR%hMzop5v2hl|`ArL+}z?LEK#a=-U&6SHRdo8SU*3H`t~N|AbU;}_`015m=Y{6OHq3R~)-l#@ z*QGM(v@&gRVNUDK zMUOuz{9&Tdsd^xuzlxukrjVhkW%{$n<^F>({BO3g>eG1P=PWk3A5I_U+7?bl7vpO0 zuPTt?SaWsWolFd4RZM#$bl;!U+RwPsx`a^VM5CAg{V593bb&}z(Px%?4vUbH*ITX| z++C?*9KYvRFlockx!{)ykIDKIeQXr`_vl4Rfl$!W0r#i$I5{PCt`Gi^luxF#zBOj! zB?ip#Kk2mZG>~jJkJ8a-A(F>%nj80wA(kc_MvkObnR36APe90$_y{(hOq#%kJh#DV zT%+nu$iw(Aojw%W^-dB2uGUr7RWfdj*DkS)_!5|Dik3Rn7%Wk7QxpfSIbM7($er|4 zJU(O(XYt(i$G}L8^PpVRx5hb`gTov~P%N;26H*e{G{|i9WL6DRY@)JQ`-iB*Yw4c&Rp;l>-yn4Fju?;5#RqS)(k7304b9%3j z`aVGSXL3%A<$asu9Om(|o#*y+@hi*&7hLtr6F&dV|Mlz_ z@=uCTOfsC>w{+jpxpJ_Q6e*b6O7KT>yw%f-v`C7`l}zGT2-#J&3+9y8PYF44?d}a2 z5TaE%ab4|BitXYs9&7&zRBRU@rF;EX@j!-vgRzK{>|YRpRHVm~7KEv=ylR{DtTBA& zbnT#!L4)oCJ?438^FVQ263)3_-@RB2n8S;j3Cn19S#3_1ndIF&!b8`|ZS`D(My-Qp z2wap%V;_IIpP%xJY$ru>mp8~jgp>W*q{B6LOkblwRw~cav8Qr9WKYJ;-#lz0SJaK; zP5Aq`|J*nnU+NAG1dB9QjaPVbw}K?Hypmq^JE|Uu-ZDCxdb=&}*e1@*m#m^;NuR{y zUtb}t`u})q@smROl<>=OQw^pCzGO^HVynfVqKi_Y$RN|&p|JLwsOCHJ%(U*#y>x{Z+Dpd&1K#}I``4+!6`?U71_OWAAhc->e(j+b*NP9pQ&T-B$M>c+`Y~NV_S)4PFh-8K0ZEn z_7aO9Z=XGT#t_%@oErtD$8ewS(D|TJD5)_%`=O{GJCS?*=z@o)j*1#fAj zA}F*<1Xy>Fg}E1WB_Kz>SJAF*j~z?Be`{O%mnUa46a@w4$6Lzj2KP-8Q@>~BdRrci zJ{u&vPmXdlSm#xa^T47L~AtRrdGWYU(#KA08P%7P*<1N7m!)Hd+ zzbyRRsbIIaL+D5OY0O%_;h_54+&&u%?V*D+>n`=deJ}66<$;YQ!S~HkIhL5#}tlA6+>P9C26^hg*7gH=;G56vz=|KH~v+>zFAFomn}>rmapBB)t=#s zFTgJwWYA@Rlc!RYA|lbu{uQB9eEfX8+~NmI)RIRdD=TZQ-DE|;)j0|l@o&4DpFe-L zhoa$82y%&uHRrMt-?0AtejGY@VXcME!*Mv*~1Q(#T-8w4EZF84a{Y+`LFT3Yd~eT4lq z`&zJiR#?57EsbDIbjP>&^Y7q@-=${F*nx$Y=v;BA#b^i`N{t00SXz z8(p^X9wp^fpXv2MoSJz3K`-mg<(kC2>!27KF2$bbQ+s*Hl4s8{TZ?a7((Oli^jh<( ze&Sl}<7`dkx1WNa^1j%vRZ=~E9UmXx)Fc|H3yDDYRdFrPdROipmDuy{_hZGn5+}bc znte~xA6dv57$mnwW178u`7%5_JSxk&+69pfPC)5^i0+PM<-d*MGLt%|XHTB=e$lTq z@jup1>|5E*LeicnHI9yoDk?6%GLD4Og}{KJ9jQt8;DOc8Py64nI4MLt>{fp!NnGxQ zW>uYcelo}y9UYyTn(FO+5=cS^D++>?S!%5^uwNTU%kbGKWG$^*O0r7VuXD;AvpM#B zipW4uFOxkCKXulKe_N%M35u*awY1%Z(;)gPDk^eva*nE^qN0+M$zCnDrnsyhpJ%{k z4NBZxLY7hc{LPGGR68%<3bNo&aThkWw=ZeMx(l1u_B=1%+IGgFw%@W+j}59O)HhjK z*@q7wuB@zRYir}a>R5McFefi=z$a=?Xc7IJoZSgDOrX?&k$LSYKa1HZ}%1 z$<56TFJxvelz&GBb?xcXrB`iOc%RIFmy-~_iy;A)=D#IT31o=>)zFs@mn~HAV~f@^oe~hDknW4*Id^I z#C%V*w6tX80Y;AWrjEx%FZWb98)!W@I=$hYeIo%p~)BBNC zz+vXElOUDv)}zF}B9*vAH$Q9@G*@p)XSYyT(V9)*d@QKUaa| zHfi>mZ}E@HI@+8lgPNn6r>v-=a{O=or{&?pL?f4;hlzDYrPKjuizT&lK6~wGt}ZS+ zjk_(8=+ySY^TbKYc~H{6eUnP;dx!xW80PusLi$b+Y}bwje}{t~d3k zbG{uN9h?J`p&=onPu6rt$n&R zc{uAiZ$DkrZ^rfJKF?|oV}`P#;_&A2HOtGrh4y<4%4g@BWsGX+TR*rBTKD#xQu
p*2B9Oa_e2N82`Gnz@el9MT#%POscdYIBi;6Dw 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 vMnP0E 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 T`NLQLG5~?6tDnm{r-UW|NmVo* literal 137543 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 DP0>y;pWBsQn(jsBZ~j&m*o-z415l-5G7wuOEp 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 { + '"custom1"' => { + 'T1' => 16, + 'T2' => 16, + 'ROUTE_NAME' => '"custom"', + 'T3' => 5, + 'ROUTER_Ps' => { + '3' => 4, + '4' => 8, + '5' => 4 + }, 'er_addr' => [ + 0, + 1, + 2, + 3, 4, 5, 6, @@ -19,31 +32,18 @@ $Topology = { 9, 10, 11, - 0, - 1, - 2, - 3, 12, 13, 14, 15 - ], + ] + }, + '"mesh4x4"' => { + 'T3' => 5, 'ROUTER_Ps' => { '5' => 16 }, - 'T1' => 16, - 'T2' => 16, - 'ROUTE_NAME' => '"custom","m4"', - 'T3' => 5 - }, - '"custom1"' => { - 'ROUTE_NAME' => '"custom"', - 'T3' => 5, 'er_addr' => [ - 0, - 1, - 2, - 3, 4, 5, 6, @@ -52,17 +52,17 @@ $Topology = { 9, 10, 11, + 0, + 1, + 2, + 3, 12, 13, 14, 15 ], - 'ROUTER_Ps' => { - '3' => 4, - '4' => 8, - '5' => 4 - }, 'T2' => 16, + 'ROUTE_NAME' => '"custom","m4"', 'T1' => 16 } }; From 101dc9db3c587e8cf2af531d11d319fda9c95f50 Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 16 Jun 2025 19:01:38 +0200 Subject: [PATCH 050/107] add lint summary to questasim intigration test --- .../Questa_lint/golden_ref/report.txt | 25 ++++++++++++ mpsoc/Integration_test/Questa_lint/run.sh | 39 ++++++++++++++----- 2 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 mpsoc/Integration_test/Questa_lint/golden_ref/report.txt diff --git a/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt new file mode 100644 index 0000000..8bfbc1a --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt @@ -0,0 +1,25 @@ +Configuration | # Warnings | # Errors | +bintree_k3_L3_st | 4 | 1 | +custom1_topology | 0 | 1 | +Fattree_k3_L3_st | 0 | 1 | +fmesh_1x1_openpiton | 6 | 0 | +fmesh_2x2_openpiton | 8 | 0 | +fmesh_8x8_2cycle_xy | 20 | 1 | +fmesh_8x8_openpiton | 20 | 1 | +line4_smart3 | 0 | 0 | +mesh_2x2_openpiton | 24 | 0 | +mesh_3x3_v2_ssa | 46 | 1 | +mesh_4x4_2cycle_mcast_f | 86 | 1 | +mesh_4x4_smart3 | 12 | 1 | +mesh_4x4_v1_B15 | 76 | 1 | +mesh_4x4x3_2cycle_xy | 76 | 1 | +mesh_8x8_2cycle_adaptive | 282 | 1 | +mesh_8x8_2cycle_west_first | 276 | 1 | +mesh_8x8_2cycle_xy | 276 | 1 | +mesh_8x8_4vc_4c | 276 | 1 | +mesh_8x8_b2 | 276 | 1 | +mesh_8x8_sbp6_xy | 276 | 1 | +mesh_8x8_single_flit | 277 | 1 | +mesh_8x8_ssa_xy | 276 | 1 | +star_6 | 0 | 0 | +torus_8x8_2cycle_xy | 274 | 1 | diff --git a/mpsoc/Integration_test/Questa_lint/run.sh b/mpsoc/Integration_test/Questa_lint/run.sh index bd8b0bc..db49d3b 100644 --- a/mpsoc/Integration_test/Questa_lint/run.sh +++ b/mpsoc/Integration_test/Questa_lint/run.sh @@ -10,11 +10,17 @@ conf_dir="${SCRPT_DIR_PATH}/configurations" work="${SCRPT_DIR_PATH}/work" file_list_f="${SCRPT_DIR_PATH}/src/file_list.f" lint_file="${SCRPT_DIR_PATH}/src/lint.tcl" +report_file="${log_dir}/report.txt" mkdir -p $work mkdir -p $log_dir +rm -rf $report_file +printf "%-30s | %-10s | %-10s |\n" "Configuration" "# Warnings" "# Errors" >> "$report_file" + + questa_lint () { + set -e # Exit on any command failure conf=$1 conf_file="${conf_dir}/$conf" log_file="${log_dir}/${conf}.log" @@ -33,7 +39,16 @@ questa_lint () { vlib work # Lint the design vlog -sv -lint -f ${file_list_f} - vsim -c work.noc_top -do "quit" + vsim -suppress vopt-14408 -c work.noc_top -do "quit" +} + +report_total_errors_warnings () { + conf="$1" + conf_file="${conf_dir}/${conf}" + log_file="${log_dir}/${conf}.log" + warnings=$(grep '\*\* Warning' "$log_file" | wc -l) + errors=$(grep '\*\*\ Error' "$log_file" | wc -l) + printf "%-30s | %-10s | %-10s |\n" "$conf" "$warnings" "$errors" >> "$report_file" } for f in "$conf_dir"/*; do @@ -41,14 +56,20 @@ for f in "$conf_dir"/*; do conf=$(basename "$f") log_file="${log_dir}/${conf}.log" echo "▶️ Compiling configuration: $conf" - questa_lint "$conf" |& tee $log_file - if [[ $? -ne 0 ]]; then - echo "❌ Compilation failed for $conf (check $log_file)" - rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v - exit 1 - else + # questa_lint "$conf" |& tee $log_file + #if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + # echo "❌ Compilation failed for $conf (check $log_file)" + # rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + # exit 1 + #else echo "✅ Compilation successful for $conf" rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v - fi - + report_total_errors_warnings "$conf" + #fi done + +echo "Report saved in $report_file" +echo "Summary:" +echo "-------------------------------|------------|------------|" +cat $report_file + From 5ceea28521e46b08b85c818106c7dbaaca25e180 Mon Sep 17 00:00:00 2001 From: amonemi Date: Tue, 17 Jun 2025 15:07:56 +0200 Subject: [PATCH 051/107] remove most of Questasim linting warnings --- mpsoc/Integration_test/Altera/src/compare.pl | 7 +-- .../Questa_lint/golden_ref/report.txt | 44 +++++++-------- mpsoc/Integration_test/Questa_lint/run.sh | 21 +++++--- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 54 +++++++++---------- mpsoc/rtl/src_noc/router_top.sv | 8 +-- 5 files changed, 71 insertions(+), 63 deletions(-) diff --git a/mpsoc/Integration_test/Altera/src/compare.pl b/mpsoc/Integration_test/Altera/src/compare.pl index 3ac795a..4cc0f06 100644 --- a/mpsoc/Integration_test/Altera/src/compare.pl +++ b/mpsoc/Integration_test/Altera/src/compare.pl @@ -46,11 +46,12 @@ sub parse_file { while (<$fh>) { chomp; - next if /^\s*$/; - if (/^File\|/) { + next if /^\s*$/; #skip empty line + next if /^---$/; #skip separtion lines + if (scalar @fields ==0) { s/^\s+|\s+$//g; @fields = split /\|/; - shift @fields; # remove "File" + shift @fields; # remove first column name s/^\s+|\s+$//g for @fields; next; } diff --git a/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt index 8bfbc1a..a713eb9 100644 --- a/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt +++ b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt @@ -1,25 +1,25 @@ Configuration | # Warnings | # Errors | -bintree_k3_L3_st | 4 | 1 | -custom1_topology | 0 | 1 | -Fattree_k3_L3_st | 0 | 1 | -fmesh_1x1_openpiton | 6 | 0 | -fmesh_2x2_openpiton | 8 | 0 | -fmesh_8x8_2cycle_xy | 20 | 1 | -fmesh_8x8_openpiton | 20 | 1 | +bintree_k3_L3_st | 3 | 0 | +custom1_topology | 0 | 0 | +Fattree_k3_L3_st | 0 | 0 | +fmesh_1x1_openpiton | 2 | 0 | +fmesh_2x2_openpiton | 2 | 0 | +fmesh_8x8_2cycle_xy | 2 | 0 | +fmesh_8x8_openpiton | 2 | 0 | line4_smart3 | 0 | 0 | -mesh_2x2_openpiton | 24 | 0 | -mesh_3x3_v2_ssa | 46 | 1 | -mesh_4x4_2cycle_mcast_f | 86 | 1 | -mesh_4x4_smart3 | 12 | 1 | -mesh_4x4_v1_B15 | 76 | 1 | -mesh_4x4x3_2cycle_xy | 76 | 1 | -mesh_8x8_2cycle_adaptive | 282 | 1 | -mesh_8x8_2cycle_west_first | 276 | 1 | -mesh_8x8_2cycle_xy | 276 | 1 | -mesh_8x8_4vc_4c | 276 | 1 | -mesh_8x8_b2 | 276 | 1 | -mesh_8x8_sbp6_xy | 276 | 1 | -mesh_8x8_single_flit | 277 | 1 | -mesh_8x8_ssa_xy | 276 | 1 | +mesh_2x2_openpiton | 2 | 0 | +mesh_3x3_v2_ssa | 2 | 0 | +mesh_4x4_2cycle_mcast_f | 12 | 0 | +mesh_4x4_smart3 | 2 | 0 | +mesh_4x4_v1_B15 | 2 | 0 | +mesh_4x4x3_2cycle_xy | 2 | 0 | +mesh_8x8_2cycle_adaptive | 8 | 0 | +mesh_8x8_2cycle_west_first | 2 | 0 | +mesh_8x8_2cycle_xy | 2 | 0 | +mesh_8x8_4vc_4c | 2 | 0 | +mesh_8x8_b2 | 2 | 0 | +mesh_8x8_sbp6_xy | 2 | 0 | +mesh_8x8_single_flit | 3 | 0 | +mesh_8x8_ssa_xy | 2 | 0 | star_6 | 0 | 0 | -torus_8x8_2cycle_xy | 274 | 1 | +torus_8x8_2cycle_xy | 0 | 0 | diff --git a/mpsoc/Integration_test/Questa_lint/run.sh b/mpsoc/Integration_test/Questa_lint/run.sh index db49d3b..4dc62a6 100644 --- a/mpsoc/Integration_test/Questa_lint/run.sh +++ b/mpsoc/Integration_test/Questa_lint/run.sh @@ -39,7 +39,7 @@ questa_lint () { vlib work # Lint the design vlog -sv -lint -f ${file_list_f} - vsim -suppress vopt-14408 -c work.noc_top -do "quit" + vsim -suppress vopt-14408,vsim-16154 -c work.noc_top -do "quit" } report_total_errors_warnings () { @@ -51,21 +51,22 @@ report_total_errors_warnings () { printf "%-30s | %-10s | %-10s |\n" "$conf" "$warnings" "$errors" >> "$report_file" } + for f in "$conf_dir"/*; do [[ -d "$f" ]] && continue conf=$(basename "$f") log_file="${log_dir}/${conf}.log" echo "▶️ Compiling configuration: $conf" - # questa_lint "$conf" |& tee $log_file - #if [[ ${PIPESTATUS[0]} -ne 0 ]]; then - # echo "❌ Compilation failed for $conf (check $log_file)" - # rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v - # exit 1 - #else + questa_lint "$conf" |& tee $log_file + if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + echo "❌ Compilation failed for $conf (check $log_file)" + rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + exit 1 + else echo "✅ Compilation successful for $conf" rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v report_total_errors_warnings "$conf" - #fi + fi done echo "Report saved in $report_file" @@ -73,3 +74,7 @@ echo "Summary:" echo "-------------------------------|------------|------------|" cat $report_file +echo "Comparing with golden reference..." +# Compare the results with the golden reference report +perl ${SCRPT_DIR_PATH}/../Altera/src/compare.pl $report_file ${SCRPT_DIR_PATH}/golden_ref/report.txt +echo "All configurations processed. Results are in $report_file \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 7160d9f..202dc78 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -66,8 +66,8 @@ module mesh_torus_noc_top ( .P (MAX_P) ) the_router ( .router_config_in(router_config_in[RID]), - .chan_in(router_chan_in [RID]), - .chan_out(router_chan_out[RID]), + .chan_in(router_chan_in [RID]), + .chan_out(router_chan_out[RID]), .router_event(router_event[RID]), .clk(clk), .reset(reset) @@ -86,7 +86,7 @@ module mesh_torus_noc_top ( assign router_chan_in[x][LOCALP]= chan_in_all [ENDPID]; assign chan_out_all [ENDPID] = router_chan_out[x][LOCALP]; end// locals - end//x + end//x end else begin :mesh_torus for (y=0; y 0) ? fmesh_router_id(x, y-1) : fmesh_router_id(x, NY-1); assign router_chan_in[fmesh_router_id(x, y)][NORTH] = - (y > 0 ) ? router_chan_out[fmesh_router_id(x, y-1)][SOUTH] : //not_first_y - (IS_MESH) ? is_grounded : //first_y_mesh - (IS_TORUS)? router_chan_out[fmesh_router_id(x, NY-1)][SOUTH] : //first_y_torus - chan_in_all[NORTH_ID]; //first_y_fmesh + ((y > 0) | IS_TORUS ) ? router_chan_out[NORTH_RID][SOUTH] : //not_first_y + (IS_MESH) ? is_grounded : chan_in_all[NORTH_ID]; //first_y_fmesh + + localparam WEST_RID = (x > 0) ? fmesh_router_id(x-1, y) : fmesh_router_id(NX-1, y); //not_first_x assign router_chan_in[fmesh_router_id(x, y)][WEST] = - (x > 0) ? router_chan_out[fmesh_router_id(x-1, y)][EAST] : //not_first_x - (IS_MESH) ? is_grounded : //first_x_mesh - (IS_TORUS)? router_chan_out[fmesh_router_id(NX-1, y)][EAST] : //first_x_torus - chan_in_all[WEST_ID]; //first_x_fmesh + ((x > 0) | IS_TORUS) ? router_chan_out[WEST_RID][EAST] : //not_first_x + (IS_MESH) ? is_grounded : chan_in_all[WEST_ID]; //first_x_fmesh + + localparam SOUTH_RID = (y < NY-1) ? fmesh_router_id(x, y+1) : fmesh_router_id(x, 0); assign router_chan_in[fmesh_router_id(x, y)][SOUTH] = - (y < NY-1)? router_chan_out[fmesh_router_id(x, y+1)][NORTH] : //not_last_y - (IS_MESH)? is_grounded : //last_y_mesh - (IS_TORUS)? router_chan_out[fmesh_router_id(x, 0)][NORTH] : //last_y_torus - chan_in_all[SOUTH_ID]; //last_y_fmesh - if(IS_FMESH) begin :fmesh //connect to endpoints + (y < NY-1 || IS_TORUS)? router_chan_out[SOUTH_RID][NORTH] : //not_last_y + (IS_MESH)? is_grounded : chan_in_all[SOUTH_ID]; //last_y_fmesh + + if(IS_FMESH) begin : fmesh //connect to endpoints if(x == NX-1) assign chan_out_all [EAST_ID] = router_chan_out [fmesh_router_id(x,y)][EAST]; if(y ==0 ) assign chan_out_all [NORTH_ID] = router_chan_out [fmesh_router_id(x,y)][NORTH]; if (x ==0 ) assign chan_out_all [WEST_ID] = router_chan_out[fmesh_router_id(x, y)][WEST]; @@ -152,12 +152,12 @@ module mesh_torus_noc_top ( localparam LOCALP = (l==0) ? l : l + R2R_CHANELS_MESH_TORI; // first local port is connected to router port 0. The rest are connected at the end localparam ENDP_ADDR = {l,R_ADDR[RAw-1: 0]}; assign router_chan_in [fmesh_router_id(x,y)][LOCALP] = chan_in_all [ENDPID]; - assign chan_out_all [ENDPID] = router_chan_out [fmesh_router_id(x,y)][LOCALP]; + assign chan_out_all [ENDPID] = router_chan_out [fmesh_router_id(x,y)][LOCALP]; assign router_config_in[RID].endp_addrs[(l+1)*EAw -1 : l*EAw] = ENDP_ADDR[EAw-1:0]; assign router_config_in[RID].endp_ids[(l+1)*NEw -1 : l*NEw] =ENDPID[NEw-1:0]; - end// locals + end// locals end //y end //x - end// mesh_torus + end// mesh_torus endgenerate endmodule diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index b927f6e..dd242cd 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -248,9 +248,11 @@ module router_top #( for(int k=0;k Date: Tue, 17 Jun 2025 18:54:04 +0200 Subject: [PATCH 052/107] add hetrovc configuration to Questasim lint --- .../configurations/mesh_8x8_4vc_hetero1 | 77 +++++++++++++++++++ .../configurations/mesh_8x8_4vc_hetero2 | 77 +++++++++++++++++++ mpsoc/Integration_test/Questa_lint/run.sh | 5 +- mpsoc/rtl/src_noc/flit_buffer.sv | 61 ++++++++------- 4 files changed, 192 insertions(+), 28 deletions(-) create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 new file mode 100644 index 0000000..5196912 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 @@ -0,0 +1,77 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "ESCAP_VC_MASK" => "4'd1", + "V" => 4, + "HETERO_VC"=> "1", + "MAX_ROUTER"=>"64", + "MAX_PORT"=>"1", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{ + //P0 P1 P2 P3 P4 + '{1}, // R0 + '{2}, // R1 + '{3}, // R2 + '{4}, // R3 + '{1}, // R4 + '{2}, // R5 + '{3}, // R6 + '{4}, // R7 + '{1}, // R8 + '{2}, // R9 + '{3}, // R10 + '{4}, // R11 + '{1}, // R12 + '{2}, // R13 + '{3}, // R14 + '{1}, // R15 + '{2}, // R16 + '{3}, // R17 + '{4}, // R18 + '{1}, // R19 + '{2}, // R20 + '{3}, // R21 + '{4}, // R22 + '{1}, // R23 + '{2}, // R24 + '{3}, // R25 + '{4}, // R26 + '{1}, // R27 + '{2}, // R28 + '{3}, // R29 + '{1}, // R30 + '{2}, // R31 + '{3}, // R32 + '{4}, // R33 + '{1}, // R34 + '{2}, // R35 + '{3}, // R36 + '{4}, // R37 + '{1}, // R38 + '{2}, // R39 + '{3}, // R40 + '{4}, // R41 + '{1}, // R42 + '{2}, // R43 + '{3}, // R44 + '{1}, // R45 + '{2}, // R46 + '{3}, // R47 + '{4}, // R48 + '{1}, // R49 + '{2}, // R50 + '{3}, // R51 + '{4}, // R52 + '{1}, // R53 + '{2}, // R54 + '{3}, // R55 + '{4}, // R56 + '{1}, // R57 + '{2}, // R58 + '{3}, // R59 + '{1}, // R60 + '{2}, // R61 + '{3}, // R62 + '{4} // R63 + }", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 new file mode 100644 index 0000000..38c6d2b --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 @@ -0,0 +1,77 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "V" => 4, + "ESCAP_VC_MASK" => "4'd1", + "HETERO_VC"=> "2", + "MAX_ROUTER"=>"64", + "MAX_PORT"=>"5", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{ + //P0 P1 P2 P3 P4 + '{1, 2, 3, 4, 1}, // R0 + '{2, 3, 4, 1, 2}, // R1 + '{3, 4, 1, 2, 3}, // R2 + '{4, 1, 2, 3, 4}, // R3 + '{1, 2, 3, 4, 1}, // R4 + '{2, 3, 4, 1, 2}, // R5 + '{3, 4, 1, 2, 3}, // R6 + '{4, 1, 2, 3, 4}, // R7 + '{1, 2, 3, 4, 1}, // R8 + '{2, 3, 4, 1, 2}, // R9 + '{3, 4, 1, 2, 3}, // R10 + '{4, 1, 2, 3, 4}, // R11 + '{1, 2, 3, 4, 1}, // R12 + '{2, 3, 4, 1, 2}, // R13 + '{3, 4, 1, 2, 3}, // R14 + '{1, 2, 3, 4, 1}, // R15 + '{2, 3, 4, 1, 2}, // R16 + '{3, 4, 1, 2, 3}, // R17 + '{4, 1, 2, 3, 4}, // R18 + '{1, 2, 3, 4, 1}, // R19 + '{2, 3, 4, 1, 2}, // R20 + '{3, 4, 1, 2, 3}, // R21 + '{4, 1, 2, 3, 4}, // R22 + '{1, 2, 3, 4, 1}, // R23 + '{2, 3, 4, 1, 2}, // R24 + '{3, 4, 1, 2, 3}, // R25 + '{4, 1, 2, 3, 4}, // R26 + '{1, 2, 3, 4, 1}, // R27 + '{2, 3, 4, 1, 2}, // R28 + '{3, 4, 1, 2, 3}, // R29 + '{1, 2, 3, 4, 1}, // R30 + '{2, 3, 4, 1, 2}, // R31 + '{3, 4, 1, 2, 3}, // R32 + '{4, 1, 2, 3, 4}, // R33 + '{1, 2, 3, 4, 1}, // R34 + '{2, 3, 4, 1, 2}, // R35 + '{3, 4, 1, 2, 3}, // R36 + '{4, 1, 2, 3, 4}, // R37 + '{1, 2, 3, 4, 1}, // R38 + '{2, 3, 4, 1, 2}, // R39 + '{3, 4, 1, 2, 3}, // R40 + '{4, 1, 2, 3, 4}, // R41 + '{1, 2, 3, 4, 1}, // R42 + '{2, 3, 4, 1, 2}, // R43 + '{3, 4, 1, 2, 3}, // R44 + '{1, 2, 3, 4, 1}, // R45 + '{2, 3, 4, 1, 2}, // R46 + '{3, 4, 1, 2, 3}, // R47 + '{4, 1, 2, 3, 4}, // R48 + '{1, 2, 3, 4, 1}, // R49 + '{2, 3, 4, 1, 2}, // R50 + '{3, 4, 1, 2, 3}, // R51 + '{4, 1, 2, 3, 4}, // R52 + '{1, 2, 3, 4, 1}, // R53 + '{2, 3, 4, 1, 2}, // R54 + '{3, 4, 1, 2, 3}, // R55 + '{4, 1, 2, 3, 4}, // R56 + '{1, 2, 3, 4, 1}, // R57 + '{2, 3, 4, 1, 2}, // R58 + '{3, 4, 1, 2, 3}, // R59 + '{1, 2, 3, 4, 1}, // R60 + '{2, 3, 4, 1, 2}, // R61 + '{3, 4, 1, 2, 3}, // R62 + '{4, 1, 2, 3, 4} // R63 + }", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/run.sh b/mpsoc/Integration_test/Questa_lint/run.sh index 4dc62a6..7d295c5 100644 --- a/mpsoc/Integration_test/Questa_lint/run.sh +++ b/mpsoc/Integration_test/Questa_lint/run.sh @@ -17,7 +17,8 @@ mkdir -p $log_dir rm -rf $report_file printf "%-30s | %-10s | %-10s |\n" "Configuration" "# Warnings" "# Errors" >> "$report_file" - +# Source the environment variables +# conf_dir="${SCRPT_DIR_PATH}/conf_small" questa_lint () { set -e # Exit on any command failure @@ -76,5 +77,5 @@ cat $report_file echo "Comparing with golden reference..." # Compare the results with the golden reference report -perl ${SCRPT_DIR_PATH}/../Altera/src/compare.pl $report_file ${SCRPT_DIR_PATH}/golden_ref/report.txt +perl ${SCRPT_DIR_PATH}/../Altera/src/compare.pl ${SCRPT_DIR_PATH}/golden_ref/report.txt $report_file echo "All configurations processed. Results are in $report_file \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index ae754f4..1b7d864 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -92,12 +92,12 @@ module flit_buffer wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_din; wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_dout; - wire [V-1 : 0] wr; - wire [V-1 : 0] rd; - wire [DEPTHw-1 : 0] depth [V-1 :0]; - reg [DEPTHw-1 : 0] depth_next [V-1 :0]; - wire [DEPTHw-1 : 0] sub_depth [V-1 :0]; - reg [DEPTHw-1 : 0] sub_depth_next [V-1 :0]; + wire [V-1 : 0] wr; + wire [V-1 : 0] rd; + wire [DEPTHw-1 : 0] depth [V-1 :0]; + reg [DEPTHw-1 : 0] depth_next [V-1 :0]; + wire [DEPTHw-1 : 0] sub_depth [V-1 :0]; + logic [DEPTHw-1 : 0] sub_depth_next [V-1 :0]; reg [B-1 : 0] tail_fifo [V-1 : 0]; wire [1 : 0] flgs_in, flgs_out; @@ -128,6 +128,34 @@ module flit_buffer assign dout = {2'b11,{V{1'bX}},fifo_ram_dout}; end + always_comb begin + for(int k=0;k 0); end else begin : unicast assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = rd_ptr[i]; @@ -239,13 +261,8 @@ module flit_buffer pronoc_register #(.W(Bw )) reg2 (.D_in(wr_ptr_next[i]), .Q_out(wr_ptr[i]), .reset(reset), .clk(clk)); pronoc_register #(.W(DEPTHw)) reg3 (.D_in(depth_next[i] ), .Q_out(depth [i]), .reset(reset), .clk(clk)); - + if (~IS_UNICAST) begin :multicast - always_comb begin - sub_rd_ptr_next[i] = sub_rd_ptr[i]; - if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i]; - else if(sub_rd[i]) sub_rd_ptr_next[i] = sub_rd_ptr[i]+ 1'h1; - end assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][sub_rd_ptr[i]] : 1'b1; end else begin : unicast assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][rd_ptr[i]] : 1'b1; @@ -271,14 +288,6 @@ module flit_buffer end if (~IS_UNICAST) begin :multicast - always_comb begin - sub_rd_ptr_next[i] = sub_rd_ptr[i]; - if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i]; - /* verilator lint_off WIDTH */ - else if(sub_rd[i]) sub_rd_ptr_next[i] = (sub_rd_ptr[i]==(B*(i+1))-1)? (B*i) : sub_rd_ptr [i]+ 1'h1; - /* verilator lint_on WIDTH */ - end - /* verilator lint_off WIDTH */ assign ptr_tmp [i] = sub_rd_ptr[i]-(B*i); assign flit_is_tail[i] = (IS_MULTI_FLIT)? tail_fifo[i][ptr_tmp [i]] :1'b1; From 0a9944e8fa362d56edcd522064afbefb0fbc2ac3 Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 18 Jun 2025 13:15:39 +0200 Subject: [PATCH 053/107] remove questa linting warning --- .../Questa_lint/golden_ref/report.txt | 6 ++- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 39 ++++++++++++++++- mpsoc/rtl/src_noc/output_ports.sv | 42 +++++++------------ 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt index a713eb9..04f6ee9 100644 --- a/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt +++ b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt @@ -9,14 +9,16 @@ fmesh_8x8_openpiton | 2 | 0 | line4_smart3 | 0 | 0 | mesh_2x2_openpiton | 2 | 0 | mesh_3x3_v2_ssa | 2 | 0 | -mesh_4x4_2cycle_mcast_f | 12 | 0 | +mesh_4x4_2cycle_mcast_f | 2 | 0 | mesh_4x4_smart3 | 2 | 0 | mesh_4x4_v1_B15 | 2 | 0 | mesh_4x4x3_2cycle_xy | 2 | 0 | -mesh_8x8_2cycle_adaptive | 8 | 0 | +mesh_8x8_2cycle_adaptive | 2 | 0 | mesh_8x8_2cycle_west_first | 2 | 0 | mesh_8x8_2cycle_xy | 2 | 0 | mesh_8x8_4vc_4c | 2 | 0 | +mesh_8x8_4vc_hetero1 | 2 | 0 | +mesh_8x8_4vc_hetero2 | 2 | 0 | mesh_8x8_b2 | 2 | 0 | mesh_8x8_sbp6_xy | 2 | 0 | mesh_8x8_single_flit | 3 | 0 | diff --git a/mpsoc/rtl/src_noc/mesh_torus_routting.sv b/mpsoc/rtl/src_noc/mesh_torus_routting.sv index db0506b..bb9fee7 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_routting.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_routting.sv @@ -869,4 +869,41 @@ module mesh_tori_decode_dstport ( 2'b00 : dstport_one_hot = 5'b00001; endcase end //always -endmodule \ No newline at end of file +endmodule + +module mesh_tori_full_adapt_ovc_avail #( + parameter P = 4 +) ( + reset,clk, + empty_all_next, + full_all_next, + nearly_full_all_next, + ovc_status, + ovc_avalable_all +); + import pronoc_pkg::*; + localparam PV = P * V; + localparam [V-1 : 0] ADAPTIVE_VC_MASK = ~ ESCAP_VC_MASK; + input [PV-1 : 0] empty_all_next, full_all_next, nearly_full_all_next,ovc_status; + output [PV-1 : 0]ovc_avalable_all; + input reset,clk; + reg [PV-1 : 0] full_adaptive_ovc_mask,full_adaptive_ovc_mask_next; + always_comb begin + for( int k=0; k Date: Wed, 18 Jun 2025 18:51:23 +0200 Subject: [PATCH 054/107] remove more Questasim linting warnings --- .../Questa_lint/configurations/line_4_v1_B15 | 14 +++++ .../configurations/line_8_single_flit | 9 +++ .../configurations/mesh_4x4_LB5_B4 | 12 ++++ .../configurations/mesh_4x4_selflp_mcast_f | 9 +++ .../configurations/mesh_4x4x2_bcast_f | 10 ++++ .../configurations/mesh_4x4x2_bcast_p | 10 ++++ .../configurations/mesh_4x4x2_mcast_p | 10 ++++ .../configurations/mesh_4x4x3_vc_nonspec | 10 ++++ .../configurations/mesh_4x4x3_vc_spec1 | 10 ++++ .../configurations/mesh_4x4x3_vc_spec2 | 10 ++++ .../Questa_lint/configurations/mesh_8x8_4vc | 7 +++ .../configurations/ring_8x8_2cycle_xy | 8 +++ .../configurations/star6_2cycle_mcast_par | 11 ++++ .../Questa_lint/golden_ref/report.txt | 55 ++++++++++++------- mpsoc/Integration_test/Questa_lint/run.sh | 43 ++++++++++++--- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 2 +- mpsoc/rtl/src_noc/multicast.sv | 17 ++---- 17 files changed, 206 insertions(+), 41 deletions(-) create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/line_4_v1_B15 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/line_8_single_flit create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_LB5_B4 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_selflp_mcast_f create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_f create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_p create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_mcast_p create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/star6_2cycle_mcast_par diff --git a/mpsoc/Integration_test/Questa_lint/configurations/line_4_v1_B15 b/mpsoc/Integration_test/Questa_lint/configurations/line_4_v1_B15 new file mode 100644 index 0000000..5d00709 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/line_4_v1_B15 @@ -0,0 +1,14 @@ +$model = bless( { + 'noc_param'=> { + TOPOLOGY=>"\"LINE\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "15", + "LB" => "15", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "0", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/line_8_single_flit b/mpsoc/Integration_test/Questa_lint/configurations/line_8_single_flit new file mode 100644 index 0000000..a73600b --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/line_8_single_flit @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + TOPOLOGY=>"\"LINE\"", + "B" => "5", + "LB" => "5", + "MIN_PCK_SIZE" => "1", + "PCK_TYPE" => " \"SINGLE_FLIT\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_LB5_B4 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_LB5_B4 new file mode 100644 index 0000000..50ac90c --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_LB5_B4 @@ -0,0 +1,12 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "B" => "4", + "LB" => "5", + "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", + "MCAST_ENDP_LIST" => "16'b110011000111101", + "Fpay" => "64", + "SELF_LOOP_EN" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_selflp_mcast_f b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_selflp_mcast_f new file mode 100644 index 0000000..5c5852e --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4_selflp_mcast_f @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64", + "SELF_LOOP_EN" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_f b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_f new file mode 100644 index 0000000..dc24a2f --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_f @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "2", + "CAST_TYPE" => "\"BROADCAST_FULL\"", + "MCAST_ENDP_LIST" => "32'b1100110001111", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_p b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_p new file mode 100644 index 0000000..23c4749 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_bcast_p @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "2", + "CAST_TYPE" => "\"BROADCAST_PARTIAL\"", + "MCAST_ENDP_LIST" => "32'b1100110001111", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_mcast_p b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_mcast_p new file mode 100644 index 0000000..ad2854b --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x2_mcast_p @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "2", + "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", + "MCAST_ENDP_LIST" => "32'b1100110001111", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec new file mode 100644 index 0000000..719d562 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + "COMBINATION_TYPE" => "\"COMB_NONSPEC\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 new file mode 100644 index 0000000..9d89499 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + "COMBINATION_TYPE" => "\"COMB_SPEC1\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 new file mode 100644 index 0000000..aea90d2 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + "COMBINATION_TYPE" => "\"COMB_SPEC2\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc new file mode 100644 index 0000000..248f91c --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "ESCAP_VC_MASK" => "4'd1", + "V" => 4, + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy new file mode 100644 index 0000000..f75ef5b --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy @@ -0,0 +1,8 @@ +$model = bless( { + 'compile' => "verilate_mesh.sh", + 'noc_param'=> { + TOPOLOGY=>"\"RING\"", + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_XY\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/star6_2cycle_mcast_par b/mpsoc/Integration_test/Questa_lint/configurations/star6_2cycle_mcast_par new file mode 100644 index 0000000..3bf044e --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/star6_2cycle_mcast_par @@ -0,0 +1,11 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=>"\"STAR\"", + "ROUTE_NAME" =>"\"UNKNOWN\"", + "T1" => "6", + "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", + "Fpay" => "32", + "MCAST_ENDP_LIST" => "'b001011", + "SELF_LOOP_EN" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt index 04f6ee9..35e9951 100644 --- a/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt +++ b/mpsoc/Integration_test/Questa_lint/golden_ref/report.txt @@ -1,27 +1,40 @@ Configuration | # Warnings | # Errors | -bintree_k3_L3_st | 3 | 0 | +bintree_k3_L3_st | 0 | 0 | custom1_topology | 0 | 0 | Fattree_k3_L3_st | 0 | 0 | -fmesh_1x1_openpiton | 2 | 0 | -fmesh_2x2_openpiton | 2 | 0 | -fmesh_8x8_2cycle_xy | 2 | 0 | -fmesh_8x8_openpiton | 2 | 0 | +fmesh_1x1_openpiton | 0 | 0 | +fmesh_2x2_openpiton | 0 | 0 | +fmesh_8x8_2cycle_xy | 0 | 0 | +fmesh_8x8_openpiton | 0 | 0 | line4_smart3 | 0 | 0 | -mesh_2x2_openpiton | 2 | 0 | -mesh_3x3_v2_ssa | 2 | 0 | -mesh_4x4_2cycle_mcast_f | 2 | 0 | -mesh_4x4_smart3 | 2 | 0 | -mesh_4x4_v1_B15 | 2 | 0 | -mesh_4x4x3_2cycle_xy | 2 | 0 | -mesh_8x8_2cycle_adaptive | 2 | 0 | -mesh_8x8_2cycle_west_first | 2 | 0 | -mesh_8x8_2cycle_xy | 2 | 0 | -mesh_8x8_4vc_4c | 2 | 0 | -mesh_8x8_4vc_hetero1 | 2 | 0 | -mesh_8x8_4vc_hetero2 | 2 | 0 | -mesh_8x8_b2 | 2 | 0 | -mesh_8x8_sbp6_xy | 2 | 0 | -mesh_8x8_single_flit | 3 | 0 | -mesh_8x8_ssa_xy | 2 | 0 | +line_4_v1_B15 | 0 | 0 | +line_8_single_flit | 1 | 0 | +mesh_2x2_openpiton | 0 | 0 | +mesh_3x3_v2_ssa | 0 | 0 | +mesh_4x4_2cycle_mcast_f | 0 | 0 | +mesh_4x4_LB5_B4 | 0 | 0 | +mesh_4x4_selflp_mcast_f | 0 | 0 | +mesh_4x4_smart3 | 0 | 0 | +mesh_4x4_v1_B15 | 0 | 0 | +mesh_4x4x2_bcast_f | 0 | 0 | +mesh_4x4x2_bcast_p | 0 | 0 | +mesh_4x4x2_mcast_p | 0 | 0 | +mesh_4x4x3_2cycle_xy | 0 | 0 | +mesh_4x4x3_vc_nonspec | 0 | 0 | +mesh_4x4x3_vc_spec1 | 0 | 0 | +mesh_4x4x3_vc_spec2 | 0 | 0 | +mesh_8x8_2cycle_adaptive | 0 | 0 | +mesh_8x8_2cycle_west_first | 0 | 0 | +mesh_8x8_2cycle_xy | 0 | 0 | +mesh_8x8_4vc | 0 | 0 | +mesh_8x8_4vc_4c | 0 | 0 | +mesh_8x8_4vc_hetero1 | 0 | 0 | +mesh_8x8_4vc_hetero2 | 0 | 0 | +mesh_8x8_b2 | 0 | 0 | +mesh_8x8_sbp6_xy | 0 | 0 | +mesh_8x8_single_flit | 1 | 0 | +mesh_8x8_ssa_xy | 0 | 0 | +ring_8x8_2cycle_xy | 0 | 0 | star_6 | 0 | 0 | +star6_2cycle_mcast_par | 0 | 0 | torus_8x8_2cycle_xy | 0 | 0 | diff --git a/mpsoc/Integration_test/Questa_lint/run.sh b/mpsoc/Integration_test/Questa_lint/run.sh index 7d295c5..d7a973e 100644 --- a/mpsoc/Integration_test/Questa_lint/run.sh +++ b/mpsoc/Integration_test/Questa_lint/run.sh @@ -53,22 +53,49 @@ report_total_errors_warnings () { } -for f in "$conf_dir"/*; do - [[ -d "$f" ]] && continue - conf=$(basename "$f") +run_config () { + conf="$1" log_file="${log_dir}/${conf}.log" echo "▶️ Compiling configuration: $conf" - questa_lint "$conf" |& tee $log_file + questa_lint "$conf" |& tee "$log_file" if [[ ${PIPESTATUS[0]} -ne 0 ]]; then echo "❌ Compilation failed for $conf (check $log_file)" - rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + rm -f "${SCRPT_DIR_PATH}/src/noc_localparam.v" exit 1 else echo "✅ Compilation successful for $conf" - rm -f ${SCRPT_DIR_PATH}/src/noc_localparam.v + rm -f "${SCRPT_DIR_PATH}/src/noc_localparam.v" report_total_errors_warnings "$conf" fi -done +} + + +# === Main === +if [[ "$1" == "-h" || "$1" == "--help" ]]; then + echo "Usage: bash run.sh [config_name]" + echo + echo "If [config_name] is provided, only that configuration will be processed." + echo "If no argument is given, all configurations in the 'configurations/' directory will be processed." + echo + echo "Examples:" + echo " bash run.sh # Run all configurations" + echo " bash run.sh conf1 # Run only conf1" + exit 0 +fi + +if [[ $# -eq 1 ]]; then + # Run only the specified configuration + conf_name="$1" + run_config "$conf_name" +else + # Run all configurations + for f in "$conf_dir"/*; do + [[ -d "$f" ]] && continue + conf=$(basename "$f") + run_config "$conf" + done +fi + echo "Report saved in $report_file" echo "Summary:" @@ -78,4 +105,4 @@ cat $report_file echo "Comparing with golden reference..." # Compare the results with the golden reference report perl ${SCRPT_DIR_PATH}/../Altera/src/compare.pl ${SCRPT_DIR_PATH}/golden_ref/report.txt $report_file -echo "All configurations processed. Results are in $report_file \ No newline at end of file +echo "All configurations processed. Results are in $report_file diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 202dc78..46301eb 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -88,7 +88,7 @@ module mesh_torus_noc_top ( end// locals end//x - end else begin :mesh_torus + end else if (IS_MESH | IS_FMESH | IS_TORUS ) begin : mesh_torus for (y=0; y Date: Thu, 19 Jun 2025 16:06:05 +0200 Subject: [PATCH 055/107] fix bug in Questasim run --- mpsoc/rtl/main_comp.v | 22 ---------------------- mpsoc/rtl/src_noc/router_bypass.sv | 21 +++++++++++++++++++++ mpsoc/rtl/src_noc/router_top.sv | 4 ++++ mpsoc/script/synfull/model.tcl | 2 +- mpsoc/script/synfull/noc_localparam.v | 6 ++++++ mpsoc/script/synfull/run_modelsim | 3 --- 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/mpsoc/rtl/main_comp.v b/mpsoc/rtl/main_comp.v index c749063..350ac23 100755 --- a/mpsoc/rtl/main_comp.v +++ b/mpsoc/rtl/main_comp.v @@ -162,28 +162,6 @@ module one_hot_demux #( endgenerate endmodule -/************************** -* reduction_or -***************************/ -module reduction_or #( - parameter W = 5,//out width - parameter N = 4 //array lenght -)( - D_in, - Q_out -); - input [W-1 : 0] D_in [N-1 : 0]; - output reg [W-1 : 0] Q_out; - - // assign Q_out = D_in.or(); //it is not synthesizable able by some compiler - always_comb begin - Q_out = {W{1'b0}}; - for (int i = 0; i < N; i++) - Q_out |= D_in[i]; - end -endmodule - - /***************************************** * sum the output of all ports * except the output of port itself diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index 3f56046..26babad 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -720,3 +720,24 @@ module smart_credit_manage_per_vc #( assign credit_out = credit_in | smart_credit_in | (counter > 0); pronoc_register #(.W(Bw+1)) reg1 (.D_in(counter_next), .reset(reset), .clk(clk), .Q_out(counter)); endmodule + +/************************** +* reduction_or +***************************/ +module reduction_or #( + parameter W = 5,//out width + parameter N = 4 //array lenght +)( + D_in, + Q_out +); + input [W-1 : 0] D_in [N-1 : 0]; + output reg [W-1 : 0] Q_out; + + // assign Q_out = D_in.or(); //it is not synthesizable able by some compiler + always_comb begin + Q_out = {W{1'b0}}; + for (int i = 0; i < N; i++) + Q_out |= D_in[i]; + end +endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index dd242cd..9b90123 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -218,6 +218,10 @@ module router_top #( end //smart_en end//for Port_ + end else begin + for(i=0;i Date: Thu, 19 Jun 2025 16:28:30 +0200 Subject: [PATCH 056/107] Fix NoAssignX-ML linting warning --- mpsoc/rtl/src_noc/comb_nonspec.sv | 8 ++++---- mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv | 12 ++++++------ mpsoc/rtl/src_noc/congestion_analyzer.sv | 14 +++++++------- mpsoc/rtl/src_noc/inout_ports.sv | 4 ++-- mpsoc/rtl/src_noc/input_ports.sv | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index 38e83a7..ba25c1f 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -530,12 +530,12 @@ module nonspec_sw_alloc #( end end else begin - assign single_flit_pck_local_grant[i] = 1'bx; - assign single_flit_granted_dst[i] = {P_1{1'bx}}; + assign single_flit_pck_local_grant[i] = 1'b0; + assign single_flit_granted_dst[i] = {P_1{1'b0}}; assign single_flit_granted_dst_all[i] = {P{1'b0}}; end //second arbiter input/output generate - for(j=0;j7)begin : cmb_v2 comb_nonspec_v2_allocator #( @@ -230,8 +230,8 @@ module combined_vc_sw_alloc #( ); end assign nonspec_granted_dest_port_all = granted_dest_port_all; - assign spec_granted_dest_port_all = {PP_1{1'bx}}; - assign spec_ovc_num_all = {PVV{1'bx}}; + assign spec_granted_dest_port_all = {PP_1{1'b0}}; + assign spec_ovc_num_all = {PVV{1'b0}}; assign spec_first_arbiter_granted_ivc_all = nonspec_first_arbiter_granted_ivc_all ; end endgenerate diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.sv b/mpsoc/rtl/src_noc/congestion_analyzer.sv index 3703b1e..7ddfde7 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.sv +++ b/mpsoc/rtl/src_noc/congestion_analyzer.sv @@ -1014,7 +1014,7 @@ localparam .V(V) ) the_congestion_out_gen ( .ovc_avalable_all(ovc_avalable_all), - .congestion_out_all(congestion_out_all_next) + .congestion_out_all(congestion_out_all_next) ); end else if (CONGESTION_INDEX==11 || CONGESTION_INDEX==12) begin :indx11 congestion_out_based_avb_ovc_not_granted_ivc #( @@ -1027,19 +1027,19 @@ localparam .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant), .clk(clk), .reset(reset), - .congestion_out_all(congestion_out_all_next) + .congestion_out_all(congestion_out_all_next) ); - end else begin :nocong assign congestion_out_all_next = {CONG_ALw{1'bx}}; end + end else begin :nocong assign congestion_out_all_next = {CONG_ALw{1'b0}}; end end else begin :dtrmn - assign congestion_out_all_next = {CONG_ALw{1'bx}}; + assign congestion_out_all_next = {CONG_ALw{1'b0}}; end endgenerate pronoc_register #( - .W(CONG_ALw) + .W(CONG_ALw) ) reg1 ( .D_in(congestion_out_all_next), - .reset(reset), - .clk(clk), + .reset(reset), + .clk(clk), .Q_out(congestion_out_all) ); endmodule diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index 2e6e1e5..6ee9269 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -516,9 +516,9 @@ module vc_alloc_request_gen #( .candidate_ovc_all(candidate_ovc_all) ); - assign swap_port_presel = {PV{1'bx}}; + assign swap_port_presel = {PV{1'b0}}; assign destport_clear_all={PVDSTPw{1'b0}}; - assign sel = {PV{1'bx}}; + assign sel = {PV{1'b0}}; end else begin: adptv diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index c64b5c1..46fe0f6 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -828,10 +828,10 @@ module input_queue_per_port #( .recieve_more_than_1(), .reset(reset), .clk(clk) - ); + ); end else begin : single_local - assign endp_localp_num[(i+1)*PLw-1 : i*PLw] = {PLw{1'bx}}; + assign endp_localp_num[(i+1)*PLw-1 : i*PLw] = {PLw{1'b0}}; end /* verilator lint_off WIDTH */ From 7749a81f6e080347e30250f8bc12210596a67051 Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 19 Jun 2025 16:43:05 +0200 Subject: [PATCH 057/107] fix SignedUnsignedExpr-ML lint warning --- mpsoc/rtl/src_noc/input_ports.sv | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 46fe0f6..bc4d424 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -233,9 +233,11 @@ module input_queue_per_port #( localparam /* verilator lint_off WIDTH */ - OFFSET = (PORT_B%MIN_PCK_SIZE)? 1 :0, - NON_ATOM_PCKS = (PORT_B>MIN_PCK_SIZE)? (PORT_B/MIN_PCK_SIZE)+ OFFSET : 1, - MAX_PCK = (VC_REALLOCATION_TYPE== "ATOMIC")? 1 : NON_ATOM_PCKS + OVC_ALLOC_MODE,// min packet size is two hence the max packet number in buffer is (B/2) + OFFSET = (PORT_B % MIN_PCK_SIZE) ? 1 :0, + NON_ATOM_PCKS = (PORT_B>MIN_PCK_SIZE)? (PORT_B / MIN_PCK_SIZE) + OFFSET : 1, + MAX_PCK = // min packet size is two hence the max packet number in buffer is (B/2) + (VC_REALLOCATION_TYPE== "ATOMIC") ? 1 : + (OVC_ALLOC_MODE) ? NON_ATOM_PCKS + 1 : NON_ATOM_PCKS, IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN==1) || (SMART_EN==1))? 1 : 0; localparam From 549c8401c3154df646fe2c66cd79d849b2fe53ae Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 26 Jun 2025 13:30:32 +0200 Subject: [PATCH 058/107] fix linting warnings --- mpsoc/rtl/src_noc/debug.sv | 8 +- mpsoc/rtl/src_noc/input_ports.sv | 86 ++++----------- mpsoc/rtl/src_noc/topology_localparam.v | 140 ++++++++++++------------ 3 files changed, 97 insertions(+), 137 deletions(-) diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index 094b99a..f75ddb0 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -17,7 +17,7 @@ module check_flit_chanel_type_is_in_order #( hdr_flg_in, flit_in_wr, tail_flg_in, - vc_num_in, + vc_num_in, clk, reset ); @@ -70,7 +70,7 @@ module check_flit_chanel_type_is_in_order #( $display("%t ERROR: A single flit packet is injected while the minimum packet size is set to %d. %m",$time,MIN_PCK_SIZE); $finish; end - //TODO check that the injected packet size meets the MIN_PCK_SIZE + //TODO check that the injected packet size meets the MIN_PCK_SIZE end//always `endif endmodule @@ -207,8 +207,8 @@ module debug_mesh_tori_route_ckeck #( if((vc_num_in & ESCAP_VC_MASK)>0 && (SW_LOC== SOUTH || SW_LOC== NORTH) ) begin // escape vc // if (a & b) $display("%t :Error EVC allocation violate subfunction routing rules %m",$time); if ((current_x - x_dst_in) !=0 && (current_y- y_dst_in) !=0) $display("%t :Error EVC allocation violate subfunction routing rules src_x=%d src_y=%d dst_x%d dst_y=%d %m",$time,x_src_in, y_src_in, x_dst_in,y_dst_in); - end - end//hdr_wr_in + end + end//hdr_wr_in end//always end /* verilator lint_off WIDTH */ diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index bc4d424..c5c69ea 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -232,13 +232,12 @@ module input_queue_per_port #( VP_1 = V * P_1; localparam - /* verilator lint_off WIDTH */ - OFFSET = (PORT_B % MIN_PCK_SIZE) ? 1 :0, - NON_ATOM_PCKS = (PORT_B>MIN_PCK_SIZE)? (PORT_B / MIN_PCK_SIZE) + OFFSET : 1, + OFFSET = ((PORT_B % MIN_PCK_SIZE)>0) ? 1 : 0, + NON_ATOM_PCKS = (PORT_B > MIN_PCK_SIZE) ? (PORT_B / MIN_PCK_SIZE) + OFFSET : 1, MAX_PCK = // min packet size is two hence the max packet number in buffer is (B/2) - (VC_REALLOCATION_TYPE== "ATOMIC") ? 1 : - (OVC_ALLOC_MODE) ? NON_ATOM_PCKS + 1 : NON_ATOM_PCKS, - IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN==1) || (SMART_EN==1))? 1 : 0; + (IS_VCA_ATOMIC) ? 1 : + (OVC_ALLOC_MODE) ? (NON_ATOM_PCKS + 1) : NON_ATOM_PCKS, + IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN == 1) || (SMART_EN==1) ) ? 1 : 0; localparam ELw = log2(T3), @@ -246,7 +245,7 @@ module input_queue_per_port #( PLw = (IS_FMESH) ? Pw : ELw, VPLw= V * PLw, PRAw= P * RAw; - /* verilator lint_on WIDTH */ + input reset, clk; input router_info_t router_info; @@ -405,7 +404,7 @@ module input_queue_per_port #( .clk (clk ), .Q_out (assigned_ovc_num [(i+1)*V-1 : i*V] )); end - if (( IS_RING | IS_LINE | IS_MESH | IS_TORUS) & (T3 > 1) & IS_UNICAST) begin : multi_local + if (IS_REGULAR_TOPO & IS_MULTI_ENDP_ROUTER & IS_UNICAST) begin mesh_tori_endp_addr_decode endp_addr_decode ( .e_addr(dest_e_addr_in), .ex( ), @@ -413,7 +412,7 @@ module input_queue_per_port #( .el(endp_l_in), .valid( ) ); - end :multi_local + end if ( IS_FMESH & IS_UNICAST ) begin : fmesh fmesh_endp_addr_decode endp_addr_decode ( .e_addr(dest_e_addr_in), @@ -658,13 +657,8 @@ module input_queue_per_port #( assign class_out[i] = 1'b0; end - //localparam CAST_TYPE = "UNICAST"; // multicast is not yet supported - /* verilator lint_off WIDTH */ - if(CAST_TYPE!= "UNICAST") begin : muticast - /* verilator lint_on WIDTH */ - + if(~IS_UNICAST) begin : muticast // for multicast we send one packet to each direction in order. The priority is according to DoR routing dimentions - fwft_fifo_with_output_clear #( .DATA_WIDTH(DSTPw), .MAX_DEPTH (MAX_PCK), @@ -723,9 +717,7 @@ module input_queue_per_port #( .clk (clk) ); - /* verilator lint_off WIDTH */ - if( ROUTE_TYPE=="DETERMINISTIC") begin : dtrmn_dest - /* verilator lint_on WIDTH */ + if( IS_DETERMINISTIC ) begin : dtrmn_dest //destport_fifo fwft_fifo #( .DATA_WIDTH(DSTPw), @@ -744,7 +736,7 @@ module input_queue_per_port #( .clk(clk) ); - end else begin : adptv_dest + end else begin : adptv_dest fwft_fifo_with_output_clear #( .DATA_WIDTH(DSTPw), @@ -790,11 +782,8 @@ module input_queue_per_port #( .odd_column(odd_column) ); - /* verilator lint_off WIDTH */ - if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1) && (CAST_TYPE== "UNICAST")) begin : multi_local - /* verilator lint_on WIDTH */ + if ( IS_REGULAR_TOPO & IS_MULTI_ENDP_ROUTER & IS_UNICAST ) begin : multi_local // the router has multiple local ports. Save the destination local port - fwft_fifo #( .DATA_WIDTH(ELw), .MAX_DEPTH (MAX_PCK), @@ -811,9 +800,7 @@ module input_queue_per_port #( .reset(reset), .clk(clk) ); - /* verilator lint_off WIDTH */ - end else if ( TOPOLOGY == "FMESH" && CAST_TYPE== "UNICAST") begin : fmesh - /* verilator lint_on WIDTH */ + end else if ( IS_FMESH & IS_UNICAST) begin : fmesh fwft_fifo #( .DATA_WIDTH(Pw), @@ -835,32 +822,11 @@ module input_queue_per_port #( end else begin : single_local assign endp_localp_num[(i+1)*PLw-1 : i*PLw] = {PLw{1'b0}}; end - - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra - /* verilator lint_on WIDTH */ - /* - weight_control #( - .WEIGHTw(WEIGHTw) - ) wctrl_per_vc ( - .sw_is_granted(ivc_num_getting_sw_grant[i]), - .flit_is_tail(flit_is_tail[i]), - .weight_is_consumed_o(vc_weight_is_consumed[i]), - .iport_weight(1), //(iport_weight), - .clk(clk), - .reset(reset) - ); - */ - assign vc_weight_is_consumed[i] = 1'b1; - end else begin :no_wrra - assign vc_weight_is_consumed[i] = 1'bX; - end + assign vc_weight_is_consumed[i] = (~IS_RRA); end//for i - /* verilator lint_off WIDTH */ - if(SWA_ARBITER_TYPE != "RRA")begin : wrra - /* verilator lint_on WIDTH */ + if(~IS_RRA) begin : wrra wire granted_flit_is_tail; onehot_mux_1D #( @@ -889,18 +855,15 @@ module input_queue_per_port #( .refresh_w_counter(refresh_w_counter), .clk(clk), .reset(reset) - ); + ); end else begin :no_wrra - assign iport_weight_is_consumed=1'bX; - assign oports_weight = {WP{1'bX}}; + assign iport_weight_is_consumed=1'b0; + assign oports_weight = {WP{1'b0}}; end - /* verilator lint_off WIDTH */ - wire [V-1 : 0] flit_buffer_vc_num_rd = (COMBINATION_TYPE == "COMB_NONSPEC")? - /* verilator lint_on WIDTH */ - nonspec_first_arbiter_granted_ivc: - ivc_num_getting_sw_grant; - + wire [V-1 : 0] flit_buffer_vc_num_rd; + assign flit_buffer_vc_num_rd = ( IS_COMB_NONSPEC ) ? nonspec_first_arbiter_granted_ivc : ivc_num_getting_sw_grant; + flit_buffer #( .B(PORT_B), // buffer space :flit per VC, .V(PORT_IVC) @@ -924,7 +887,7 @@ module input_queue_per_port #( assign ivc_not_empty [V-1 : PORT_IVC]={(V-PORT_IVC){1'b0}}; assign flit_is_tail [V-1 : PORT_IVC]={(V-PORT_IVC){1'b0}}; for (i=PORT_IVC;i 1) ; /* verilator lint_on WIDTH */ localparam [0:0] @@ -29,12 +31,14 @@ IS_MULTI_FLIT = (PCK_TYPE == "MULTI_FLIT"), IS_COMB_SPEC2 = (COMBINATION_TYPE == "COMB_SPEC2"), IS_COMB_SPEC1 = (COMBINATION_TYPE == "COMB_SPEC1"), + IS_COMB_NONSPEC = (COMBINATION_TYPE == "COMB_NONSPEC"), IS_MULTICAST_FULL = (CAST_TYPE == "MULTICAST_FULL"), IS_MULTICAST_PARTIAL = (CAST_TYPE == "MULTICAST_PARTIAL"), IS_BROADCAST_PARTIAL = (CAST_TYPE == "BROADCAST_PARTIAL"), IS_UNICAST = (CAST_TYPE == "UNICAST"), IS_BROADCAST_FULL = (CAST_TYPE == "BROADCAST_FULL"), - IS_ONE_HOT_MUX = (MUX_TYPE=="ONE_HOT"); + IS_ONE_HOT_MUX = (MUX_TYPE == "ONE_HOT"), + IS_VCA_ATOMIC = (VC_REALLOCATION_TYPE == "ATOMIC"); /* verilator lint_on WIDTH */ //MESH, TORUS Topology p=5 @@ -57,11 +61,11 @@ function automatic integer log2; input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2= MCAST_PRTLw) ? EAw +1 : - (CAST_TYPE == "MULTICAST_PARTIAL" && EAw < MCAST_PRTLw) ? MCAST_PRTLw +1 : + (IS_MULTICAST_FULL) ? NE : + ((IS_MULTICAST_PARTIAL==1'b1) && (EAw >= MCAST_PRTLw)) ? EAw +1 : + ((IS_MULTICAST_PARTIAL==1'b1) && (EAw < MCAST_PRTLw)) ? MCAST_PRTLw +1 : EAw +1, //broadcast DAw = (IS_MULTI_MESH) ? DAw_MULTI_MESH : - (CAST_TYPE == "UNICAST") ? EAw: - MCASTw + DAw_OFFSETw, - //total number of routers + (IS_UNICAST) ? EAw: + MCASTw + DAw_OFFSETw, + //total number of routers NR = (IS_FATTREE)? NR_FATTREE: (IS_TREE)? NR_TREE: - (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? NR_MESH_TORI: + (IS_REGULAR_TOPO)? NR_MESH_TORI: (IS_FMESH)? NR_FMESH: (IS_STAR) ? NR_STAR: (IS_MULTI_MESH) ? NR_MULTI_MESH: NR_CUSTOM, - //routing algorithm type + //routing algorithm type ROUTE_TYPE = (IS_FATTREE)? ROUTE_TYPE_FATTREE: (IS_TREE)? ROUTE_TYPE_TREE: - (IS_RING || IS_LINE || IS_MESH || IS_TORUS)? ROUTE_TYPE_MESH_TORI: + (IS_REGULAR_TOPO)? ROUTE_TYPE_MESH_TORI: (IS_FMESH)? ROUTE_TYPE_MESH_TORI: (IS_STAR) ? ROUTE_TYPE_STAR: ROUTE_TYPE_CUSTOM; - + /* verilator lint_off WIDTH */ localparam [0:0] IS_DETERMINISTIC = (ROUTE_TYPE == "DETERMINISTIC"); - /* verilator lint_on WIDTH */ + /* verilator lint_on WIDTH */ + function automatic integer mcast_id_to_endp_id; input integer mcast_id; reg [NE-1 : 0] mcast_list; @@ -338,16 +344,14 @@ mcast_list =MCAST_ENDP_LIST; mcast_id_to_endp_id=0; k=0; - /* verilator lint_off WIDTH */ - if (CAST_TYPE == "MULTICAST_FULL")begin - /* verilator lint_on WIDTH */ + if (IS_MULTICAST_FULL)begin mcast_id_to_endp_id =mcast_id; end else begin - while( k!=mcast_id+1) begin + while( k!=mcast_id+1) begin if( mcast_list[mcast_id_to_endp_id]==1'b1) begin - k=k+1; + k=k+1; end - mcast_id_to_endp_id= mcast_id_to_endp_id+1; + mcast_id_to_endp_id= mcast_id_to_endp_id+1; end end end @@ -356,11 +360,9 @@ function automatic integer endp_id_to_mcast_id; input integer endp_id; reg [NE-1 : 0] mcast_list; - integer i; + integer i; begin - /* verilator lint_off WIDTH */ - if (CAST_TYPE == "MULTICAST_FULL") begin - /* verilator lint_on WIDTH */ + if (IS_MULTICAST_FULL) begin endp_id_to_mcast_id = endp_id; end else begin mcast_list =MCAST_ENDP_LIST; @@ -415,7 +417,7 @@ end//else fmesh_addrencode = ( p<<(NXw+NYw) | (y< Date: Thu, 26 Jun 2025 15:08:24 +0200 Subject: [PATCH 059/107] fix some VCS linting warning --- mpsoc/rtl/src_noc/debug.sv | 17 ++++---- mpsoc/rtl/src_noc/flit_buffer.sv | 53 ++++++++++--------------- mpsoc/rtl/src_noc/header_flit.sv | 12 +++--- mpsoc/rtl/src_noc/pronoc_pkg.sv | 21 ++++++---- mpsoc/rtl/src_noc/router_two_stage.sv | 18 ++++----- mpsoc/rtl/src_noc/topology_localparam.v | 4 +- 6 files changed, 61 insertions(+), 64 deletions(-) diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index f75ddb0..1aae2e9 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -483,40 +483,41 @@ module check_pck_size #( wire [DAw-1 : 0] dest_e_addr [V-1:0]; wire [V-1 : 0] vc_hdr_wr_en; wire [V-1 : 0] onehot; - localparam MIN_B = (B2) begin :mwb2 + if(MAX_DEPTH > 2) begin :mwb2 wire [MUX_SEL_WIDTH-1 : 0] mux_sel; wire [DEPTH_DATA_WIDTH-1 : 0] depth_2; wire empty; @@ -597,10 +588,10 @@ module fwft_fifo #( assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; assign recieve_more_than_0 = ~ empty; - assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); + assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== DEPTH_DATA_WIDTH'(1) ); assign out_sel = (recieve_more_than_1) ? 1'b1 : 1'b0; - assign out_ld = (depth !=0 )? rd_en : wr_en; - assign depth_2 = depth - 2; + assign out_ld = (depth !=DEPTH_DATA_WIDTH'(0) )? rd_en : wr_en; + assign depth_2 = depth - DEPTH_DATA_WIDTH'(2); assign mux_sel = depth_2[MUX_SEL_WIDTH-1 : 0]; end else if ( MAX_DEPTH == 2) begin :mw2 diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index 5ed3a65..8a92503 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -71,16 +71,16 @@ module header_flit_generator #( end if(~IS_RRA)begin : wrra_b - assign flit_out [WEIGHT_MSB :WEIGHT_LSB] = weight_in; + assign flit_out [WEIGHT_MSB :WEIGHT_LSB] = weight_in; end if( BYTE_EN ) begin : be_1 - assign flit_out [BE_MSB : BE_LSB] = be_in; + assign flit_out [BE_MSB : BE_LSB] = be_in; end if (DATA_w ==0) begin :no_data if(FPAYw>DATA_LSB) begin: dontcare - assign flit_out [FPAYw-1 : DATA_LSB] = {(FPAYw-DATA_LSB){1'bX}}; + assign flit_out [FPAYw-1 : DATA_LSB] = {(FPAYw-DATA_LSB){1'b0}}; end end else begin :have_data assign flit_out [DATA_MSB : DATA_LSB] = data_in[DATA_MSB-DATA_LSB : 0]; // we have enough space for adding whole of the data @@ -94,10 +94,10 @@ module header_flit_generator #( initial begin if((DATA_LSB + DATA_w)-1 > FPAYw)begin $display("%t: ERROR: The reqired header flit size is %d which is larger than %d payload size ",$time,(DATA_LSB + DATA_w)-1,FPAYw); - $finish; + $finish; end - end - `endif + end + `endif endmodule diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index b0520a7..8a884a2 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -286,19 +286,24 @@ package pronoc_pkg; (HETERO_VC == 0) ? V : (HETERO_VC == 1) ? VC_CONFIG_TABLE [router_id][0] : VC_CONFIG_TABLE [router_id][router_port_num]; - `endif + `endif end endfunction function automatic logic [V-1 : 0] hetero_ovc_unary; - input integer router_id; - input integer router_port_num; //router port num - begin - hetero_ovc_unary = - (HETERO_VC == 0) ? {V{1'b1}} : - (HETERO_VC == 1) ? (1 << VC_CONFIG_TABLE [router_id][0]) - 1 : - (1 << VC_CONFIG_TABLE [router_id][router_port_num]) -1; + input integer router_id; + input integer router_port_num; //router port num + integer vc_num, i; + begin + vc_num = + (HETERO_VC == 0) ? V : + (HETERO_VC == 1) ? VC_CONFIG_TABLE [router_id][0] : + VC_CONFIG_TABLE [router_id][router_port_num]; + hetero_ovc_unary = '0; // initialize to zero + for (i = 0; i < vc_num; i = i + 1) begin + hetero_ovc_unary[i] = 1'b1; end + end endfunction /*********** diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 2404f13..409f3de 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -65,16 +65,16 @@ module router_two_stage #( output flit_chanel_t chan_out [P-1 : 0]; input ctrl_chanel_t ctrl_in [P-1 : 0]; output ctrl_chanel_t ctrl_out [P-1 : 0]; - input clk,reset; + input clk,reset; output ivc_info_t ivc_info [P-1 : 0][V-1 : 0]; output ovc_info_t ovc_info [P-1 : 0][V-1 : 0]; output iport_info_t iport_info [P-1 : 0]; output oport_info_t oport_info [P-1 : 0]; - input smart_ctrl_t smart_ctrl_in [P-1 : 0]; + input smart_ctrl_t smart_ctrl_in [P-1 : 0]; - vsa_ctrl_t vsa_ctrl [P-1 : 0]; + vsa_ctrl_t vsa_ctrl [P-1 : 0]; localparam PV = V * P, @@ -638,32 +638,32 @@ module credit_release_gen #( clk, reset, en, - credit_out + credit_out ); import pronoc_pkg::*; input clk, reset; input en; - output reg credit_out; + output reg credit_out; localparam W=log2(CREDIT_NUM +1); reg [W-1 : 0] counter; - wire counter_is_zero = counter=={W{1'b0}}; - wire counter_is_max = counter==CREDIT_NUM; + wire counter_is_zero = counter=={W{1'b0}}; + wire counter_is_max = (counter==CREDIT_NUM[W-1 : 0]); wire counter_incr = (en & counter_is_zero ) | (~counter_is_zero & ~counter_is_max); always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin - counter <= {W{1'b0}}; + counter <= {W{1'b0}}; credit_out<=1'b0; end else begin if(counter_incr) begin counter<= counter +1'b1; credit_out<=1'b1; end else begin - credit_out<=1'b0; + credit_out<=1'b0; end end end diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 8b24dc4..f8ee4d7 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -341,7 +341,7 @@ reg [NE-1 : 0] mcast_list; integer k; begin - mcast_list =MCAST_ENDP_LIST; + mcast_list = MCAST_ENDP_LIST [NE-1 : 0]; mcast_id_to_endp_id=0; k=0; if (IS_MULTICAST_FULL)begin @@ -365,7 +365,7 @@ if (IS_MULTICAST_FULL) begin endp_id_to_mcast_id = endp_id; end else begin - mcast_list =MCAST_ENDP_LIST; + mcast_list = MCAST_ENDP_LIST [NE-1 : 0]; endp_id_to_mcast_id=0; for (i=0;i Date: Thu, 26 Jun 2025 15:32:20 +0200 Subject: [PATCH 060/107] fix width missmatch linting warning --- mpsoc/rtl/src_noc/flit_buffer.sv | 4 ++-- mpsoc/rtl/src_noc/ss_allocator.sv | 2 +- mpsoc/rtl/src_noc/topology_localparam.v | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 06417d0..4957a8d 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -177,8 +177,8 @@ module flit_buffer if (wr[k] ) wr_ptr_next [k] = wr_ptr [k]+ 1'h1; if (rd[k] ) rd_ptr_next [k] = rd_ptr [k]+ 1'h1; end else begin - if (wr[k] ) wr_ptr_next[k] =(wr_ptr[k]==PTRw'(B*(k+1))-1) ? PTRw'(B*k) : wr_ptr [k] + PTRw'(1); - if (rd[k] ) rd_ptr_next[k] =(rd_ptr[k]==PTRw'(B*(k+1))-1) ? PTRw'(B*k) : rd_ptr [k] + PTRw'(1); + if (wr[k] ) wr_ptr_next[k] =(wr_ptr[k]==PTRw'(B*(k+1)-1)) ? PTRw'(B*k) : wr_ptr [k] + PTRw'(1); + if (rd[k] ) rd_ptr_next[k] =(rd_ptr[k]==PTRw'(B*(k+1)-1)) ? PTRw'(B*k) : rd_ptr [k] + PTRw'(1); end if (wr[k] & ~rd[k]) depth_next [k] = depth[k] + 1'h1; else if (~wr[k] & rd[k]) depth_next [k] = depth[k] - 1'h1; diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index a015315..6771a89 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -216,7 +216,7 @@ module ssa_per_vc #( SW_LOC = V_GLOBAL/V, V_LOCAL = V_GLOBAL%V; /* verilator lint_off WIDTH */ - localparam SSA_EN_IN_PORT = ((IS_MESH | IS_TORUS) && (ROUTE_TYPE == "FULL_ADAPTIVE") && (SS_PORT==2 || SS_PORT == 4) && ((1< Date: Thu, 26 Jun 2025 16:26:06 +0200 Subject: [PATCH 061/107] fix linting --- mpsoc/rtl/src_noc/input_ports.sv | 57 ++++++++---------------------- mpsoc/rtl/src_noc/ss_allocator.sv | 20 +++-------- mpsoc/rtl/src_openpiton/wrapper.sv | 8 ----- 3 files changed, 19 insertions(+), 66 deletions(-) diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index c5c69ea..7ff1bcb 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -760,18 +760,8 @@ module input_queue_per_port #( end//unicast destp_generator #( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), - .T1(T1), - .NL(T3), .P(P), - .DSTPw(DSTPw), - .PLw(PLw), - .PPSw(PPSw), - .SELF_LOOP_EN (SELF_LOOP_EN), - .SW_LOC(SW_LOC), - .CAST_TYPE(CAST_TYPE) + .SW_LOC(SW_LOC) ) decoder ( .destport_one_hot (destport_one_hot[i]), .dest_port_encoded(dest_port_encoded[i]), @@ -1024,18 +1014,8 @@ endmodule // decode and mask the destination port according to routing algorithm and topology module destp_generator #( - parameter TOPOLOGY="MESH", - parameter ROUTE_NAME="XY", - parameter ROUTE_TYPE="DETERMINISTIC", - parameter T1=3, - parameter NL=1, parameter P=5, - parameter DSTPw=4, - parameter PLw=1, - parameter PPSw=4, - parameter SW_LOC=0, - parameter SELF_LOOP_EN=0, - parameter CAST_TYPE = "UNICAST" + parameter SW_LOC=0 )( destport_one_hot, dest_port_encoded, @@ -1045,20 +1025,24 @@ module destp_generator #( port_pre_sel, odd_column ); - + import pronoc_pkg::*; + + localparam + ELw = log2(T3), + Pw = log2(P), + PLw = (IS_FMESH) ? Pw : ELw; + localparam P_1 = (SELF_LOOP_EN )? P : P-1; input [DSTPw-1 : 0] dest_port_encoded; input [PLw-1 : 0] endp_localp_num; output [P_1-1: 0] dest_port_out; output [P-1 : 0] destport_one_hot; - input swap_port_presel; + input swap_port_presel; input [PPSw-1 : 0] port_pre_sel; input odd_column; generate - /* verilator lint_off WIDTH */ - if(CAST_TYPE!= "UNICAST") begin : muticast - /* verilator lint_on WIDTH */ + if( ~IS_UNICAST ) begin : muticast // destination port is not coded for multicast/broadcast if( SELF_LOOP_EN==0) begin : nslp remove_sw_loc_one_hot #( @@ -1071,9 +1055,7 @@ module destp_generator #( end else begin : slp assign dest_port_out = dest_port_encoded; end - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "FATTREE" ) begin : fat - /* verilator lint_on WIDTH */ + end else if( IS_FATTREE ) begin : fat fattree_destp_generator #( .K(T1), .P(P), @@ -1086,9 +1068,7 @@ module destp_generator #( .dest_port_in_encoded(dest_port_encoded), .dest_port_out(dest_port_out) ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "TREE") begin :tree - /* verilator lint_on WIDTH */ + end else if ( IS_TREE ) begin :tree tree_destp_generator #( .K(T1), .P(P), @@ -1099,9 +1079,7 @@ module destp_generator #( .dest_port_in_encoded(dest_port_encoded), .dest_port_out(dest_port_out) ); - /* verilator lint_off WIDTH */ - end else if(TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH"|| TOPOLOGY == "TORUS") begin : mesh - /* verilator lint_on WIDTH */ + end else if( IS_REGULAR_TOPO ) begin : reqular mesh_torus_destp_generator #( .TOPOLOGY(TOPOLOGY), .ROUTE_NAME(ROUTE_NAME), @@ -1121,9 +1099,7 @@ module destp_generator #( .port_pre_sel(port_pre_sel), .odd_column(odd_column)// only needed for odd even routing ); - /* verilator lint_off WIDTH */ - end else if (TOPOLOGY == "FMESH") begin :fmesh - /* verilator lint_on WIDTH */ + end else if ( IS_FMESH ) begin :fmesh fmesh_destp_generator #( .ROUTE_NAME(ROUTE_NAME), .ROUTE_TYPE(ROUTE_TYPE), @@ -1143,7 +1119,6 @@ module destp_generator #( .odd_column(odd_column) // only needed for odd even routing ); end else begin :custom - custom_topology_destp_decoder #( .ROUTE_TYPE(ROUTE_TYPE), .DSTPw(DSTPw), @@ -1155,9 +1130,7 @@ module destp_generator #( .dest_port_out(dest_port_out) ); end - /* verilator lint_off WIDTH */ if(SELF_LOOP_EN==0) begin : nslp - /* verilator lint_on WIDTH */ add_sw_loc_one_hot #( .P(P), .SW_LOC(SW_LOC) diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index 6771a89..d92b6d3 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -215,9 +215,8 @@ module ssa_per_vc #( localparam SW_LOC = V_GLOBAL/V, V_LOCAL = V_GLOBAL%V; - /* verilator lint_off WIDTH */ - localparam SSA_EN_IN_PORT = (((IS_MESH | IS_TORUS) & IS_FULL_ADAPTIVE) && (SS_PORT == 2 || SS_PORT == 4) && ((1< Date: Thu, 26 Jun 2025 17:34:48 +0200 Subject: [PATCH 062/107] fix linting 2 --- mpsoc/rtl/src_noc/debug.sv | 27 +++++++++++---------------- mpsoc/rtl/src_noc/flit_buffer.sv | 17 ++++++++++------- mpsoc/rtl/src_noc/output_ports.sv | 12 +++--------- mpsoc/rtl/src_noc/router_top.sv | 14 ++++---------- mpsoc/rtl/src_noc/ss_allocator.sv | 2 +- 5 files changed, 29 insertions(+), 43 deletions(-) diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index 1aae2e9..5a52910 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -9,11 +9,8 @@ //check if flits are recived in correct order in a VC -module check_flit_chanel_type_is_in_order #( - parameter V=4, - parameter PCK_TYPE = "SINGLE_FLIT", - parameter MIN_PCK_SIZE=2 -)( +module check_flit_chanel_type_is_in_order +( hdr_flg_in, flit_in_wr, tail_flg_in, @@ -21,6 +18,8 @@ module check_flit_chanel_type_is_in_order #( clk, reset ); + import pronoc_pkg::*; + input clk, reset; input hdr_flg_in, tail_flg_in, flit_in_wr; input [V-1 : 0] vc_num_in; @@ -34,7 +33,7 @@ module check_flit_chanel_type_is_in_order #( assign vc_num_tail_wr =(tail_flg_in & flit_in_wr)? vc_num_in : {V{1'b0}}; assign vc_num_bdy_wr =({hdr_flg_in,tail_flg_in} == 2'b00 && flit_in_wr)? vc_num_in : {V{1'b0}}; assign single_flit_pck = vc_num_hdr_wr & vc_num_tail_wr; - always @(*)begin + always_comb begin hdr_passed_next = (hdr_passed | vc_num_hdr_wr) & ~vc_num_tail_wr; end @@ -56,16 +55,14 @@ module check_flit_chanel_type_is_in_order #( $display("%t ERROR: a tail flit is received in an inactive IVC %m",$time); $finish; end - if ((~hdr_passed & vc_num_bdy_wr )>0)begin + if ((~hdr_passed & vc_num_bdy_wr )>0)begin $display("%t ERROR: a body flit is received in an inactive IVC %m",$time); $finish; end - /* verilator lint_off WIDTH */ - if((PCK_TYPE == "SINGLE_FLIT") & flit_in_wr & ~(hdr_flg_in & tail_flg_in )) begin + if( IS_SINGLE_FLIT & flit_in_wr & ~(hdr_flg_in & tail_flg_in )) begin $display("%t ERROR: both tail and header flit flags must be asserted in SINGLE_FLIT mode %m",$time); $finish; end - /* verilator lint_on WIDTH */ if( (MIN_PCK_SIZE !=1) & flit_in_wr & hdr_flg_in & tail_flg_in ) begin $display("%t ERROR: A single flit packet is injected while the minimum packet size is set to %d. %m",$time,MIN_PCK_SIZE); $finish; @@ -280,12 +277,10 @@ module debug_mesh_edges #( SOUTH = 4; `ifdef SIMULATION always @(posedge clk) begin - /* verilator lint_off WIDTH */ - if(current_rx == {RXw{1'b0}} && flit_out_wr_all[WEST]) $display ( "%t\t ERROR: a packet is going to the WEST in a router located in first column in mesh topology %m",$time ); - if(current_rx == T1-1 && flit_out_wr_all[EAST]) $display ( "%t\t ERROR: a packet is going to the EAST in a router located in last column in mesh topology %m",$time ); - if(current_ry == {RYw{1'b0}} && flit_out_wr_all[NORTH])$display ( "%t\t ERROR: a packet is going to the NORTH in a router located in first row in mesh topology %m",$time ); - if(current_ry == T2-1 && flit_out_wr_all[SOUTH])$display ( "%t\t ERROR: a packet is going to the SOUTH in a router located in last row in mesh topology %m",$time); - /* verilator lint_on WIDTH */ + if(current_rx == {RXw{1'b0}} && flit_out_wr_all[WEST]) $display ( "%t\t ERROR: a packet is going to the WEST in a router located in first column in mesh topology %m",$time ); + if(current_rx == RXw'(T1-1) && flit_out_wr_all[EAST]) $display ( "%t\t ERROR: a packet is going to the EAST in a router located in last column in mesh topology %m",$time ); + if(current_ry == {RYw{1'b0}} && flit_out_wr_all[NORTH])$display ( "%t\t ERROR: a packet is going to the NORTH in a router located in first row in mesh topology %m",$time ); + if(current_ry == RYw'(T2-1) && flit_out_wr_all[SOUTH])$display ( "%t\t ERROR: a packet is going to the SOUTH in a router located in last row in mesh topology %m",$time); end//always `endif endmodule diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 4957a8d..44b1e6a 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -86,7 +86,7 @@ module flit_buffer reg [PTRw- 1 : 0] wr_ptr_next [V-1 :0]; reg [PTRw- 1 : 0] sub_rd_ptr_next [V-1 :0]; wire [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; - wire [PTRw-1 : 0] ptr_tmp [V-1 : 0]; + wire [ARRAYw-1 : 0] rd_ptr_array; wire [ARRAYw-1 : 0] wr_ptr_array; @@ -270,21 +270,24 @@ module flit_buffer not power of 2 ******************/ // memory address - wire [BVw- 1 : 0] wr_addr; - wire [BVw- 1 : 0] rd_addr; + wire [BVw- 1 : 0] wr_addr, rd_addr; + wire [PTRw-1 : 0] rd_ptr_tmp [V-1 : 0]; + wire [PTRw-1 : 0] wr_ptr_tmp [V-1 : 0]; for(i=0;i 1) && (IS_SINGLE_FLIT)) begin + if((MIN_PCK_SIZE > 1) && (IS_SINGLE_FLIT==1'b1)) begin $display("ERROR: The minimum packet size must be set as one for single-flit packet type NoC"); $finish; end - if(((SSA_EN==1) || (SMART_EN==1)) && CAST_TYPE!="UNICAST") begin + if(((SSA_EN==1) || (SMART_EN==1)) && (IS_UNICAST==1'b0)) begin $display("ERROR: SMART or SAA do not support muticast/braodcast packets"); $finish; end end - /* verilator lint_on WIDTH */ generate `ifdef IVC_DEBUG wire report_active_ivcs = testbench_noc.report_active_ivcs; @@ -317,11 +315,7 @@ module router_top #( ); if(DEBUG_EN) begin :dbg - check_flit_chanel_type_is_in_order #( - .V(V), - .PCK_TYPE(PCK_TYPE), - .MIN_PCK_SIZE(MIN_PCK_SIZE) - ) IVC_flit_type_check ( + check_flit_chanel_type_is_in_order IVC_flit_type_check ( .clk(clk), .reset(reset), .hdr_flg_in(chan_in[i].flit_chanel.flit.hdr_flag), diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index d92b6d3..0e97c95 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -215,7 +215,7 @@ module ssa_per_vc #( localparam SW_LOC = V_GLOBAL/V, V_LOCAL = V_GLOBAL%V; - localparam logic [V-1:0] MASKED_LOCAL_VC = V'((1 << V_LOCAL) & ~ESCAP_VC_MASK); + localparam logic [V-1:0] MASKED_LOCAL_VC = V'((1 << V_LOCAL)) & ~ V'(ESCAP_VC_MASK); localparam SSA_EN_IN_PORT = (((IS_MESH | IS_TORUS) & IS_FULL_ADAPTIVE) && (SS_PORT == 2 || SS_PORT == 4) && ( MASKED_LOCAL_VC != {V{1'b0}}) ) ? 1'b0 : 1'b1; input [Fw-1 : 0] flit_in; From 0bef76ad382e672bc73d7a01022c74723c675f81 Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 26 Jun 2025 17:58:30 +0200 Subject: [PATCH 063/107] fix linting3 --- mpsoc/rtl/src_noc/debug.sv | 4 ++-- mpsoc/rtl/src_noc/multicast.sv | 10 ++++------ mpsoc/rtl/src_noc/router_two_stage.sv | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index 5a52910..c2c0471 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -516,7 +516,7 @@ module check_pck_size #( if(CAST_TYPE!="UNICAST") begin /* verilator lint_on WIDTH */ //Check that the size of multicast/broadcast packets <= buffer size - assign vc_hdr_wr_en [i] = flit_in_wr & hdr_flg_in & (vc_num_in == i); + assign vc_hdr_wr_en [i] = flit_in_wr & hdr_flg_in & (vc_num_in == VC); pronoc_register_ld_en #(.W(DAw)) reg2( .D_in (dest_e_addr_in), .reset (reset ), @@ -539,7 +539,7 @@ module check_pck_size #( .result(onehot[i]) ); always @(posedge clk) begin - if (vc_num_in == i)begin + if (vc_num_in == VC) begin if(flit_in_wr & ~onehot[i])begin if(pck_size_counter_next[i]>MIN_B) begin $display ( "%t\t ERROR: A multicast packet is injected to the router with packet size (%d flits) that is larger than the minimum router buffer size (%d flits) parameter %m",$time,pck_size_counter_next[i],MIN_B); diff --git a/mpsoc/rtl/src_noc/multicast.sv b/mpsoc/rtl/src_noc/multicast.sv index 90b0895..6005379 100644 --- a/mpsoc/rtl/src_noc/multicast.sv +++ b/mpsoc/rtl/src_noc/multicast.sv @@ -518,15 +518,13 @@ module multicast_chan_in_process #( chan_out=chan_in; if(chan_in.flit.hdr_flag == 1'b1) begin chan_out.flit [E_DST_MSB : E_DST_LSB] = dest_e_addr; - chan_out.flit [DST_P_MSB : DST_P_LSB] = destport_o; + chan_out.flit [DST_P_MSB : DST_P_LSB] = destport_o; end - end - `ifdef SIMULATION + end + `ifdef SIMULATION if(DEBUG_EN) begin :debg always @(posedge clk) begin - /* verilator lint_off WIDTH */ - if(CAST_TYPE == "MULTICAST_FULL" || CAST_TYPE == "MULTICAST_PARTIAL") - /* verilator lint_on WIDTH */ + if(IS_MULTICAST_FULL | IS_MULTICAST_PARTIAL) if(chan_in.flit_wr == 1'b1 && chan_in.flit.hdr_flag == 1'b1 && mcast_dst_coded == {MCASTw{1'b0}}) begin $display ("%t: ERROR: A multicast packet is injected to the NoC with zero mcast_dst_coded filed %m ",$time); $finish; diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 409f3de..77a32af 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -193,7 +193,7 @@ module router_two_stage #( end for (i=0; i0 && t2[i]==0)begin $display("%t :Out router (id=%d, addr=%h, port=%d), flitout=%h",$time,current_r_id,current_r_addr,i,flit_out_all[(i+1)*Fw-1 : i*Fw]); From a6916c39b54e2f57992334cab8f5c919312c52cc Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 26 Jun 2025 18:33:19 +0200 Subject: [PATCH 064/107] fix phy gen --- mpsoc/script/phy_noc_gen/phy_noc.pl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mpsoc/script/phy_noc_gen/phy_noc.pl b/mpsoc/script/phy_noc_gen/phy_noc.pl index 4ae90e3..7917c69 100644 --- a/mpsoc/script/phy_noc_gen/phy_noc.pl +++ b/mpsoc/script/phy_noc_gen/phy_noc.pl @@ -97,8 +97,8 @@ # Remove content within quotes $file_content =~ s/"(?:[^"\\]|\\.)*"//g; # Find all parameters and localparams - while ($file_content =~ /\b(parameter|localparam)\s+(.*?);/sg) { - my $declaration = $2; + while ($file_content =~ /\b(parameter|localparam)\b\s*(\[[^\]]*\]\s*)?(.*?);/sg) { + my $declaration = $3; # Split the declaration into individual parameter assignments my @params = split /,\s*/, $declaration; foreach my $param (@params) { @@ -148,7 +148,8 @@ # Pre-compile regular expressions my $before = qr/[%!~,=><:\/\n\s\[\]\{\}\(\)\+\-\*\\\.]/; -my $after = qr/[%!~,=><:\/\s;\[\]\(\)\{\}\+\-\*\\\^]/; +#my $after = qr/[%!~,=><:\/\s;\[\]\(\)\{\}\+\-\*\\\^]/; +my $after = qr/[%!~,=><:\/\s;\[\]\(\)\{\}\+\-\*\\\^']/; # Compile module replacement regex my %module_replacements = map { $_ => "${_}_$noc_id" } @module_names; From c98e03338b08d80019d8c1d2dac4e67e152c0d77 Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 7 Jul 2025 19:07:25 +0200 Subject: [PATCH 065/107] add verilator lint to intigration test --- .../configurations/Fattree_k3_L3_st | 9 ++ .../configurations/bintree_k3_L3_st | 9 ++ .../configurations/custom1_topology | 10 ++ .../configurations/fmesh_1x1_openpiton | 15 +++ .../configurations/fmesh_2x2_openpiton | 14 +++ .../configurations/fmesh_8x8_2cycle_xy | 6 + .../configurations/fmesh_8x8_openpiton | 14 +++ .../configurations/line4_smart3 | 16 +++ .../configurations/line_4_v1_B15 | 14 +++ .../configurations/line_8_single_flit | 9 ++ .../configurations/mesh_2x2_openpiton | 13 +++ .../configurations/mesh_3x3_v2_ssa | 12 ++ .../configurations/mesh_4x4_2cycle_mcast_f | 8 ++ .../configurations/mesh_4x4_LB5_B4 | 12 ++ .../configurations/mesh_4x4_selflp_mcast_f | 9 ++ .../configurations/mesh_4x4_smart3 | 15 +++ .../configurations/mesh_4x4_v1_B15 | 13 +++ .../configurations/mesh_4x4x2_bcast_f | 10 ++ .../configurations/mesh_4x4x2_bcast_p | 10 ++ .../configurations/mesh_4x4x2_mcast_p | 10 ++ .../configurations/mesh_4x4x3_2cycle_xy | 9 ++ .../configurations/mesh_4x4x3_vc_nonspec | 10 ++ .../configurations/mesh_4x4x3_vc_spec1 | 10 ++ .../configurations/mesh_4x4x3_vc_spec2 | 10 ++ .../configurations/mesh_8x8_2cycle_adaptive | 6 + .../configurations/mesh_8x8_2cycle_west_first | 5 + .../configurations/mesh_8x8_2cycle_xy | 5 + .../configurations/mesh_8x8_4vc | 7 ++ .../configurations/mesh_8x8_4vc_4c | 9 ++ .../configurations/mesh_8x8_4vc_hetero1 | 77 +++++++++++++ .../configurations/mesh_8x8_4vc_hetero2 | 77 +++++++++++++ .../verilator_lint/configurations/mesh_8x8_b2 | 7 ++ .../configurations/mesh_8x8_sbp6_xy | 5 + .../configurations/mesh_8x8_single_flit | 8 ++ .../configurations/mesh_8x8_ssa_xy | 5 + .../configurations/ring_8x8_2cycle_xy | 8 ++ .../configurations/star6_2cycle_mcast_par | 11 ++ .../verilator_lint/configurations/star_6 | 8 ++ .../configurations/torus_8x8_2cycle_xy | 6 + mpsoc/Integration_test/verilator_lint/run.sh | 104 ++++++++++++++++++ .../verilator_lint/src/file_list.f | 6 + .../verilator_lint/src/param_gen.pl | 46 ++++++++ mpsoc/rtl/src_noc/debug.sv | 1 - mpsoc/rtl/src_noc/flit_buffer.sv | 2 - mpsoc/rtl/src_noc/multicast.sv | 22 ++-- mpsoc/rtl/src_noc/router_top.sv | 31 +++--- mpsoc/rtl/src_noc/router_two_stage.sv | 3 + mpsoc/rtl/src_noc/tree_noc_top.sv | 29 ++--- mpsoc/rtl/src_noc/wrra.sv | 2 +- 49 files changed, 703 insertions(+), 54 deletions(-) create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/Fattree_k3_L3_st create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/bintree_k3_L3_st create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/custom1_topology create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/fmesh_1x1_openpiton create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/fmesh_2x2_openpiton create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_openpiton create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/line4_smart3 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/line_4_v1_B15 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/line_8_single_flit create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_2x2_openpiton create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_3x3_v2_ssa create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_2cycle_mcast_f create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_LB5_B4 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_selflp_mcast_f create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_smart3 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_v1_B15 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_f create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_p create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_mcast_p create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_west_first create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_sbp6_xy create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_single_flit create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_ssa_xy create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/star6_2cycle_mcast_par create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/star_6 create mode 100644 mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/verilator_lint/run.sh create mode 100644 mpsoc/Integration_test/verilator_lint/src/file_list.f create mode 100644 mpsoc/Integration_test/verilator_lint/src/param_gen.pl diff --git a/mpsoc/Integration_test/verilator_lint/configurations/Fattree_k3_L3_st b/mpsoc/Integration_test/verilator_lint/configurations/Fattree_k3_L3_st new file mode 100644 index 0000000..e8816f6 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/Fattree_k3_L3_st @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"FATTREE\"", + "T1" => "3", + "T2" => "3", + "B" => "5", + "ROUTE_NAME" => "\"NCA_STRAIGHT_UP\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/bintree_k3_L3_st b/mpsoc/Integration_test/verilator_lint/configurations/bintree_k3_L3_st new file mode 100644 index 0000000..85fc4b5 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/bintree_k3_L3_st @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TREE\"", + "T1" => "3", + "T2" => "3", + "B" => "5", + "ROUTE_NAME" => "\"NCA\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/custom1_topology b/mpsoc/Integration_test/verilator_lint/configurations/custom1_topology new file mode 100644 index 0000000..8b17d0e --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/custom1_topology @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=>"\"custom1\"", + "CUSTOM_TOPOLOGY_NAME"=>"\"custom1\"", + "T1" => "16", + "T2" => "16", + "T3" => "5", + "ROUTE_NAME" =>"\"custom\"" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/fmesh_1x1_openpiton b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_1x1_openpiton new file mode 100644 index 0000000..f80a7c7 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_1x1_openpiton @@ -0,0 +1,15 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "1", + "T2" => "1", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + "MIN_PCK_SIZE" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/fmesh_2x2_openpiton b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_2x2_openpiton new file mode 100644 index 0000000..449f321 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_2x2_openpiton @@ -0,0 +1,14 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "2", + "T2" => "2", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy new file mode 100644 index 0000000..ff79533 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy @@ -0,0 +1,6 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"FMESH\"", + "ROUTE_NAME" => "\"XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_openpiton b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_openpiton new file mode 100644 index 0000000..37c19a2 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_openpiton @@ -0,0 +1,14 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "8", + "T2" => "8", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/line4_smart3 b/mpsoc/Integration_test/verilator_lint/configurations/line4_smart3 new file mode 100644 index 0000000..548c123 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/line4_smart3 @@ -0,0 +1,16 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + TOPOLOGY=>"\"LINE\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "1", + "MCAST_ENDP_LIST" => "'b11", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/line_4_v1_B15 b/mpsoc/Integration_test/verilator_lint/configurations/line_4_v1_B15 new file mode 100644 index 0000000..5d00709 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/line_4_v1_B15 @@ -0,0 +1,14 @@ +$model = bless( { + 'noc_param'=> { + TOPOLOGY=>"\"LINE\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "15", + "LB" => "15", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "0", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/line_8_single_flit b/mpsoc/Integration_test/verilator_lint/configurations/line_8_single_flit new file mode 100644 index 0000000..a73600b --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/line_8_single_flit @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + TOPOLOGY=>"\"LINE\"", + "B" => "5", + "LB" => "5", + "MIN_PCK_SIZE" => "1", + "PCK_TYPE" => " \"SINGLE_FLIT\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_2x2_openpiton b/mpsoc/Integration_test/verilator_lint/configurations/mesh_2x2_openpiton new file mode 100644 index 0000000..4b61b2e --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_2x2_openpiton @@ -0,0 +1,13 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "2", + "T2" => "2", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_3x3_v2_ssa b/mpsoc/Integration_test/verilator_lint/configurations/mesh_3x3_v2_ssa new file mode 100644 index 0000000..1383775 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_3x3_v2_ssa @@ -0,0 +1,12 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "3", + "T2" => "3", + "SELF_LOOP_EN" => "1", + "SSA_EN"=> "1", + "LB" => 16, + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", + "Fpay" => "64", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_2cycle_mcast_f new file mode 100644 index 0000000..975dea2 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_2cycle_mcast_f @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64" + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_LB5_B4 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_LB5_B4 new file mode 100644 index 0000000..50ac90c --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_LB5_B4 @@ -0,0 +1,12 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "B" => "4", + "LB" => "5", + "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", + "MCAST_ENDP_LIST" => "16'b110011000111101", + "Fpay" => "64", + "SELF_LOOP_EN" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_selflp_mcast_f b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_selflp_mcast_f new file mode 100644 index 0000000..5c5852e --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_selflp_mcast_f @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64", + "SELF_LOOP_EN" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_smart3 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_smart3 new file mode 100644 index 0000000..ad8749e --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_smart3 @@ -0,0 +1,15 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_v1_B15 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_v1_B15 new file mode 100644 index 0000000..a07a491 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4_v1_B15 @@ -0,0 +1,13 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "15", + "LB" => "15", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "0", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_f b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_f new file mode 100644 index 0000000..dc24a2f --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_f @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "2", + "CAST_TYPE" => "\"BROADCAST_FULL\"", + "MCAST_ENDP_LIST" => "32'b1100110001111", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_p b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_p new file mode 100644 index 0000000..23c4749 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_bcast_p @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "2", + "CAST_TYPE" => "\"BROADCAST_PARTIAL\"", + "MCAST_ENDP_LIST" => "32'b1100110001111", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_mcast_p b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_mcast_p new file mode 100644 index 0000000..ad2854b --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x2_mcast_p @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "2", + "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", + "MCAST_ENDP_LIST" => "32'b1100110001111", + "Fpay" => "64" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy new file mode 100644 index 0000000..f0c8499 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec new file mode 100644 index 0000000..719d562 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + "COMBINATION_TYPE" => "\"COMB_NONSPEC\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 new file mode 100644 index 0000000..9d89499 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + "COMBINATION_TYPE" => "\"COMB_SPEC1\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 new file mode 100644 index 0000000..aea90d2 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "3", + "TOPOLOGY" => "\"MESH\"", + "ROUTE_NAME" => "\"XY\"", + "COMBINATION_TYPE" => "\"COMB_SPEC2\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive new file mode 100644 index 0000000..20550e3 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive @@ -0,0 +1,6 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"DUATO\"", + "ESCAP_VC_MASK" => "2'b01" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_west_first b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_west_first new file mode 100644 index 0000000..a794210 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_west_first @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"WEST_FIRST\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy new file mode 100644 index 0000000..4af7e61 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc new file mode 100644 index 0000000..248f91c --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "ESCAP_VC_MASK" => "4'd1", + "V" => 4, + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c new file mode 100644 index 0000000..d2f38c8 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "V" => 4, + "C" => 4, + "CLASS_SETTING" => "16'b1000010000100001", + "ESCAP_VC_MASK" => "4'b1000" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 new file mode 100644 index 0000000..5196912 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 @@ -0,0 +1,77 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "ESCAP_VC_MASK" => "4'd1", + "V" => 4, + "HETERO_VC"=> "1", + "MAX_ROUTER"=>"64", + "MAX_PORT"=>"1", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{ + //P0 P1 P2 P3 P4 + '{1}, // R0 + '{2}, // R1 + '{3}, // R2 + '{4}, // R3 + '{1}, // R4 + '{2}, // R5 + '{3}, // R6 + '{4}, // R7 + '{1}, // R8 + '{2}, // R9 + '{3}, // R10 + '{4}, // R11 + '{1}, // R12 + '{2}, // R13 + '{3}, // R14 + '{1}, // R15 + '{2}, // R16 + '{3}, // R17 + '{4}, // R18 + '{1}, // R19 + '{2}, // R20 + '{3}, // R21 + '{4}, // R22 + '{1}, // R23 + '{2}, // R24 + '{3}, // R25 + '{4}, // R26 + '{1}, // R27 + '{2}, // R28 + '{3}, // R29 + '{1}, // R30 + '{2}, // R31 + '{3}, // R32 + '{4}, // R33 + '{1}, // R34 + '{2}, // R35 + '{3}, // R36 + '{4}, // R37 + '{1}, // R38 + '{2}, // R39 + '{3}, // R40 + '{4}, // R41 + '{1}, // R42 + '{2}, // R43 + '{3}, // R44 + '{1}, // R45 + '{2}, // R46 + '{3}, // R47 + '{4}, // R48 + '{1}, // R49 + '{2}, // R50 + '{3}, // R51 + '{4}, // R52 + '{1}, // R53 + '{2}, // R54 + '{3}, // R55 + '{4}, // R56 + '{1}, // R57 + '{2}, // R58 + '{3}, // R59 + '{1}, // R60 + '{2}, // R61 + '{3}, // R62 + '{4} // R63 + }", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 new file mode 100644 index 0000000..38c6d2b --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 @@ -0,0 +1,77 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "V" => 4, + "ESCAP_VC_MASK" => "4'd1", + "HETERO_VC"=> "2", + "MAX_ROUTER"=>"64", + "MAX_PORT"=>"5", + "int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]"=>"'{ + //P0 P1 P2 P3 P4 + '{1, 2, 3, 4, 1}, // R0 + '{2, 3, 4, 1, 2}, // R1 + '{3, 4, 1, 2, 3}, // R2 + '{4, 1, 2, 3, 4}, // R3 + '{1, 2, 3, 4, 1}, // R4 + '{2, 3, 4, 1, 2}, // R5 + '{3, 4, 1, 2, 3}, // R6 + '{4, 1, 2, 3, 4}, // R7 + '{1, 2, 3, 4, 1}, // R8 + '{2, 3, 4, 1, 2}, // R9 + '{3, 4, 1, 2, 3}, // R10 + '{4, 1, 2, 3, 4}, // R11 + '{1, 2, 3, 4, 1}, // R12 + '{2, 3, 4, 1, 2}, // R13 + '{3, 4, 1, 2, 3}, // R14 + '{1, 2, 3, 4, 1}, // R15 + '{2, 3, 4, 1, 2}, // R16 + '{3, 4, 1, 2, 3}, // R17 + '{4, 1, 2, 3, 4}, // R18 + '{1, 2, 3, 4, 1}, // R19 + '{2, 3, 4, 1, 2}, // R20 + '{3, 4, 1, 2, 3}, // R21 + '{4, 1, 2, 3, 4}, // R22 + '{1, 2, 3, 4, 1}, // R23 + '{2, 3, 4, 1, 2}, // R24 + '{3, 4, 1, 2, 3}, // R25 + '{4, 1, 2, 3, 4}, // R26 + '{1, 2, 3, 4, 1}, // R27 + '{2, 3, 4, 1, 2}, // R28 + '{3, 4, 1, 2, 3}, // R29 + '{1, 2, 3, 4, 1}, // R30 + '{2, 3, 4, 1, 2}, // R31 + '{3, 4, 1, 2, 3}, // R32 + '{4, 1, 2, 3, 4}, // R33 + '{1, 2, 3, 4, 1}, // R34 + '{2, 3, 4, 1, 2}, // R35 + '{3, 4, 1, 2, 3}, // R36 + '{4, 1, 2, 3, 4}, // R37 + '{1, 2, 3, 4, 1}, // R38 + '{2, 3, 4, 1, 2}, // R39 + '{3, 4, 1, 2, 3}, // R40 + '{4, 1, 2, 3, 4}, // R41 + '{1, 2, 3, 4, 1}, // R42 + '{2, 3, 4, 1, 2}, // R43 + '{3, 4, 1, 2, 3}, // R44 + '{1, 2, 3, 4, 1}, // R45 + '{2, 3, 4, 1, 2}, // R46 + '{3, 4, 1, 2, 3}, // R47 + '{4, 1, 2, 3, 4}, // R48 + '{1, 2, 3, 4, 1}, // R49 + '{2, 3, 4, 1, 2}, // R50 + '{3, 4, 1, 2, 3}, // R51 + '{4, 1, 2, 3, 4}, // R52 + '{1, 2, 3, 4, 1}, // R53 + '{2, 3, 4, 1, 2}, // R54 + '{3, 4, 1, 2, 3}, // R55 + '{4, 1, 2, 3, 4}, // R56 + '{1, 2, 3, 4, 1}, // R57 + '{2, 3, 4, 1, 2}, // R58 + '{3, 4, 1, 2, 3}, // R59 + '{1, 2, 3, 4, 1}, // R60 + '{2, 3, 4, 1, 2}, // R61 + '{3, 4, 1, 2, 3}, // R62 + '{4, 1, 2, 3, 4} // R63 + }", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 new file mode 100644 index 0000000..8ad895e --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"XY\"", + "B"=> "2", + "LB"=> 2 + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_sbp6_xy b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_sbp6_xy new file mode 100644 index 0000000..8e2119a --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_sbp6_xy @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "6", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_single_flit b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_single_flit new file mode 100644 index 0000000..fb793b8 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_single_flit @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "B" => "5", + "LB" => "5", + "MIN_PCK_SIZE" => "1", + "PCK_TYPE" => " \"SINGLE_FLIT\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_ssa_xy b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_ssa_xy new file mode 100644 index 0000000..02cf843 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_ssa_xy @@ -0,0 +1,5 @@ +$model = bless( { + 'noc_param'=> { + "SSA_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy new file mode 100644 index 0000000..f75ef5b --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy @@ -0,0 +1,8 @@ +$model = bless( { + 'compile' => "verilate_mesh.sh", + 'noc_param'=> { + TOPOLOGY=>"\"RING\"", + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_XY\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/star6_2cycle_mcast_par b/mpsoc/Integration_test/verilator_lint/configurations/star6_2cycle_mcast_par new file mode 100644 index 0000000..3bf044e --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/star6_2cycle_mcast_par @@ -0,0 +1,11 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=>"\"STAR\"", + "ROUTE_NAME" =>"\"UNKNOWN\"", + "T1" => "6", + "CAST_TYPE" => "\"MULTICAST_PARTIAL\"", + "Fpay" => "32", + "MCAST_ENDP_LIST" => "'b001011", + "SELF_LOOP_EN" => "1" + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/star_6 b/mpsoc/Integration_test/verilator_lint/configurations/star_6 new file mode 100644 index 0000000..06cc862 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/star_6 @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"STAR\"", + "T1" => "6", + "T2" => "1", + "B" => "5", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy new file mode 100644 index 0000000..5ade6a7 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy @@ -0,0 +1,6 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_XY\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/run.sh b/mpsoc/Integration_test/verilator_lint/run.sh new file mode 100644 index 0000000..104c52d --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/run.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +SCRPT_FULL_PATH=$(realpath "${BASH_SOURCE[0]}") +SCRPT_DIR_PATH=$(dirname "$SCRPT_FULL_PATH") + +# Paths +conf_dir="${SCRPT_DIR_PATH}/configurations" +log_dir="${SCRPT_DIR_PATH}/result_logs" +work="${SCRPT_DIR_PATH}/work" +file_list_f="${SCRPT_DIR_PATH}/src/file_list.f" +report_file="${log_dir}/report.txt" + +mkdir -p "$work" +mkdir -p "$log_dir" +rm -rf "$report_file" +printf "%-30s | %-10s | %-10s |\n" "Configuration" "# Warnings" "# Errors" >> "$report_file" + + +# List of Verilator warnings to suppress +verilator_ignores=( + EOFNEWLINE + DECLFILENAME + PINCONNECTEMPTY +) + + +verilator_lint () { + set -e + conf=$1 + conf_file="${conf_dir}/$conf" + log_file="${log_dir}/${conf}.log" + + if [[ ! -f "$conf_file" ]]; then + echo "Configuration file $conf_file does not exist" + exit 1 + fi + + perl "${SCRPT_DIR_PATH}/src/param_gen.pl" "$conf_file" + + # Build warning suppression flags + ignore_flags="" + for warn in "${verilator_ignores[@]}"; do + ignore_flags+=" --Wno-${warn}" + done + + # Lint using Verilator + verilator --lint-only -Wall $ignore_flags -Wno-fatal -f "$file_list_f" --top-module noc_top_v > "$log_file" 2>&1 +} + +report_total_errors_warnings () { + conf="$1" + log_file="${log_dir}/${conf}.log" + warnings=$(grep '%Warning' "$log_file" | wc -l) + errors=$(grep '%Error' "$log_file" | wc -l) + printf "%-30s | %-10s | %-10s |\n" "$conf" "$warnings" "$errors" >> "$report_file" +} + +run_config () { + conf="$1" + log_file="${log_dir}/${conf}.log" + echo "▶️ Linting configuration: $conf" + if ! verilator_lint "$conf"; then + echo "❌ Linting failed for $conf (check $log_file)" + rm -f "${SCRPT_DIR_PATH}/src/noc_localparam.v" + exit 1 + else + echo "✅ Linting successful for $conf" + rm -f "${SCRPT_DIR_PATH}/src/noc_localparam.v" + report_total_errors_warnings "$conf" + fi +} + +# === Main === +if [[ "$1" == "-h" || "$1" == "--help" ]]; then + echo "Usage: bash run.sh [config_name]" + echo + echo "If [config_name] is provided, only that configuration will be processed." + echo "If no argument is given, all configurations in the 'configurations/' directory will be processed." + echo + echo "Examples:" + echo " bash run.sh # Run all configurations" + echo " bash run.sh conf1 # Run only conf1" + exit 0 +fi + +if [[ $# -eq 1 ]]; then + run_config "$1" +else + for f in "$conf_dir"/*; do + [[ -d "$f" ]] && continue + conf=$(basename "$f") + run_config "$conf" + done +fi + +echo "Report saved in $report_file" +echo "Summary:" +echo "-------------------------------|------------|------------|" +cat "$report_file" + +echo "Comparing with golden reference..." +perl "${SCRPT_DIR_PATH}/../Altera/src/compare.pl" "${SCRPT_DIR_PATH}/golden_ref/report.txt" "$report_file" +echo "All configurations processed. Results are in $report_file" + diff --git a/mpsoc/Integration_test/verilator_lint/src/file_list.f b/mpsoc/Integration_test/verilator_lint/src/file_list.f new file mode 100644 index 0000000..1f5742d --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/src/file_list.f @@ -0,0 +1,6 @@ ++incdir+./src + +-F ./../../rtl/src_noc/noc_filelist.f +-F ./../../rtl/src_topology/custom_flist.f + + diff --git a/mpsoc/Integration_test/verilator_lint/src/param_gen.pl b/mpsoc/Integration_test/verilator_lint/src/param_gen.pl new file mode 100644 index 0000000..1ad4763 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/src/param_gen.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl +package ProNOC; +use strict; +use warnings; +use File::Basename; + + +#add home dir in perl 5.6 +use FindBin; +use lib $FindBin::Bin; +use Cwd qw(realpath); + + + + +use File::Path qw(make_path); + + +use strict; +use warnings; + + + + +my $script_path = dirname(__FILE__); + +require "$script_path/../../synthetic_sim/src/src.pl"; +use lib "../synthetic_sim/src/perl_lib"; + +use constant::boolean; +use base 'Class::Accessor::Fast'; + +my $conf_file=$ARGV[0]; + + +sub create_noc_param_vv { + my ($conf_file)=@_; + my $o = do $conf_file; + die "Could not parse $conf_file: $@" if $@; + die "Could not read $conf_file: $!" unless defined $o; + my $param = $o->{'noc_param'}; + my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); + save_file("$script_path/noc_localparam.v",$param_v); +} + +create_noc_param_vv ($conf_file); diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index c2c0471..d0a8cee 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -402,7 +402,6 @@ module endp_addr_decoder ( ); import pronoc_pkg::*; - localparam NEw= log2(NE); output [NEw-1 :0] id_out; input [EAw-1 : 0] code_in; generate diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 44b1e6a..49db5cf 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -53,10 +53,8 @@ module flit_buffer localparam - Bw = (B==1)? 1 : log2(B), BV = B * V, BVw = log2(BV), - Vw = (V==1)? 1 : log2(V), DEPTHw = log2(B+1), BwV = Bw * V, BVwV = BVw * V, diff --git a/mpsoc/rtl/src_noc/multicast.sv b/mpsoc/rtl/src_noc/multicast.sv index 6005379..30e5293 100644 --- a/mpsoc/rtl/src_noc/multicast.sv +++ b/mpsoc/rtl/src_noc/multicast.sv @@ -340,11 +340,11 @@ module mcast_dest_list_decode ( genvar i; generate - if(IS_STAR) begin :star - assign mcast_dst_coded=dest_e_addr; - end else begin :no_star - assign {row_has_any_dest,mcast_dst_coded}=dest_e_addr; - end + if(IS_STAR) begin :star + assign mcast_dst_coded=dest_e_addr; + end else begin :no_star + assign {row_has_any_dest,mcast_dst_coded}=dest_e_addr; + end if(IS_MULTICAST_FULL) begin : full assign dest_o = mcast_dst_coded; assign is_unicast = 1'b0; @@ -362,36 +362,30 @@ module mcast_dest_list_decode ( ); for(i=0; i< NE; i=i+1) begin : endpoints localparam MCAST_ID = (MCAST_ENDP_LIST[i]==1'b1) ? endp_id_to_mcast_id(i): 0; - assign dest_o_multi [i] = (MCAST_ENDP_LIST[i]==1'b1)? mcast_dst_coded[MCAST_ID+1] : 1'b0; + assign dest_o_multi [i] = (MCAST_ENDP_LIST[i]==1'b1)? mcast_dst_coded[MCAST_ID+1] : 1'b0; end assign dest_o = (not_in_cast_list)? dest_o_uni : dest_o_multi; - end else if (IS_BROADCAST_FULL) begin : bcast_full wire not_broad_casted; wire [EAw-1 : 0] unicast_code; assign {unicast_code,not_broad_casted} = mcast_dst_coded; assign is_unicast = not_broad_casted; wire [NE-1 : 0] dest_o_multi; - reg [NE-1 : 0] dest_o_uni; - wire [NEw-1 : 0] unicast_id; endp_addr_decoder decoder ( .code_in(unicast_code), .id_out(unicast_id) ); assign dest_o = (not_broad_casted)? dest_o_uni : {NE{1'b1}}; - end else begin //BCAST_PARTIAL wire not_broad_casted; wire [EAw-1 : 0] unicast_code; assign {unicast_code,not_broad_casted} = mcast_dst_coded; assign is_unicast =not_broad_casted; wire [NE-1 : 0] dest_o_multi; - reg [NE-1 : 0] dest_o_uni; - wire [NEw-1 : 0] unicast_id; endp_addr_decoder decoder ( .code_in(unicast_code), .id_out(unicast_id) - ); + ); assign dest_o = (not_broad_casted)? dest_o_uni : MCAST_ENDP_LIST; end endgenerate @@ -399,7 +393,7 @@ endmodule module multicast_chan_in_process #( - parameter SW_LOC=0, + parameter SW_LOC=0, parameter P=5 )( endp_port, diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index b4165bc..131506c 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -51,7 +51,7 @@ module router_top #( output router_event_t router_event [P-1 : 0]; input clk,reset; - genvar i,j; + genvar i; flit_chanel_t r2_chan_in [P-1 : 0]; flit_chanel_t r2_chan_out [P-1 : 0]; @@ -60,23 +60,16 @@ module router_top #( ovc_info_t ovc_info [P-1 : 0][V-1 : 0]; iport_info_t iport_info [P-1 : 0]; oport_info_t oport_info [P-1 : 0]; - smart_chanel_t smart_chanel_new [P-1 : 0]; + smart_chanel_t smart_chanel_in [P-1 : 0]; - smart_chanel_t smart_chanel_out [P-1 : 0]; smart_ctrl_t smart_ctrl [P-1 : 0]; ctrl_chanel_t ctrl_in [P-1 : 0]; ctrl_chanel_t ctrl_out [P-1 : 0]; - logic [RAw-1 : 0] current_r_addr; - logic [31 : 0] current_r_id; - always_comb begin - current_r_addr = router_config_in.router_addr; - current_r_id = 0; - current_r_id [NRw-1 : 0] = router_config_in.router_id; for( int k=0; k Date: Tue, 8 Jul 2025 11:08:25 +0200 Subject: [PATCH 066/107] fix bug caused by linting fix --- mpsoc/rtl/src_noc/flit_buffer.sv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 49db5cf..44b1e6a 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -53,8 +53,10 @@ module flit_buffer localparam + Bw = (B==1)? 1 : log2(B), BV = B * V, BVw = log2(BV), + Vw = (V==1)? 1 : log2(V), DEPTHw = log2(B+1), BwV = Bw * V, BVwV = BVw * V, From 78c9a352472c26db8d0c28e519e33e9cb5e89ee9 Mon Sep 17 00:00:00 2001 From: amonemi Date: Tue, 8 Jul 2025 12:54:38 +0200 Subject: [PATCH 067/107] fix verilator linting --- mpsoc/rtl/src_noc/comb_nonspec.sv | 9 +- mpsoc/rtl/src_noc/congestion_analyzer.sv | 5 +- mpsoc/rtl/src_noc/crossbar.sv | 6 -- mpsoc/rtl/src_noc/debug.sv | 104 +++++++---------------- mpsoc/rtl/src_noc/fattree_noc_top.sv | 12 +-- mpsoc/rtl/src_noc/flit_buffer.sv | 2 - mpsoc/rtl/src_noc/inout_ports.sv | 77 ++++++++--------- mpsoc/rtl/src_noc/input_ports.sv | 24 +----- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 3 +- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 16 ++-- mpsoc/rtl/src_noc/multicast.sv | 42 ++++----- mpsoc/rtl/src_noc/router_top.sv | 11 +-- mpsoc/rtl/src_noc/router_two_stage.sv | 4 +- mpsoc/rtl/src_noc/routing.sv | 4 +- mpsoc/rtl/src_noc/ss_allocator.sv | 5 +- mpsoc/rtl/src_noc/tree_noc_top.sv | 8 +- 16 files changed, 112 insertions(+), 220 deletions(-) diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index ba25c1f..847d74a 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -88,7 +88,6 @@ module comb_nonspec_allocator # ( //internal wires switch allocator wire [PV-1 : 0] first_arbiter_granted_ivc_all; wire [PV-1 : 0] ivc_request_masked_all; - wire [P-1 : 0] any_cand_ovc_exsit; wire [PV-1 : 0] ivc_request_all; wire [PV-1 : 0] ovc_is_assigned_all; wire [PV-1 : 0] assigned_ovc_not_full_all; @@ -128,14 +127,13 @@ module comb_nonspec_allocator # ( wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; wire [V-1 : 0] ivc_local_num_getting_ovc_grant[P-1 : 0]; wire [V : 0] summ_in [PV-1 : 0]; - wire [V-1 : 0] vc_pririty [PV-1 : 0] ; assign assigned_ovc_request_all = ivc_request_all & ovc_is_assigned_all; - genvar i,j; + genvar i,j; generate // IVC loop - for(i=0;i< PV;i=i+1) begin :PV_ + for(i=0;i< PV;i=i+1) begin :PV_ // mask unavailable ovc from requests assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; assign masked_assigned_request [i] = assigned_ovc_not_full_all [i] & assigned_ovc_request_all [i]; @@ -429,8 +427,7 @@ module nonspec_sw_alloc #( PV = V * P, VP_1 = V * P_1, PP_1 = P_1 * P, - PVP_1 = PV * P_1, - PP = P*P; + PVP_1 = PV * P_1; output [PV-1 : 0] ivc_granted_all; output [P-1 : 0] granted_dst_is_from_a_single_flit_pck; diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.sv b/mpsoc/rtl/src_noc/congestion_analyzer.sv index 7ddfde7..3ebe2f1 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.sv +++ b/mpsoc/rtl/src_noc/congestion_analyzer.sv @@ -337,7 +337,6 @@ module port_pre_sel_gen #( ); import pronoc_pkg::*; localparam - P_1 = P-1, PV = P * V, CONG_ALw = CONGw * P; output [PPSw-1 : 0] port_pre_sel; @@ -399,8 +398,8 @@ module port_pre_sel_gen #( .V(V), .CONGw(CONGw) ) port_presel_gen ( - .port_pre_sel(port_pre_sel), - .congestion_in_all(congestion_in_all) + .port_pre_sel(port_pre_sel), + .congestion_in_all(congestion_in_all) ); end end diff --git a/mpsoc/rtl/src_noc/crossbar.sv b/mpsoc/rtl/src_noc/crossbar.sv index 6e15928..0bb8d6f 100755 --- a/mpsoc/rtl/src_noc/crossbar.sv +++ b/mpsoc/rtl/src_noc/crossbar.sv @@ -37,14 +37,8 @@ module crossbar #( import pronoc_pkg::*; localparam - PV = V * P, - VV = V * V, - PP = P * P, - PVV = PV * V, P_1 = (SELF_LOOP_EN )? P : P-1, - VP_1 = V * P_1, PP_1 = P_1 * P, - PVP_1 = PV * P_1, PFw = P*Fw, P_1Fw = P_1 * Fw, P_1w = log2(P_1); diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index d0a8cee..f74fdae 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -74,20 +74,8 @@ endmodule module debug_mesh_tori_route_ckeck #( - parameter T1=4, - parameter T2=4, - parameter T3=4, - parameter ROUTE_TYPE = "FULL_ADAPTIVE", - parameter V=4, - parameter AVC_ATOMIC_EN=1, - parameter SW_LOC = 0, - parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001, - parameter TOPOLOGY="MESH", - parameter DSTPw=4, - parameter RAw=4, - parameter EAw=4, - parameter DAw=EAw -)( + parameter SW_LOC=0 + )( reset, clk, hdr_flg_in, @@ -100,15 +88,7 @@ module debug_mesh_tori_route_ckeck #( src_e_addr_in, destport_in ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log20) begin // adaptive VCs if( (not_empty & vc_num_in)>0) $display("%t :Error AVC allocated nonatomicly in %d port %m",$time,SW_LOC); end @@ -208,11 +177,9 @@ module debug_mesh_tori_route_ckeck #( end//hdr_wr_in end//always end - /* verilator lint_off WIDTH */ - if(TOPOLOGY=="MESH")begin :mesh - /* verilator lint_on WIDTH */ + if( IS_MESH )begin :mesh wire [EXw-1 : 0] low_x,high_x; - wire [EYw-1 : 0] low_y,high_y; + wire [EYw-1 : 0] low_y,high_y; assign low_x = (x_src_in < x_dst_in)? x_src_in : x_dst_in; assign low_y = (y_src_in < y_dst_in)? y_src_in : y_dst_in; assign high_x = (x_src_in < x_dst_in)? x_dst_in : x_src_in; @@ -234,8 +201,6 @@ endmodule module debug_mesh_edges #( parameter T1=2, parameter T2=2, - parameter T3=3, - parameter T4=3, parameter RAw=4, parameter P=5 )( @@ -245,9 +210,9 @@ module debug_mesh_edges #( ); function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 SOUTH) begin destport_tmp [NORTH] = goto_north; destport_tmp [SOUTH] = goto_south; destport_tmp [EAST] = goto_east; destport_tmp [WEST] = goto_west; - end + end end localparam MSB_DSTP = (DSTPw-1 < SOUTH)? DSTPw-1: SOUTH; assign destport [MSB_DSTP : 0] =destport_tmp; for(i=1;i Date: Tue, 8 Jul 2025 13:04:35 +0200 Subject: [PATCH 068/107] fix verilator linting 2 --- mpsoc/rtl/src_noc/input_ports.sv | 3 +-- mpsoc/rtl/src_noc/routing.sv | 8 +++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 089f4c3..80fb3e5 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -884,8 +884,7 @@ module input_queue_per_port #( if( IS_UNICAST ) begin : unicast look_ahead_routing #( - .P(P), - .SW_LOC(SW_LOC) + .P(P) ) lk_routing ( .current_r_addr(current_r_addr), .neighbors_r_addr(neighbors_r_addr), diff --git a/mpsoc/rtl/src_noc/routing.sv b/mpsoc/rtl/src_noc/routing.sv index 68c415f..9d4253d 100755 --- a/mpsoc/rtl/src_noc/routing.sv +++ b/mpsoc/rtl/src_noc/routing.sv @@ -157,8 +157,7 @@ endmodule * look_ahead_routing *************************************/ module look_ahead_routing #( - parameter P = 5, - parameter SW_LOC = 0 + parameter P = 5 )( current_r_addr, //current router address neighbors_r_addr, @@ -185,7 +184,7 @@ module look_ahead_routing #( genvar i; generate - if(IS_MESH | IS_FMESH | IS_TORUS | IS_RING | IS_LINE) begin : mesh_torus + if(IS_REGULAR_TOPO | IS_FMESH ) begin : regular_fmesh localparam RXw = log2(NX), RYw = (IS_RING | IS_LINE) ? 1 : log2(NY), @@ -195,7 +194,6 @@ module look_ahead_routing #( wire [RYw-1 : 0] current_ry; wire [EXw-1 : 0] dest_ex; wire [EYw-1 : 0] dest_ey; - localparam SL_SW_LOC = ( SW_LOC > P-T3) ? 0 : SW_LOC; //single_local mesh_tori_router_addr_decode router_addr_decode ( .r_addr(current_r_addr), .rx(current_rx), @@ -210,7 +208,7 @@ module look_ahead_routing #( .ep( ), .valid() ); - end else begin :mesh + end else begin :regular mesh_tori_endp_addr_decode end_addr_decode ( .e_addr(dest_e_addr), .ex(dest_ex), From eb2803a3bf396ddd31d3a93c65971a63f1989234 Mon Sep 17 00:00:00 2001 From: amonemi Date: Tue, 8 Jul 2025 14:08:50 +0200 Subject: [PATCH 069/107] add verilator lint golden ref --- .../verilator_lint/golden_ref/report.txt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 mpsoc/Integration_test/verilator_lint/golden_ref/report.txt diff --git a/mpsoc/Integration_test/verilator_lint/golden_ref/report.txt b/mpsoc/Integration_test/verilator_lint/golden_ref/report.txt new file mode 100644 index 0000000..3dbdb8d --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/golden_ref/report.txt @@ -0,0 +1,40 @@ +Configuration | # Warnings | # Errors | +bintree_k3_L3_st | 120 | 0 | +custom1_topology | 119 | 0 | +Fattree_k3_L3_st | 121 | 0 | +fmesh_1x1_openpiton | 135 | 0 | +fmesh_2x2_openpiton | 142 | 0 | +fmesh_8x8_2cycle_xy | 116 | 0 | +fmesh_8x8_openpiton | 142 | 0 | +line4_smart3 | 160 | 0 | +line_4_v1_B15 | 144 | 0 | +line_8_single_flit | 138 | 0 | +mesh_2x2_openpiton | 154 | 0 | +mesh_3x3_v2_ssa | 141 | 0 | +mesh_4x4_2cycle_mcast_f | 114 | 0 | +mesh_4x4_LB5_B4 | 112 | 0 | +mesh_4x4_selflp_mcast_f | 113 | 0 | +mesh_4x4_smart3 | 138 | 0 | +mesh_4x4_v1_B15 | 131 | 0 | +mesh_4x4x2_bcast_f | 114 | 0 | +mesh_4x4x2_bcast_p | 114 | 0 | +mesh_4x4x2_mcast_p | 113 | 0 | +mesh_4x4x3_2cycle_xy | 121 | 0 | +mesh_4x4x3_vc_nonspec | 121 | 0 | +mesh_4x4x3_vc_spec1 | 123 | 0 | +mesh_4x4x3_vc_spec2 | 129 | 0 | +mesh_8x8_2cycle_adaptive | 121 | 0 | +mesh_8x8_2cycle_west_first | 128 | 0 | +mesh_8x8_2cycle_xy | 124 | 0 | +mesh_8x8_4vc | 124 | 0 | +mesh_8x8_4vc_4c | 124 | 0 | +mesh_8x8_4vc_hetero1 | 135 | 0 | +mesh_8x8_4vc_hetero2 | 135 | 0 | +mesh_8x8_b2 | 123 | 0 | +mesh_8x8_sbp6_xy | 137 | 0 | +mesh_8x8_single_flit | 125 | 0 | +mesh_8x8_ssa_xy | 144 | 0 | +ring_8x8_2cycle_xy | 132 | 0 | +star_6 | 124 | 0 | +star6_2cycle_mcast_par | 116 | 0 | +torus_8x8_2cycle_xy | 132 | 0 | From 1e1ca16ef9ceee0f047b3ddd64e87d77dcce5f19 Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 10 Jul 2025 18:05:56 +0200 Subject: [PATCH 070/107] fix verilator linting warnings 3 --- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 4 ++-- mpsoc/rtl/src_noc/router_two_stage.sv | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 0ecfbdf..86b8eb6 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -147,11 +147,11 @@ module mesh_torus_noc_top ( end // endpoint(s) connection // connect other local ports - for (l=0; l Date: Sat, 19 Jul 2025 00:54:03 +0200 Subject: [PATCH 071/107] add feature flat mode verilator simulation --- .github/workflows/main.yml | 95 +- .../configurations/failed-model/ring_3_2 | 11 + .../tiny_topos/Fattree_k3_L2_st | 9 + .../configurations/tiny_topos/Line_3x2_v2 | 13 + .../tiny_topos/fmesh_2x2_openpiton | 14 + .../tiny_topos/mesh_2x2_openpiton | 13 + .../configurations/tiny_topos/star_7 | 8 + .../tiny_topos/torus_3x2_adaptive | 8 + .../configurations/tiny_topos/tree_k3_L2_st | 9 + .../synthetic_sim/golden_ref/tiny_topos | 48 + mpsoc/Integration_test/synthetic_sim/run.sh | 16 +- .../Integration_test/synthetic_sim/src/src.pl | 46 +- .../synthetic_sim/src/verify.perl | 12 +- mpsoc/perl_gui/lib/perl/topology.pl | 38 +- mpsoc/rtl/arch/iport_reg_base.sv | 4 +- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 2 +- mpsoc/rtl/src_noc/congestion_analyzer.sv | 4 +- mpsoc/rtl/src_noc/debug.sv | 50 +- mpsoc/rtl/src_noc/fattree_route.sv | 2 +- mpsoc/rtl/src_noc/fmesh.sv | 144 +-- mpsoc/rtl/src_noc/header_flit.sv | 4 +- mpsoc/rtl/src_noc/inout_ports.sv | 4 +- mpsoc/rtl/src_noc/input_ports.sv | 33 +- mpsoc/rtl/src_noc/mesh_torus.sv | 145 +-- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 65 +- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 36 +- mpsoc/rtl/src_noc/multicast.sv | 24 +- mpsoc/rtl/src_noc/noc_top.sv | 45 +- mpsoc/rtl/src_noc/output_ports.sv | 2 +- mpsoc/rtl/src_noc/route_mesh.sv | 4 +- mpsoc/rtl/src_noc/route_torus.sv | 2 +- mpsoc/rtl/src_noc/router_bypass.sv | 4 +- mpsoc/rtl/src_noc/routing.sv | 14 +- mpsoc/rtl/src_noc/ss_allocator.sv | 2 +- mpsoc/rtl/src_noc/topology_localparam.v | 93 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 2 +- mpsoc/rtl/src_noc/tree_noc_top.sv | 4 +- mpsoc/rtl/src_openpiton/piton_mesh.sv | 10 +- mpsoc/rtl/src_openpiton/wrapper.sv | 2 +- .../synfull/traffic-generator/src/Makefile | 36 +- mpsoc/src_verilator/simulator.cpp | 34 +- mpsoc/src_verilator/simulator.h | 19 +- mpsoc/src_verilator/topology/fattree.h | 371 +++--- mpsoc/src_verilator/topology/mesh.h | 1009 ++++++++--------- mpsoc/src_verilator/topology/star.h | 41 +- mpsoc/src_verilator/topology/topology_top.h | 240 ++-- mpsoc/src_verilator/topology/tree.h | 308 ++--- mpsoc/src_verilator/traffic_synthetic.h | 2 +- 48 files changed, 1486 insertions(+), 1615 deletions(-) create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/failed-model/ring_3_2 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Fattree_k3_L2_st create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/fmesh_2x2_openpiton create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_2x2_openpiton create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/star_7 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/tree_k3_L2_st create mode 100644 mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 027a0d3..a4da3bc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,48 +1,81 @@ name: Verilator Test Suite -on: +on: push: branches: [ "**" ] jobs: - synthetic-sim: + synthetic-sim-split-mode: runs-on: ubuntu-latest container: image: verilator/verilator:4.104 - #options: --volume ${{ github.workspace }}/mpsoc_work:/mpsoc_work --volume ${{ github.workspace }}/mpsoc:/mpsoc strategy: matrix: - conf_name: [general, line-ring, multicast, vc_alloc] + conf_name: [general, line-ring, multicast, vc_alloc, tiny_topos] env: ROOT: ${{ github.workspace }}/mpsoc PRONOC_WORK: ${{ github.workspace }}/mpsoc_work GOLDEN_REF: ${{ github.workspace }}/mpsoc/Integration_test/synthetic_sim/golden_ref LOG_DIR: ${{ github.workspace }}/mpsoc/Integration_test/synthetic_sim/result_logs steps: - - uses: actions/checkout@v4 - - name: Run NoC simulation - ${{ matrix.conf_name }} - run: | - set -ex # Enable exit on error and command tracing - verilator --version - echo "Running simulation for config: ${{ matrix.conf_name }}" - echo "Workspace structure:" - ls -lR $ROOT/Integration_test/synthetic_sim/src - cd $ROOT/Integration_test/synthetic_sim/src - perl ./verify.perl -p 15 -u 80 -l 2 -s 4 -d ${{ matrix.conf_name }} - perl ./check.pl -o $GOLDEN_REF/${{ matrix.conf_name }} -n $LOG_DIR/${{ matrix.conf_name }} || { - echo "❌ Verification check failed. Please inspect the simulation logs." - exit 1 - } - - name: Upload failures artifact - ${{ matrix.conf_name }} - if: failure() # Only upload if previous step failed - uses: actions/upload-artifact@v4 - with: - name: simulation-failures-${{ matrix.conf_name }} - path: | - ${{ env.PRONOC_WORK }}/failures.txt - - name: Upload simulation reports - ${{ matrix.conf_name }} - uses: actions/upload-artifact@v4 - with: - name: simulation-reports-${{ matrix.conf_name }}-${{ github.run_id }} - path: ${{ env.LOG_DIR }} - retention-days: 7 + - uses: actions/checkout@v4 + - name: Run NoC simulation split mode - ${{ matrix.conf_name }} + run: | + set -ex + verilator --version + echo "Running simulation for config: ${{ matrix.conf_name }}" + cd $ROOT/Integration_test/synthetic_sim/src + perl ./verify.perl -p 15 -u 80 -l 2 -s 4 -d ${{ matrix.conf_name }} + perl ./check.pl -o $GOLDEN_REF/${{ matrix.conf_name }} -n $LOG_DIR/${{ matrix.conf_name }} || { + echo "❌ Verification check failed. Please inspect the simulation logs." + exit 1 + } + - name: Upload failures artifact - ${{ matrix.conf_name }} + if: failure() + uses: actions/upload-artifact@v4 + with: + name: simulation-failures-${{ matrix.conf_name }} + path: | + ${{ env.PRONOC_WORK }}/failures.txt + - name: Upload simulation reports - ${{ matrix.conf_name }} + uses: actions/upload-artifact@v4 + with: + name: simulation-reports-${{ matrix.conf_name }}-${{ github.run_id }} + path: ${{ env.LOG_DIR }} + retention-days: 7 + + tiny-topos-flat-mode: + needs: synthetic-sim-split-mode + runs-on: ubuntu-latest + container: + image: verilator/verilator:4.104 + env: + ROOT: ${{ github.workspace }}/mpsoc + PRONOC_WORK: ${{ github.workspace }}/mpsoc_work + GOLDEN_REF: ${{ github.workspace }}/mpsoc/Integration_test/synthetic_sim/golden_ref + LOG_DIR: ${{ github.workspace }}/mpsoc/Integration_test/synthetic_sim/result_logs + steps: + - uses: actions/checkout@v4 + - name: Run NoC simulation flat_mode - tiny_topos + run: | + set -ex + cd $ROOT/Integration_test/synthetic_sim/src + perl ./verify.perl -p 15 -u 80 -l 2 -s 4 -d tiny_topos -f + perl ./check.pl -o $GOLDEN_REF/tiny_topos -n $LOG_DIR/tiny_topos || { + echo "❌ flat config differs from non-flat." + exit 1 + } + - name: Upload failures artifact - flat-tiny-tops + if: failure() + uses: actions/upload-artifact@v4 + with: + name: simulation-failures-tiny_topos-flat-${{ github.run_id }} + path: | + ${{ env.PRONOC_WORK }}/failures.txt + - name: Upload simulation reports - flat-tiny-tops + uses: actions/upload-artifact@v4 + with: + name: simulation-reports-flat-tiny-tops-${{ github.run_id }} + path: ${{ env.LOG_DIR }} + retention-days: 7 + diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/ring_3_2 b/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/ring_3_2 new file mode 100644 index 0000000..4ebdb26 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/failed-model/ring_3_2 @@ -0,0 +1,11 @@ +$model = bless( { + 'compile' => "verilate_mesh.sh", + 'noc_param'=> { + TOPOLOGY=>"\"RING\"", + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_XY\"", + "T1" => "3", + "T2" => "1", + "T3" => "2", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Fattree_k3_L2_st b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Fattree_k3_L2_st new file mode 100644 index 0000000..5a0726a --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Fattree_k3_L2_st @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"FATTREE\"", + "T1" => "3", + "T2" => "2", + "B" => "6", + "ROUTE_NAME" => "\"NCA_STRAIGHT_UP\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 new file mode 100644 index 0000000..39a9863 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 @@ -0,0 +1,13 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"LINE\"", + "T1" => "3", + "T2" => "1", + "T3" => "2", + "V" => "2", + "B" => "4", + "LB" => "4", + "Fpay" => "32", + "ROUTE_NAME"=>"\"XY\"" + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/fmesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/fmesh_2x2_openpiton new file mode 100644 index 0000000..449f321 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/fmesh_2x2_openpiton @@ -0,0 +1,14 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "2", + "T2" => "2", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_2x2_openpiton new file mode 100644 index 0000000..4b61b2e --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_2x2_openpiton @@ -0,0 +1,13 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "2", + "T2" => "2", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/star_7 b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/star_7 new file mode 100644 index 0000000..2f38437 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/star_7 @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"STAR\"", + "T1" => "7", + "T2" => "1", + "B" => "5", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive new file mode 100644 index 0000000..2df56e6 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive @@ -0,0 +1,8 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_DUATO\"", + "T1" => "3", + "T2" => "2", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/tree_k3_L2_st b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/tree_k3_L2_st new file mode 100644 index 0000000..c535b87 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/tree_k3_L2_st @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TREE\"", + "T1" => "3", + "T2" => "2", + "B" => "6", + "ROUTE_NAME" => "\"NCA_STRAIGHT_UP\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos b/mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos new file mode 100644 index 0000000..1481828 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos @@ -0,0 +1,48 @@ +Verification Results: +****************************Fattree_k3_L2_st : Compile *******************************: + model is generated successfully. +****************************fmesh_2x2_openpiton : Compile *******************************: + model is generated successfully. +****************************Line_3x2_v2 : Compile *******************************: + model is generated successfully. +****************************mesh_2x2_openpiton : Compile *******************************: + model is generated successfully. + +****************************star_7 : Compile *******************************: + model is generated successfully. +****************************torus_3x2_adaptive : Compile *******************************: + model is generated successfully. +****************************tree_k3_L2_st : Compile *******************************: + model is generated successfully. +****************************Fattree_k3_L2_st : random traffic *******************************: + Passed: zero load (2,10.2953) saturation (70,87.4965) + +****************************fmesh_2x2_openpiton : random traffic *******************************: + Passed: zero load (2,8.27536) saturation (54,67.4686) +****************************Line_3x2_v2 : random traffic *******************************: + Passed: zero load (2,9.42564) saturation (50,78.1865) +****************************mesh_2x2_openpiton : random traffic *******************************: + Passed: zero load (2,9.10156) saturation (66,72.3384) + +****************************star_7 : random traffic *******************************: + Passed: zero load (2,7.12609) saturation (62,63.5408) +****************************torus_3x2_adaptive : random traffic *******************************: + Passed: zero load (2,9.92821) saturation (70,66.6712) +****************************tree_k3_L2_st : random traffic *******************************: + Passed: zero load (2,10.5671) saturation (34,57.0081) + +****************************Fattree_k3_L2_st : transposed 1 traffic *******************************: + Passed: zero load (26,9.97316) saturation (100,-) +****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: + Passed: zero load (2,8.99642) saturation (54,71.4902) +****************************Line_3x2_v2 : transposed 1 traffic *******************************: + Passed: zero load (2,9.73786) saturation (54,94.5769) +****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: + Passed: zero load (2,8.7482) saturation (100,-) + +****************************star_7 : transposed 1 traffic *******************************: + Passed: zero load (34,6.98688) saturation (100,-) +****************************torus_3x2_adaptive : transposed 1 traffic *******************************: + Passed: zero load (2,9.25728) saturation (54,79.8004) +****************************tree_k3_L2_st : transposed 1 traffic *******************************: + Passed: zero load (2,10.624) saturation (34,81.5377) diff --git a/mpsoc/Integration_test/synthetic_sim/run.sh b/mpsoc/Integration_test/synthetic_sim/run.sh index 0d3cea8..c103262 100755 --- a/mpsoc/Integration_test/synthetic_sim/run.sh +++ b/mpsoc/Integration_test/synthetic_sim/run.sh @@ -51,13 +51,11 @@ MIN=2 MAX=80 STEP=4 CONFS="general" +FLAT="" CONFS_path=$(realpath $SCRPT_DIR_PATH/configurations) - - - -while getopts "h?a:p:u:l:s:d:m:" opt; do +while getopts "h?a:p:u:l:s:d:m:f" opt; do case "$opt" in h|\?) echo " @@ -77,6 +75,9 @@ Options: Default: 5. -s Step size for increasing injection ratio in percentage (%). Default: 25. + -f Enable flat mode. Use NoC_top as the Verilator top module. + If not set, Verilator will be run on internal router modules + and they will be connected manually in testbench.c. -d

Name of the directory where simulation model configuration files are located. Default: \"$CONFS\". -m Comma-separated list of simulation model names in the @@ -123,6 +124,8 @@ Available Configuration Directories for -d Option: ;; s) STEP=$OPTARG ;; + f) FLAT="-f" + ;; d) CONFS=$OPTARG ;; m) model="-m $OPTARG" @@ -148,6 +151,9 @@ echo " Step Size : $STEP (Simulation starts at MIN and increments by" echo " STEP to reach MAX)" echo " Target Directory : $CONFS (The model target directory where simulation" echo " is running)" +if [[ $FLAT == "-f" ]]; then + echo " flat mode is enabled" +fi if [ -n "$model" ]; then echo " Model Under Test : $model (The model name under test)" fi @@ -156,7 +162,7 @@ if [ -n "$Leftovers" ]; then fi echo "---------------------------------------------" -args="-p $PRUN -u $MAX -l $MIN -s $STEP -d $CONFS $model" +args="-p $PRUN -u $MAX -l $MIN -s $STEP -d $CONFS $model $FLAT " log_dir="${SCRPT_DIR_PATH}/result_logs" log_file="${log_dir}/${CONFS}" diff --git a/mpsoc/Integration_test/synthetic_sim/src/src.pl b/mpsoc/Integration_test/synthetic_sim/src/src.pl index 07727d4..08918d3 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/src.pl +++ b/mpsoc/Integration_test/synthetic_sim/src/src.pl @@ -157,7 +157,8 @@ sub get_model_parameter { } sub gen_noc_localparam_v { - my ($m,$ref) = @_; + my ($m,$ref,$flat) = @_; + $flat//0; #if flat is 1, it use noc_top as top level modules otherwise it split verilator over internal modules my %model = %{$ref}; my %temp; @@ -176,9 +177,16 @@ sub gen_noc_localparam_v { } $param_v.="`endif\n"; my ($nr,$ne,$router_p,$ref_tops,$includ_h) = get_noc_verilator_top_modules_info($m); - my %tops = %{$ref_tops}; - $tops{Vtraffic} = "--top-module traffic_gen_top"; - $tops{Vpck_inj} = "--top-module packet_injector_verilator"; + my %tops = ( + Vtraffic => "--top-module traffic_gen_top", + Vpck_inj => "--top-module packet_injector_verilator", + ); + + if ($flat) { + $tops{Vnoc} = "--top-module noc_top_v"; + } else { + %tops = (%{$ref_tops}, %tops); # Merge ref_tops first so Vtraffic/Vpck_inj override if needed + } my $param_h=gen_noc_param_h($m); $includ_h = gen_sim_parameter_h($param_h,$includ_h,$ne,$nr,$router_p,'16'); return ($param_v,$includ_h,\%tops); @@ -245,10 +253,23 @@ sub gen_file_list{ } sub gen_verilator_sh{ - my ($ref,$file)=@_; + my ($ref,$file,$flat)=@_; my %tops = %{$ref}; my $make_lib=""; my $jobs=0; + + # List of Verilator warnings to suppress + my @verilator_ignores=( + + "UNOPTFLAT" + ); + + my $ignore_flags=""; + if($flat){ + foreach my $warn (@verilator_ignores){ + $ignore_flags .= " --Wno-${warn}"; + } + } my $cmd= '#!/bin/bash SCRPT_FULL_PATH=$(realpath ${BASH_SOURCE[0]}) SCRPT_DIR_PATH=$(dirname $SCRPT_FULL_PATH) @@ -264,7 +285,7 @@ sub gen_verilator_sh{ fi '; foreach my $top (sort keys %tops) { - $cmd.= "verilator -DNO_HETRO_IVC=1 -f \$SCRPT_DIR_PATH/file_list.f --cc $tops{$top} --prefix \"$top\" \$cmn & \n"; + $cmd.= "verilator $ignore_flags -DNO_HETRO_IVC=1 -f \$SCRPT_DIR_PATH/file_list.f --cc $tops{$top} --prefix \"$top\" \$cmn & \n"; } $cmd.="wait\n"; foreach my $top (sort keys %tops) { @@ -281,9 +302,9 @@ sub gen_verilator_sh{ cd \$SCRPT_DIR_PATH/obj_dir/ $make_lib wait - -make sim "; + $cmd.=($flat)? "make sim_flat\n" : "make sim\n"; + save_file("$file",$cmd); } @@ -322,6 +343,7 @@ sub check_models_are_exsited { sub gen_models { my ($mref, $inref) = @_; my @models = get_model_names(@_); + my ($paralel_run,$MIN,$MAX,$STEP,$model_dir,$flat) = @{$inref}; mkdir("$work", 0700); $work=realpath($work); foreach my $m (@models){ @@ -337,7 +359,7 @@ sub gen_models { my ($fname,$fpath,$fsuffix) = fileparse("$m",qr"\..[^.]*$"); my $name = $fname; my $make =$o->{'makefile'}; - my ($param_v,$include_h,$tops)= gen_noc_localparam_v( $o,$param); + my ($param_v,$include_h,$tops)= gen_noc_localparam_v($o,$param,$flat); mkdir("$work/$name", 0700); rmtree("$work/$name/obj_dir"); mkdir("$work/$name/obj_dir", 0700); @@ -345,7 +367,7 @@ sub gen_models { #generate file list gen_file_list("$work/$name"); - gen_verilator_sh($tops,"$work/$name/verilator.sh"); + gen_verilator_sh($tops,"$work/$name/verilator.sh",$flat); #copy C files my @files = File::Find::Rule->file() ->name( '*.h' ) @@ -687,6 +709,10 @@ sub gen_verilator_makefile{ sim:\ttestbench.o \$(VK_GLOBAL_OBJS) $p \$(SLIB) \t\$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 -lpthread 2>&1 | c++filt +sim_flat:\tCPPFLAGS += -DFLAT_MODE +sim_flat:\ttestbench.o \$(VK_GLOBAL_OBJS) $p \$(SLIB) +\t\$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 -lpthread 2>&1 | c++filt + testbench.o: testbench.cpp $h \$(HLIB) clean: diff --git a/mpsoc/Integration_test/synthetic_sim/src/verify.perl b/mpsoc/Integration_test/synthetic_sim/src/verify.perl index 936ccf0..5e978b4 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/verify.perl +++ b/mpsoc/Integration_test/synthetic_sim/src/verify.perl @@ -31,7 +31,7 @@ package ProNOC; # declare the perl command line flags/options we want to allow my %options=(); -getopts("hp:u:l:s:m:d:", \%options); +getopts("hp:u:l:s:m:d:f", \%options); # test for the existence of the options on the command line. # in a normal program you'd do more than just print these. @@ -55,6 +55,9 @@ package ProNOC; -l : Enter the minimum injection ratio in %. Default is 5 -s : Enter the injection step increase ratio in %. Default value is 25. + -f : Enable flat mode. Use NoC_top as the Verilator top module. + If not set, Verilator will be run on internal router modules + and they will be connected manually in testbench.c. -d : The dir name where the simulation models configuration files are located in. The default dir is \"models\" -m : Enter the @@ -79,6 +82,7 @@ package ProNOC; $MIN = $options{l} if defined $options{l}; $STEP = $options{s} if defined $options{s}; $model_dir = $options{d} if defined $options{d}; +my $flat= (defined $options{f}) ? 1 : 0; if (defined $options{m}){ @models = split(",",$options{m}); @@ -103,10 +107,10 @@ package ProNOC; require "$script_path/src.pl"; -my @inputs =($paralel_run,$MIN,$MAX,$STEP,$model_dir); +my @inputs =($paralel_run,$MIN,$MAX,$STEP,$model_dir,$flat); -print "Maximum number of parallel simulation is $paralel_run.\n The injection ratio is set as MIN=$MIN,MAX=$MAX,STEP=$STEP.\n"; +print "Maximum number of parallel simulation is $paralel_run.\n The injection ratio is set as MIN=$MIN,MAX=$MAX,STEP=$STEP, flat_mode=$flat.\n"; print "\t The simulation models are taken from $model_dir\n"; if (defined $options{m}){ foreach my $p (@models ){ @@ -128,7 +132,7 @@ package ProNOC; check_models_are_exsited(\@models,\@inputs); -my @log_report_match =("Error","Warning" ); +my @log_report_match =("Error","Warning","fatal error","error:" ); save_file ("$log_file","Verification Results:\n"); diff --git a/mpsoc/perl_gui/lib/perl/topology.pl b/mpsoc/perl_gui/lib/perl/topology.pl index b272f92..6e5e3e8 100644 --- a/mpsoc/perl_gui/lib/perl/topology.pl +++ b/mpsoc/perl_gui/lib/perl/topology.pl @@ -529,7 +529,15 @@ sub get_noc_verilator_top_modules_info { $custom_include="#define IS_${topology_name}_noc\n"; }#else - my $includ_h="\n"; + my $includ_h=" +extern void update_router_st ( + unsigned int, + unsigned int, + void * , + size_t +); + +#ifndef FLAT_MODE \n"; for (my $p=1; $p<=$router_p ; $p++){ $includ_h=$includ_h."#include \"Vrouter$p.h\" \n"; } @@ -569,7 +577,7 @@ sub get_noc_verilator_top_modules_info { $st2=$st2." router_NRs[$p] =$nr_p{$p}; - for(i=0;irouter_event[i], + sizeof(noc_top->router_event[0][0]) + ); + return; + } + +#endif //FLAT_MODE +"; #$includ_h.=" void connect_all_nodes(){\n"; diff --git a/mpsoc/rtl/arch/iport_reg_base.sv b/mpsoc/rtl/arch/iport_reg_base.sv index 2fe4a18..38ad74f 100644 --- a/mpsoc/rtl/arch/iport_reg_base.sv +++ b/mpsoc/rtl/arch/iport_reg_base.sv @@ -258,7 +258,7 @@ generate /* verilator lint_off WIDTH */ if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS") && (T3>1)) begin : multi_local /* verilator lint_on WIDTH */ - mesh_tori_endp_addr_decode endp_addr_decode + regular_topo_endp_addr_decode endp_addr_decode ( .e_addr(dest_e_addr_in), .ex( ), @@ -726,7 +726,7 @@ if(DEBUG_EN) begin :dbg if (( TOPOLOGY == "RING" || TOPOLOGY == "LINE" || TOPOLOGY == "MESH" || TOPOLOGY == "TORUS")) begin : mesh_based /* verilator lint_on WIDTH */ - debug_mesh_tori_route_ckeck #( + debug_regular_topo_route_ckeck #( .T1(T1), .T2(T2), .T3(T3), diff --git a/mpsoc/rtl/src_modelsim/traffic_pattern.sv b/mpsoc/rtl/src_modelsim/traffic_pattern.sv index b7b30ff..2da7650 100755 --- a/mpsoc/rtl/src_modelsim/traffic_pattern.sv +++ b/mpsoc/rtl/src_modelsim/traffic_pattern.sv @@ -350,7 +350,7 @@ module two_dimension_pck_dst_gen wire [NYw-1 : 0] dest_y; wire [NLw-1 : 0] dest_l; - mesh_tori_endp_addr_decode src_addr_decode ( + regular_topo_endp_addr_decode src_addr_decode ( .e_addr(current_e_addr), .ex(current_x), .ey(current_y), diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.sv b/mpsoc/rtl/src_noc/congestion_analyzer.sv index 3ebe2f1..f8312e7 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.sv +++ b/mpsoc/rtl/src_noc/congestion_analyzer.sv @@ -211,7 +211,7 @@ endmodule * port_presel_based_dst_routers_ovc * CONGESTION_INDEX==2,3,4,5,6,7,9 ********************************/ -module mesh_torus_port_presel_based_dst_routers_vc #( +module regular_topo_port_presel_based_dst_routers_vc #( parameter PPSw=4, parameter P=5, parameter CONGw=2 //congestion width per port @@ -380,7 +380,7 @@ module port_pre_sel_gen #( (CONGESTION_INDEX==9) || (CONGESTION_INDEX==11)|| (CONGESTION_INDEX==12)) begin :dst_vc - mesh_torus_port_presel_based_dst_routers_vc #( + regular_topo_port_presel_based_dst_routers_vc #( .PPSw(PPSw), .P(P), .CONGw(CONGw) diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index f74fdae..7a9ede4 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -73,7 +73,7 @@ module check_flit_chanel_type_is_in_order endmodule -module debug_mesh_tori_route_ckeck #( +module debug_regular_topo_route_ckeck #( parameter SW_LOC=0 )( reset, @@ -109,14 +109,14 @@ module debug_mesh_tori_route_ckeck #( wire [RYw-1 : 0] current_y; wire [EYw-1 : 0] y_dst_in,y_src_in; - mesh_tori_router_addr_decode r_addr_decode ( + regular_topo_router_addr_decode r_addr_decode ( .r_addr(current_r_addr), .rx(current_x), .ry(current_y), .valid() ); - mesh_tori_endp_addr_decode dst_addr_decode ( + regular_topo_endp_addr_decode dst_addr_decode ( .e_addr(dest_e_addr_in), .ex(x_dst_in), .ey(y_dst_in), @@ -124,7 +124,7 @@ module debug_mesh_tori_route_ckeck #( .valid() ); - mesh_tori_endp_addr_decode src_addr_decode ( + regular_topo_endp_addr_decode src_addr_decode ( .e_addr(src_e_addr_in), .ex(x_src_in), .ey(y_src_in), @@ -228,7 +228,7 @@ module debug_mesh_edges #( wire [RXw-1 : 0] current_rx; wire [RYw-1 : 0] current_ry; - mesh_tori_router_addr_decode addr_decode ( + regular_topo_router_addr_decode addr_decode ( .r_addr(current_r_addr), .rx(current_rx), .ry(current_ry), @@ -292,7 +292,7 @@ module check_destination_addr #( /* verilator lint_off WIDTH */ if(TOPOLOGY=="MESH" || TOPOLOGY == "TORUS" || TOPOLOGY=="RING" || TOPOLOGY == "LINE") begin : mesh /* verilator lint_on WIDTH */ - mesh_tori_endp_addr_decode endp_decode ( + regular_topo_endp_addr_decode endp_decode ( .e_addr(dest_e_addr), .ex(), .ey(), @@ -326,26 +326,13 @@ module endp_addr_encoder ( .id(id_in), .code(code_out) ); - end else if (IS_MESH | IS_TORUS | IS_RING | IS_LINE) begin : tori - mesh_tori_addr_encoder #( - .NX(T1), - .NY(T2), - .NL(T3), - .NE(NE), - .EAw(EAw), - .TOPOLOGY(TOPOLOGY) - ) addr_encoder ( + end else if (IS_REGULAR_TOPO) begin : regular + regular_topo_endp_addr_encoder addr_encoder ( .id(id_in), .code(code_out) ); end else if (IS_FMESH) begin :fmesh - fmesh_addr_encoder #( - .NX(T1), - .NY(T2), - .NL(T3), - .NE(NE), - .EAw(EAw) - ) addr_encoder ( + fmesh_addr_encoder addr_encoder ( .id(id_in), .code(code_out) ); @@ -378,26 +365,13 @@ module endp_addr_decoder ( .id(id_out), .code(code_in) ); - end else if ( IS_MESH | IS_TORUS | IS_RING | IS_LINE ) begin :tori - mesh_tori_addr_coder #( - .TOPOLOGY(TOPOLOGY), - .NX (T1 ), - .NY (T2 ), - .NL (T3 ), - .NE (NE ), - .EAw (EAw ) - ) addr_coder ( + end else if ( IS_REGULAR_TOPO ) begin : regular + regular_topo_addr_coder addr_coder ( .id (id_out), .code (code_in ) ); end else if (IS_FMESH) begin :fmesh - fmesh_addr_coder #( - .NX(T1), - .NY(T2), - .NL(T3), - .NE(NE), - .EAw(EAw) - ) addr_coder ( + fmesh_addr_coder addr_coder ( .id(id_out), .code(code_in) ); diff --git a/mpsoc/rtl/src_noc/fattree_route.sv b/mpsoc/rtl/src_noc/fattree_route.sv index 9ce6bc2..b5d3ebc 100644 --- a/mpsoc/rtl/src_noc/fattree_route.sv +++ b/mpsoc/rtl/src_noc/fattree_route.sv @@ -730,7 +730,7 @@ module fattree_addr_decoder #( endmodule /************** - * mesh_torus_ssa_check_destport_conflict + * regular_topo_ssa_check_destport_conflict * check if the incomming flit goes to SS port * ************/ module fattree_ssa_check_destport #( diff --git a/mpsoc/rtl/src_noc/fmesh.sv b/mpsoc/rtl/src_noc/fmesh.sv index 6ae6920..8d58935 100644 --- a/mpsoc/rtl/src_noc/fmesh.sv +++ b/mpsoc/rtl/src_noc/fmesh.sv @@ -1,72 +1,12 @@ `include "pronoc_def.v" /************************ * fmesh - * - * **********************/ -module fmesh_addr_encoder #( - parameter NX=2, - parameter NY=2, - parameter NL=2, - parameter NE=16, - parameter EAw=4 -)( + ***********************/ +module fmesh_addr_encoder ( id, code ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 0) 1 else 0 // partial write +// +// This ensures the FIFO is fully utilized and accounts for partially present packets. +// ------------------------------------------------------------------------- localparam - OFFSET = ((PORT_B % MIN_PCK_SIZE)>0) ? 1 : 0, - NON_ATOM_PCKS = (PORT_B > MIN_PCK_SIZE) ? (PORT_B / MIN_PCK_SIZE) + OFFSET : 1, - MAX_PCK = // min packet size is two hence the max packet number in buffer is (B/2) + OFFSET = (((PORT_B-1) % MIN_PCK_SIZE)>0) ? 1 : 0, + NON_ATOM_PCKS = (PORT_B <= MIN_PCK_SIZE) ? 1 : ((PORT_B-1) / MIN_PCK_SIZE) + OFFSET +1, + MAX_PCK = (IS_VCA_ATOMIC) ? 1 : (OVC_ALLOC_MODE) ? (NON_ATOM_PCKS + 1) : NON_ATOM_PCKS, IGNORE_SAME_LOC_RD_WR_WARNING = ((SSA_EN == 1) || (SMART_EN==1) ) ? 1 : 0; @@ -399,7 +416,7 @@ module input_queue_per_port #( .Q_out (assigned_ovc_num [(i+1)*V-1 : i*V] )); end if (IS_REGULAR_TOPO & IS_MULTI_ENDP_ROUTER & IS_UNICAST) begin - mesh_tori_endp_addr_decode endp_addr_decode ( + regular_topo_endp_addr_decode endp_addr_decode ( .e_addr(dest_e_addr_in), .ex( ), .ey( ), @@ -946,7 +963,7 @@ module input_queue_per_port #( end//for if (IS_REGULAR_TOPO & IS_UNICAST) begin : mesh_based - debug_mesh_tori_route_ckeck #( + debug_regular_topo_route_ckeck #( .SW_LOC(SW_LOC) ) route_ckeck ( @@ -1062,8 +1079,8 @@ module destp_generator #( .dest_port_in_encoded(dest_port_encoded), .dest_port_out(dest_port_out) ); - end else if( IS_REGULAR_TOPO ) begin : reqular - mesh_torus_destp_generator #( + end else if( IS_REGULAR_TOPO ) begin : regular + regular_topo_destp_generator #( .TOPOLOGY(TOPOLOGY), .ROUTE_NAME(ROUTE_NAME), .ROUTE_TYPE(ROUTE_TYPE), diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 23abdcc..1419aa6 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -1,6 +1,6 @@ `include "pronoc_def.v" /********************************************************************** -** File: mesh_torus.v +** File: regular_topo.v ** ** Copyright (C) 2014-2017 Alireza Monemi ** @@ -33,7 +33,7 @@ * ---------x * 0 | 2 ***************************/ -module mesh_torus_vc_alloc_request_gen_adaptive #( +module regular_topo_vc_alloc_request_gen_adaptive #( parameter ROUTE_TYPE = "FULL_ADAPTIVE", // "FULL_ADAPTIVE", "PAR_ADAPTIVE" parameter V = 4, parameter DSTPw=4, @@ -111,7 +111,7 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( genvar i; generate for(i=0;i< PV;i=i+1) begin : PV_ - mesh_torus_adaptive_avb_ovc_mux #( + regular_topo_adaptive_avb_ovc_mux #( .V(V) ) ovc_mux ( .ovc_avalable (ovc_avalable_perport [i/V]), @@ -123,7 +123,7 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( .masked_ovc_request (masked_ovc_request_all [((i+1)*V)-1 : i*V]) ); - mesh_torus_port_selector #( + regular_topo_port_selector #( .SW_LOC (i/V), .PPSw(PPSw) ) the_portsel ( @@ -135,7 +135,7 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( .x_evc_forbiden (x_evc_forbiden[i]) ); - mesh_tori_dspt_clear_gen #( + regular_topo_dspt_clear_gen #( .SSA_EN(SSA_EN), .DSTPw(DSTPw), .SW_LOC(i/V) @@ -153,7 +153,7 @@ module mesh_torus_vc_alloc_request_gen_adaptive #( assign candidate_ovc_x_all[((i+1)*V)-1 : i*V] = (x_evc_forbiden[i]) ? candidate_ovc_all[((i+1)*V)-1 : i*V] & (~ESCAP_VC_MASK) : candidate_ovc_all[((i+1)*V)-1 : i*V]; assign avc_unavailable[i] = (masked_ovc_request_all [((i+1)*V)-1 : i*V] & ~ESCAP_VC_MASK) == {V{1'b0}}; - mesh_torus_swap_port_presel_gen #( + regular_topo_swap_port_presel_gen #( .V(V), .ESCAP_VC_MASK(ESCAP_VC_MASK), .VC_NUM(i) @@ -178,7 +178,7 @@ endgenerate endmodule -module mesh_tori_dspt_clear_gen #( +module regular_topo_dspt_clear_gen #( parameter SSA_EN = 1, parameter DSTPw =4, parameter SW_LOC=0 @@ -220,7 +220,7 @@ module mesh_tori_dspt_clear_gen #( endmodule -module mesh_torus_mask_non_assignable_destport #( +module regular_topo_mask_non_assignable_destport #( parameter TOPOLOGY="MESH", parameter ROUTE_NAME="XY", parameter SW_LOC=0, @@ -265,7 +265,7 @@ module mesh_torus_mask_non_assignable_destport #( end endgenerate - mesh_torus_mask_non_assignable_destport_no_self_loop # ( + regular_topo_mask_non_assignable_destport_no_self_loop # ( .TOPOLOGY(TOPOLOGY), .ROUTE_NAME(ROUTE_NAME), .SW_LOC(SW_LOC), @@ -277,7 +277,7 @@ module mesh_torus_mask_non_assignable_destport #( ); endmodule -module mesh_torus_mask_non_assignable_destport_no_self_loop #( +module regular_topo_mask_non_assignable_destport_no_self_loop #( parameter TOPOLOGY="MESH", parameter ROUTE_NAME="XY", parameter SW_LOC=0, @@ -426,7 +426,7 @@ module mesh_torus_mask_non_assignable_destport_no_self_loop #( endmodule -module mesh_torus_swap_port_presel_gen #( +module regular_topo_swap_port_presel_gen #( parameter V = 4, parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000, // mask scape vc, valid only for full adaptive parameter VC_NUM=0 @@ -473,7 +473,7 @@ module mesh_torus_swap_port_presel_gen #( endmodule -module mesh_torus_adaptive_avb_ovc_mux #( +module regular_topo_adaptive_avb_ovc_mux #( parameter V= 4 )( ovc_avalable, @@ -521,7 +521,7 @@ module mesh_torus_adaptive_avb_ovc_mux #( endmodule -module mesh_torus_port_selector #( +module regular_topo_port_selector #( parameter SW_LOC = 0, parameter PPSw=4 )( @@ -592,9 +592,9 @@ endmodule /******************* -* mesh_torus_adaptive_lk_dest_encoder +* regular_topo_adaptive_lk_dest_encoder ********************/ -module mesh_torus_adaptive_lk_dest_encoder #( +module regular_topo_adaptive_lk_dest_encoder #( parameter V=4, parameter P=5, parameter DSTPw=P-1, @@ -636,7 +636,7 @@ module mesh_torus_adaptive_lk_dest_encoder #( endmodule -module mesh_torus_dtrmn_dest_encoder #( +module regular_topo_dtrmn_dest_encoder #( parameter P=5, parameter DSTPw=P-1, parameter Fw=37, @@ -673,8 +673,8 @@ module mesh_line_distance_gen ( output[DISTw-1: 0]distance; wire [NXw-1 : 0]src_x,dest_x; wire [NYw-1 : 0]src_y,dest_y; - mesh_tori_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); - mesh_tori_endp_addr_decode dst_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); + regular_topo_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); + regular_topo_endp_addr_decode dst_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); logic [NXw-1 : 0] x_offset; logic [NYw-1 : 0] y_offset; always_comb begin @@ -697,8 +697,8 @@ module ring_torus_distance_gen ( output[DISTw-1: 0]distance; wire [NXw-1 : 0]src_x,dest_x; wire [NYw-1 : 0]src_y,dest_y; - mesh_tori_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); - mesh_tori_endp_addr_decode dest_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); + regular_topo_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); + regular_topo_endp_addr_decode dest_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); logic [NXw-1 : 0] x_offset; logic [NYw-1 : 0] y_offset; wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y; @@ -749,7 +749,7 @@ module ring_torus_distance_gen ( endmodule -module mesh_torus_ssa_check_destport #( +module regular_topo_ssa_check_destport #( parameter ROUTE_TYPE="DETERMINISTIC", parameter SW_LOC = 0, parameter P=5, @@ -854,7 +854,7 @@ module line_ring_ssa_check_destport #( endmodule -module mesh_tori_router_addr_decode ( +module regular_topo_router_addr_decode ( r_addr, rx, ry, @@ -889,7 +889,7 @@ module mesh_tori_router_addr_decode ( endmodule -module mesh_tori_endp_addr_decode +module regular_topo_endp_addr_decode ( e_addr, ex, @@ -949,46 +949,16 @@ endmodule /************** -* mesh_tori_addr_encoder +* Regular_topo_endp_addr_encoder * most probably it is only needed for simulation purposes ***************/ -module mesh_tori_addr_encoder #( - parameter NX=2, - parameter NY=2, - parameter NL=2, - parameter NE=16, - parameter EAw=4, - parameter TOPOLOGY="MESH" -)( +module regular_topo_endp_addr_encoder +( id, code ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 2) begin : local_ports assign goes_straight_o = 1'b0; // There is not a next router in this case at all diff --git a/mpsoc/rtl/src_noc/routing.sv b/mpsoc/rtl/src_noc/routing.sv index 9d4253d..c796f15 100755 --- a/mpsoc/rtl/src_noc/routing.sv +++ b/mpsoc/rtl/src_noc/routing.sv @@ -47,7 +47,7 @@ module conventional_routing #( output [DSTPw-1 :0] destport; generate - if( IS_MESH | IS_FMESH | IS_TORUS | IS_RING | IS_LINE ) begin : mesh_torus + if( IS_MESH | IS_FMESH | IS_TORUS | IS_RING | IS_LINE ) begin : regular_topo localparam RXw = log2(NX), RYw = (IS_RING | IS_LINE) ? 1 :log2(NY), @@ -58,7 +58,7 @@ module conventional_routing #( wire [EXw-1 : 0] dest_ex; wire [EYw-1 : 0] dest_ey; - mesh_tori_router_addr_decode router_addr_decode ( + regular_topo_router_addr_decode router_addr_decode ( .r_addr(current_r_addr), .rx(current_rx), .ry(current_ry), @@ -73,7 +73,7 @@ module conventional_routing #( .valid() ); end else begin : mesh - mesh_tori_endp_addr_decode end_addr_decode ( + regular_topo_endp_addr_decode end_addr_decode ( .e_addr(dest_e_addr), .ex(dest_ex), .ey(dest_ey), @@ -81,7 +81,7 @@ module conventional_routing #( .valid() ); end//mesh - mesh_torus_conventional_routing #( + regular_topo_conventional_routing #( .LOCATED_IN_NI(LOCATED_IN_NI) ) the_conventional_routing ( .current_x(current_rx), @@ -194,7 +194,7 @@ module look_ahead_routing #( wire [RYw-1 : 0] current_ry; wire [EXw-1 : 0] dest_ex; wire [EYw-1 : 0] dest_ey; - mesh_tori_router_addr_decode router_addr_decode ( + regular_topo_router_addr_decode router_addr_decode ( .r_addr(current_r_addr), .rx(current_rx), .ry(current_ry), @@ -209,7 +209,7 @@ module look_ahead_routing #( .valid() ); end else begin :regular - mesh_tori_endp_addr_decode end_addr_decode ( + regular_topo_endp_addr_decode end_addr_decode ( .e_addr(dest_e_addr), .ex(dest_ex), .ey(dest_ey), @@ -217,7 +217,7 @@ module look_ahead_routing #( .valid() ); end - mesh_torus_look_ahead_routing lkh_route ( + regular_topo_look_ahead_routing lkh_route ( .current_x(current_rx), .current_y(current_ry), .dest_x(dest_ex), diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index e8c022e..8f5a408 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -370,7 +370,7 @@ module ssa_check_destport #( .ss_port_nonhdr_flit(ss_port_nonhdr_flit) ); end else if (IS_MESH | IS_TORUS ) begin : mesh - mesh_torus_ssa_check_destport #( + regular_topo_ssa_check_destport #( .ROUTE_TYPE(ROUTE_TYPE), .SW_LOC(SW_LOC), .P(P), diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index d3c045f..2a3f5e7 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -139,10 +139,8 @@ endfunction /******************* - * "RING" "LINE" "MESH" TORUS" "FMESH" + * REGULAR_TOPO: "RING" "LINE" "MESH" TORUS" "FMESH" ******************/ - /* verilator lint_off WIDTH */ - //route type localparam NX = T1, NY = (IS_RING | IS_LINE) ? 1 : T2, @@ -150,34 +148,34 @@ NXw = log2(NX), NYw = log2(NY), NLw = log2(NL), - PPSw_MESH_TORI = 4, //port presel width for adaptive routing + PPSw_REGULAR = 4, //port presel width for adaptive routing /* verilator lint_off WIDTH */ - ROUTE_TYPE_MESH_TORI = + ROUTE_TYPE_REGULAR = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", /* verilator lint_on WIDTH */ - R2R_CHANELS_MESH_TORI= (IS_RING || IS_LINE)? 2 : 4, - R2E_CHANELS_MESH_TORI= NL, - RAw_MESH_TORI = ( IS_RING | IS_LINE)? NXw : NXw + NYw, - EAw_MESH_TORI = (NL==1) ? RAw_MESH_TORI : RAw_MESH_TORI + NLw, - NR_MESH_TORI = (IS_RING || IS_LINE)? NX : NX*NY, - NE_MESH_TORI = NR_MESH_TORI * NL, - MAX_P_MESH_TORI = R2R_CHANELS_MESH_TORI + R2E_CHANELS_MESH_TORI, - DSTPw_MESH_TORI = R2R_CHANELS_MESH_TORI, // P-1 - NE_PER_R_MESH_TORI = NL; - + R2R_CHANELS_REGULAR= (IS_RING || IS_LINE)? 2 : 4, + R2E_CHANELS_REGULAR= NL, + RAw_REGULAR = ( IS_RING | IS_LINE)? NXw : NXw + NYw, + EAw_REGULAR = (NL==1) ? RAw_REGULAR : RAw_REGULAR + NLw, + NR_REGULAR = (IS_RING || IS_LINE)? NX : NX*NY, + NE_REGULAR = NR_REGULAR * NL, + MAX_P_REGULAR = R2R_CHANELS_REGULAR + R2E_CHANELS_REGULAR, + DSTPw_REGULAR = R2R_CHANELS_REGULAR, // P-1 + NE_PER_R_REGULAR = NL; /**************** * FMESH **************/ localparam - NE_FMESH = NE_MESH_TORI + 2 * (NX+NY), - NR_FMESH = NR_MESH_TORI, + NE_FMESH = NE_REGULAR + 2 * (NX+NY), + NR_FMESH = NR_REGULAR, MAX_P_FMESH = 4 + NL, - EAw_FMESH = RAw_MESH_TORI + log2(MAX_P_FMESH); + EAw_FMESH = RAw_REGULAR + log2(MAX_P_FMESH), + NE_PER_R_FMESH = ((NX == 1) || (NY == 1)) ? NL + 3 : NL + 2; // 2 for the edge ports; /****************** - * FATTREE - * *****************/ + * FATTREE + ******************/ localparam K=T1, L=T2, @@ -245,13 +243,13 @@ DSTPw_MULTI_MESH = log2(MAX_P_MULTI_MESH); localparam - PPSw = PPSw_MESH_TORI, + PPSw = PPSw_REGULAR, // maximum number of port in a router in the topology MAX_P = (IS_FATTREE)? MAX_P_FATTREE: (IS_TREE)? MAX_P_TREE: - (IS_REGULAR_TOPO)? MAX_P_MESH_TORI: - (IS_FMESH)? MAX_P_MESH_TORI: + (IS_REGULAR_TOPO)? MAX_P_REGULAR: + (IS_FMESH)? MAX_P_REGULAR: (IS_STAR) ? MAX_P_STAR: (IS_MULTI_MESH) ? MAX_P_MULTI_MESH: MAX_P_CUSTOM, @@ -261,8 +259,8 @@ (IS_FATTREE)? DSTPw_FATTREE : (IS_TREE)? DSTPw_TREE : (~IS_UNICAST) ? MAX_P : - (IS_REGULAR_TOPO)? DSTPw_MESH_TORI : - (IS_FMESH)? DSTPw_MESH_TORI : + (IS_REGULAR_TOPO)? DSTPw_REGULAR : + (IS_FMESH)? DSTPw_REGULAR : (IS_STAR) ? DSTPw_STAR : (IS_MULTI_MESH) ? DSTPw_MULTI_MESH : DSTPw_CUSTOM, @@ -270,8 +268,8 @@ RAw = (IS_FATTREE)? RAw_FATTREE: (IS_TREE)? RAw_TREE: - (IS_REGULAR_TOPO)? RAw_MESH_TORI: - (IS_FMESH)? RAw_MESH_TORI: + (IS_REGULAR_TOPO)? RAw_REGULAR: + (IS_FMESH)? RAw_REGULAR: (IS_STAR) ? RAw_STAR: (IS_MULTI_MESH) ? RAw_MULTI_MESH: RAw_CUSTOM, @@ -279,7 +277,7 @@ EAw = (IS_FATTREE)? EAw_FATTREE: (IS_TREE)? EAw_TREE: - (IS_REGULAR_TOPO)? EAw_MESH_TORI: + (IS_REGULAR_TOPO)? EAw_REGULAR: (IS_FMESH)? EAw_FMESH: (IS_STAR) ? EAw_STAR: (IS_MULTI_MESH) ? EAw_MULTI_MESH: @@ -288,7 +286,7 @@ NE = (IS_FATTREE)? NE_FATTREE: (IS_TREE)? NE_TREE: - (IS_REGULAR_TOPO)? NE_MESH_TORI: + (IS_REGULAR_TOPO)? NE_REGULAR: (IS_FMESH)? NE_FMESH: (IS_STAR)? NE_STAR: (IS_MULTI_MESH) ? NE_MULTI_MESH: @@ -298,8 +296,8 @@ NE_PER_R = (IS_FATTREE)? NE_PER_R_FATTREE: (IS_TREE)? NE_PER_R_TREE: - (IS_REGULAR_TOPO)? NE_PER_R_MESH_TORI: - (IS_FMESH)? NE_PER_R_MESH_TORI: + (IS_REGULAR_TOPO)? NE_PER_R_REGULAR: + (IS_FMESH)? NE_PER_R_FMESH: (IS_STAR)? NE_PER_R_STAR: (IS_MULTI_MESH) ? 1: NE_PER_R_CUSTOM, @@ -319,7 +317,7 @@ NR = (IS_FATTREE)? NR_FATTREE: (IS_TREE)? NR_TREE: - (IS_REGULAR_TOPO)? NR_MESH_TORI: + (IS_REGULAR_TOPO)? NR_REGULAR: (IS_FMESH)? NR_FMESH: (IS_STAR) ? NR_STAR: (IS_MULTI_MESH) ? NR_MULTI_MESH: @@ -328,8 +326,8 @@ ROUTE_TYPE = (IS_FATTREE)? ROUTE_TYPE_FATTREE: (IS_TREE)? ROUTE_TYPE_TREE: - (IS_REGULAR_TOPO)? ROUTE_TYPE_MESH_TORI: - (IS_FMESH)? ROUTE_TYPE_MESH_TORI: + (IS_REGULAR_TOPO)? ROUTE_TYPE_REGULAR: + (IS_FMESH)? ROUTE_TYPE_REGULAR: (IS_STAR) ? ROUTE_TYPE_STAR: ROUTE_TYPE_CUSTOM; /* verilator lint_off WIDTH */ @@ -387,18 +385,29 @@ end endfunction - function automatic integer fmesh_addrencode; - input integer addr_in; + function automatic integer regular_topo_endp_addr; + input integer endp_id; + integer y, x, l,p, diff,mul; + begin + y = ((endp_id/NL) / NX ); + x = ((endp_id/NL) % NX ); + l = (endp_id % NL); + regular_topo_endp_addr = ( l << ( NXw+NYw) | (y< K)? K : MAX_P; + localparam BOUND = ( MAX_P > K ) ? K : MAX_P; assign current_layer_addr [ROOT_ID] = ROOT_L; assign current_pos_addr [ROOT_ID] = {LKw{1'b0}}; diff --git a/mpsoc/rtl/src_openpiton/piton_mesh.sv b/mpsoc/rtl/src_openpiton/piton_mesh.sv index 21e23d3..63b021b 100644 --- a/mpsoc/rtl/src_openpiton/piton_mesh.sv +++ b/mpsoc/rtl/src_openpiton/piton_mesh.sv @@ -138,12 +138,12 @@ module piton_mesh // connect other local ports for (l=0; l #include #include +#ifdef FLAT_MODE +#include "Vnoc.h" +#endif + #include "simulator.h" int main(int argc, char** argv) { @@ -29,8 +33,11 @@ int main(int argc, char** argv) { class_percentage = (int *) malloc(sizeof(int)); class_percentage[0]=100; } - + #ifdef FLAT_MODE + noc_top = new Vnoc; + #else Vrouter_new(); + #endif if (ENDP_TYPE == PCK_INJECTOR) for(i=0;irouter_event[0][0] & ACTIVE_HIGH_RST)!=0) ? 1 : 0; + #else reset_active_high = ((router1[0]->router_event[0] & ACTIVE_HIGH_RST)!=0) ? 1 : 0; + #endif if (main_time-saved_time >= 10 ) reset = (reset_active_high)? 0 :1; else reset = reset_active_high; ;//keep system in reset if(main_time == saved_time+21){ count_en=1; start_i=1;} @@ -755,6 +766,13 @@ class alignas(64) Vthread traffic[node]->clk = clk; } }//endp + #ifdef FLAT_MODE + if(n==0){// + noc_top->reset= reset; + noc_top->clk = clk; + noc_top->eval(); + } + #else for(i=0;i= NR) break; @@ -768,6 +786,7 @@ class alignas(64) Vthread //if(router_is_active[node] | (Quick_sim_en==0)) single_router_eval(node); } + #endif for(i=0;i= NE) break; @@ -856,10 +875,14 @@ void sim_eval_all (void){ }else{// no thread connect_clk_reset_start_all(); //routers_eval(); + #ifdef FLAT_MODE + noc_top->eval(); + #else for(i=0;ieval(); else for(i=0;ieval(); } @@ -886,7 +909,11 @@ void topology_connect_all_nodes (void){ void sim_final_all (void){ int i; + #ifdef FLAT_MODE + noc_top->final(); + #else routers_final(); + #endif if(ENDP_TYPE == PCK_INJECTOR) for(i=0;ifinal(); else for(i=0;ifinal(); //noc->final(); @@ -909,7 +936,12 @@ void connect_clk_reset_start_all(void){ traffic[i]->clk = clk; } } + #ifdef FLAT_MODE + noc_top->reset= reset; + noc_top->clk=clk; + #else connect_routers_reset_clk(); + #endif } void traffic_clk_negedge_event(void){ diff --git a/mpsoc/src_verilator/simulator.h b/mpsoc/src_verilator/simulator.h index 896a307..6aaf36f 100644 --- a/mpsoc/src_verilator/simulator.h +++ b/mpsoc/src_verilator/simulator.h @@ -81,11 +81,11 @@ int get_router_num (int , int ); #define pck_active_port packet_injector_verilator__DOT__endp_is_active #define traffic_active_port traffic_gen_top__DOT__endp_is_active + +#ifndef FLAT_MODE #define CHAN_SIZE sizeof(router1[0]->chan_in[0]) - #define conect_r2r(T1,r1,p1,T2,r2,p2) \ memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE ) - // router_is_active[get_router_num(T1,r1)] |=(( router##T1 [r1]-> ideal_port!=0) | (router##T2 [r2]-> active_port[p2]==1)) #define connect_r2gnd(T,r,p)\ @@ -99,7 +99,16 @@ int get_router_num (int , int ); memcpy(&router##T [r]->chan_in[p], addr1, CHAN_SIZE );\ memcpy(addr2, &router##T [r]->chan_out[p], CHAN_SIZE ) - +#else + #define CHAN_SIZE sizeof(noc_top->chan_in_all[0]) + #define conect_r2r(T1,r1,p1,T2,r2,p2) while(0) + #define connect_r2e(T,r,p,e) \ + void * addr1, * addr2;\ + addr1=(ENDP_TYPE == PCK_INJECTOR)? &pck_inj[e]->chan_out : &traffic[e]->chan_out;\ + addr2=(ENDP_TYPE == PCK_INJECTOR)? &pck_inj[e]->chan_in : &traffic[e]->chan_in;\ + memcpy(&noc_top->chan_in_all[e], addr1, CHAN_SIZE );\ + memcpy(addr2, &noc_top->chan_out_all[e], CHAN_SIZE ) +#endif @@ -122,7 +131,9 @@ int reset,clk; Vtraffic *traffic[NE]; // for synthetic and trace traffic pattern Vpck_inj *pck_inj[NE]; // for netrace - +#ifdef FLAT_MODE +Vnoc *noc_top; // for flat mode +#endif unsigned char reset_active_high=1; diff --git a/mpsoc/src_verilator/topology/fattree.h b/mpsoc/src_verilator/topology/fattree.h index e16d878..c21a753 100644 --- a/mpsoc/src_verilator/topology/fattree.h +++ b/mpsoc/src_verilator/topology/fattree.h @@ -1,247 +1,202 @@ #ifndef FATTREE_H - #define FATTREE_H - - - -unsigned int Lw; -unsigned int Kw; -unsigned int LKw; -unsigned int RAw_FATTREE; -unsigned int EAw_FATTREE; -unsigned int NE_FATTREE; -unsigned int NR_FATTREE; -unsigned int DSTPw_FATTREE ; -unsigned int MAX_P_FATTREE ; - - +#define FATTREE_H + +unsigned int Lw; +unsigned int Kw; +unsigned int LKw; +unsigned int RAw_FATTREE; +unsigned int EAw_FATTREE; +unsigned int NE_FATTREE; +unsigned int NR_FATTREE; +unsigned int DSTPw_FATTREE; +unsigned int MAX_P_FATTREE; unsigned int NPOS = powi( K, L-1); unsigned int CHAN_PER_DIRECTION = (K * powi( L , L-1 )); //up or down -unsigned int CHAN_PER_LEVEL = 2*(K * powi( K , L-1 )); //up+down - - - - - - +unsigned int CHAN_PER_LEVEL = 2 * (K * powi( K , L-1 )); //up+down +#ifndef FLAT_MODE inline void fatree_local_addr (unsigned int t1, unsigned int r1, unsigned int addr, unsigned int id){ - if (t1==1 ){ - router1[r1]->current_r_addr = addr; - router1[r1]->current_r_id = id; - } - else{ - router2[r1]->current_r_addr = addr; - router2[r1]->current_r_id = id; - } - + if (t1==1 ){ + router1[r1]->current_r_addr = addr; + router1[r1]->current_r_id = id; + } + else{ + router2[r1]->current_r_addr = addr; + router2[r1]->current_r_id = id; + } } - +#endif //FLAT_MODE unsigned int fattree_addrencode( unsigned int pos, unsigned int k, unsigned int l){ - unsigned int pow,i,tmp=0; - unsigned int addrencode=0; - unsigned int kw=0; - while((0x1<>=kw; - } - return pos; + unsigned int kw=0; + unsigned int mask=0; + unsigned int pow,i,tmp; + unsigned int pos=0; + while((0x1<>=kw; + } + return pos; } unsigned int endp_addr_encoder ( unsigned int id){ - return fattree_addrencode(id, T1, T2); + return fattree_addrencode(id, T1, T2); } unsigned int endp_addr_decoder (unsigned int code){ - return fattree_addrdecode(code, T1, T2); + return fattree_addrdecode(code, T1, T2); } - void topology_init (void){ - unsigned int pos,level,port; - - Lw= Log2(L); - Kw=Log2(K); - LKw=L*Kw; - RAw_FATTREE = LKw + Lw; - EAw_FATTREE = LKw; - NE_FATTREE = powi( K,L ); - NR_FATTREE = L * powi( K , L - 1 ); // total number of routers - DSTPw_FATTREE = K+1; - MAX_P_FATTREE = 2*K; - #define NRL (NE/K) //number of router in each layer - + unsigned int pos,level,port; + Lw= Log2(L); + Kw=Log2(K); + LKw=L*Kw; + RAw_FATTREE = LKw + Lw; + EAw_FATTREE = LKw; + NE_FATTREE = powi( K,L ); + NR_FATTREE = L * powi( K , L - 1 ); // total number of routers + DSTPw_FATTREE = K+1; + MAX_P_FATTREE = 2*K; + #define NRL (NE/K) //number of router in each layer unsigned int num = 0; - //connect all down input chanels - for (level = 0; level>=nxw; - (*y) = code & masky; - code>>=nyw; - (*l) = code; - } - - void ring_line_addr_sep(unsigned int code, unsigned int *x, unsigned int *l){ - (*x) = code & maskx; - code>>=nxw; - (*l) = code; - } - - unsigned int mesh_tori_addr_join(unsigned int x, unsigned int y, unsigned int l){ - unsigned int addrencode=0; - addrencode =(T3==1)? (y<>=nxw; + (*y) = code & masky; + code>>=nyw; + (*l) = code; + } + + void ring_line_addr_sep(unsigned int code, unsigned int *x, unsigned int *l){ + (*x) = code & maskx; + code>>=nxw; + (*l) = code; + } + + unsigned int mesh_tori_addr_join(unsigned int x, unsigned int y, unsigned int l){ + unsigned int addrencode=0; + addrencode =(T3==1)? (y< SOUTH) return ((y*T1)+x)*T3+(p-SOUTH); - if(p== NORTH) return ((T1*T2*T3) + x); - if(p== SOUTH) return ((T1*T2*T3) + T1 + x); - if(p== WEST ) return ((T1*T2*T3) + 2*T1 + y); - if(p== EAST ) return ((T1*T2*T3) + 2*T1 + T2 + y); - return 0;//should not reach here - } - - - - - - - unsigned int mesh_tori_endp_addr_decoder (unsigned int code){ - unsigned int x, y, l; - mesh_tori_addr_sep(code,&x,&y,&l); - //if(code==0x1a) printf("code=%x,x=%u,y=%u,l=%u\n",code,x,y,l); - return ((y*T1)+x)*T3+l; - } - - unsigned int ring_line_endp_addr_decoder (unsigned int code){ - unsigned int x, l; - ring_line_addr_sep(code,&x,&l); - //if(code==0x1a) printf("code=%x,x=%u,y=%u,l=%u\n",code,x,y,l); - return x*T3+l; - } - - - - - unsigned int endp_addr_encoder ( unsigned int id){ - #if defined (IS_MESH) || defined (IS_TORUS) - return mesh_tori_addrencode(id); - #elif defined (IS_LINE) || defined (IS_RING ) - return ring_line_addrencode(id); - #else - return fmesh_addrencode(id); - #endif - } - - - unsigned int endp_addr_decoder (unsigned int code){ - #if defined (IS_MESH) || defined (IS_TORUS) - return mesh_tori_endp_addr_decoder (code); - #elif defined (IS_LINE) || defined (IS_RING ) - return ring_line_endp_addr_decoder (code); - #endif - return fmesh_endp_addr_decoder (code); - } - - -void topology_connect_r2r (int n){ - conect_r2r(1,r2r_cnt_all[n].r1,r2r_cnt_all[n].p1,1,r2r_cnt_all[n].r2,r2r_cnt_all[n].p2); -} - -void topology_connect_r2e (int n){ - connect_r2e(1,r2e_cnt_all[n].r1,r2e_cnt_all[n].p1,n); -} - - - - - - - - - + unsigned int addrencode=0; + addrencode =(T3==1)? x : (l< SOUTH) return ((y*T1)+x)*T3+(p-SOUTH); + if(p== NORTH) return ((T1*T2*T3) + x); + if(p== SOUTH) return ((T1*T2*T3) + T1 + x); + if(p== WEST ) return ((T1*T2*T3) + 2*T1 + y); + if(p== EAST ) return ((T1*T2*T3) + 2*T1 + T2 + y); + return 0;//should not reach here + } + + unsigned int mesh_tori_endp_addr_decoder (unsigned int code){ + unsigned int x, y, l; + mesh_tori_addr_sep(code,&x,&y,&l); + //if(code==0x1a) printf("code=%x,x=%u,y=%u,l=%u\n",code,x,y,l); + return ((y*T1)+x)*T3+l; + } + + unsigned int ring_line_endp_addr_decoder (unsigned int code){ + unsigned int x, l; + ring_line_addr_sep(code,&x,&l); + //if(code==0x1a) printf("code=%x,x=%u,y=%u,l=%u\n",code,x,y,l); + return x*T3+l; + } + + unsigned int endp_addr_encoder ( unsigned int id){ + #if defined (IS_MESH) || defined (IS_TORUS) + return mesh_tori_addrencode(id); + #elif defined (IS_LINE) || defined (IS_RING ) + return ring_line_addrencode(id); + #else + return fmesh_addrencode(id); + #endif + } + + unsigned int endp_addr_decoder (unsigned int code){ + #if defined (IS_MESH) || defined (IS_TORUS) + return mesh_tori_endp_addr_decoder (code); + #elif defined (IS_LINE) || defined (IS_RING ) + return ring_line_endp_addr_decoder (code); + #endif + return fmesh_endp_addr_decoder (code); + } + + void topology_connect_r2r (int n){ + conect_r2r(1,r2r_cnt_all[n].r1,r2r_cnt_all[n].p1,1,r2r_cnt_all[n].r2,r2r_cnt_all[n].p2); + } + + void topology_connect_r2e (int n){ + connect_r2e(1,r2e_cnt_all[n].r1,r2e_cnt_all[n].p1,n); + } + +/* void topology_connect_all_nodes_old (void){ - - - unsigned int x,y,l; - #if defined (IS_LINE) || defined (IS_RING ) - #define R2R_CHANELS_MESH_TORI 2 - for (x=0; xcurrent_r_addr = x; - router1[x]->current_r_id = x; - if(x < T1-1){// not_last_node - //assign router_chan_in[x][FORWARD] = router_chan_out [(x+1)][BACKWARD]; - conect_r2r(1,x,FORWARD,1,(x+1),BACKWARD); - - } else { //last_node - - #if defined (IS_LINE) // : line_last_x - //assign router_chan_in[x][FORWARD]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,FORWARD); - #else // : ring_last_x - //assign router_chan_in[x][FORWARD]= router_chan_out [0][BACKWARD]; - conect_r2r(1,x,FORWARD,1,0,BACKWARD); - #endif - } - - if(x>0){// :not_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; - conect_r2r(1,x,BACKWARD,1,(x-1),FORWARD); - - }else {// :first_x - #if defined (IS_LINE) // : line_first_x - //assign router_chan_in[x][BACKWARD]={SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,BACKWARD); - #else // : ring_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; - conect_r2r(1,x,BACKWARD,1,(T1-1),FORWARD); - #endif - } - - // connect other local ports - for (l=0; lcurrent_r_addr = R_ADDR; - router1[ROUTER_NUM]->current_r_id = ROUTER_NUM; - - if(x < T1-1) {//: not_last_x - //assign router_chan_in[`router_id(x,y)][EAST]= router_chan_out [`router_id(x+1,y)][WEST]; - conect_r2r(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); - - }else {// :last_x - #if defined (IS_MESH) // :last_x_mesh - // assign router_chan_in[`router_id(x,y)][EAST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),EAST); - #elif defined (IS_TORUS) // : last_x_torus - //assign router_chan_in[`router_id(x,y)][EAST] = router_chan_out [`router_id(0,y)][WEST]; - conect_r2r(1,router_id(x,y),EAST,1,router_id(0,y),WEST); - #elif defined (IS_FMESH) //:last_x_fmesh - //connect to endp - unsigned int EAST_ID = T1*T2*T3 + 2*T1 + T2 + y; - connect_r2e(1,router_id(x,y),EAST,EAST_ID); - er_addr [EAST_ID] = R_ADDR; - #endif//topology - } - - - if(y>0) {// : not_first_y - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; - conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); - }else {// :first_y - #if defined (IS_MESH) // : first_y_mesh - //assign router_chan_in[`router_id(x,y)][NORTH] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),NORTH); - #elif defined (IS_TORUS)// :first_y_torus - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(T2-1))][SOUTH]; - conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); - #elif defined (IS_FMESH) // :first_y_fmesh - unsigned int NORTH_ID = T1*T2*T3 + x; - connect_r2e(1,router_id(x,y),NORTH,NORTH_ID); - er_addr [NORTH_ID] = R_ADDR; - #endif//topology - }//y>0 - - - if(x>0){// :not_first_x - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; - conect_r2r(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); - }else {// :first_x - - #if defined (IS_MESH) // :first_x_mesh - //assign router_chan_in[`router_id(x,y)][WEST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),WEST); - - #elif defined (IS_TORUS) // :first_x_torus - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; - conect_r2r(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); - #elif defined (IS_FMESH) // :first_x_fmesh - unsigned int WEST_ID = T1*T2*T3 + 2*T1 + y; - connect_r2e(1,router_id(x,y),WEST,WEST_ID); - er_addr [WEST_ID] = R_ADDR; - #endif//topology - } - - if(y < T2-1) {// : firsty - //assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; - conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); - }else {// : lasty - - #if defined (IS_MESH) // :ly_mesh - - //assign router_chan_in[`router_id(x,y)][SOUTH]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),SOUTH); - - #elif defined (IS_TORUS) // :ly_torus - //assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; - conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); - #elif defined (IS_FMESH) // :ly_Fmesh - unsigned int SOUTH_ID = T1*T2*T3 + T1 + x; - connect_r2e(1,router_id(x,y),SOUTH,SOUTH_ID); - er_addr [SOUTH_ID] = R_ADDR; - #endif//topology - } - - - // endpoint(s) connection - // connect other local ports - for (l=0; lcurrent_r_addr = x; + router1[x]->current_r_id = x; + if(x < T1-1){// not_last_node + //assign router_chan_in[x][FORWARD] = router_chan_out [(x+1)][BACKWARD]; + conect_r2r(1,x,FORWARD,1,(x+1),BACKWARD); + } else { //last_node + + #if defined (IS_LINE) // : line_last_x + //assign router_chan_in[x][FORWARD]= {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,x,FORWARD); + #else // : ring_last_x + //assign router_chan_in[x][FORWARD]= router_chan_out [0][BACKWARD]; + conect_r2r(1,x,FORWARD,1,0,BACKWARD); + #endif + } + if(x>0){// :not_first_x + //assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; + conect_r2r(1,x,BACKWARD,1,(x-1),FORWARD); + + }else {// :first_x + #if defined (IS_LINE) // : line_first_x + //assign router_chan_in[x][BACKWARD]={SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,x,BACKWARD); + #else // : ring_first_x + //assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; + conect_r2r(1,x,BACKWARD,1,(T1-1),FORWARD); + #endif + } + // connect other local ports + for (l=0; lcurrent_r_addr = R_ADDR; + router1[ROUTER_NUM]->current_r_id = ROUTER_NUM; + if(x < T1-1) {//: not_last_x + //assign router_chan_in[`router_id(x,y)][EAST]= router_chan_out [`router_id(x+1,y)][WEST]; + conect_r2r(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); + + }else {// :last_x + #if defined (IS_MESH) // :last_x_mesh + // assign router_chan_in[`router_id(x,y)][EAST] = {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),EAST); + #elif defined (IS_TORUS) // : last_x_torus + //assign router_chan_in[`router_id(x,y)][EAST] = router_chan_out [`router_id(0,y)][WEST]; + conect_r2r(1,router_id(x,y),EAST,1,router_id(0,y),WEST); + #elif defined (IS_FMESH) //:last_x_fmesh + //connect to endp + unsigned int EAST_ID = T1*T2*T3 + 2*T1 + T2 + y; + connect_r2e(1,router_id(x,y),EAST,EAST_ID); + er_addr [EAST_ID] = R_ADDR; + #endif//topology + } + if(y>0) {// : not_first_y + //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; + conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); + }else {// :first_y + #if defined (IS_MESH) // : first_y_mesh + //assign router_chan_in[`router_id(x,y)][NORTH] = {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),NORTH); + #elif defined (IS_TORUS)// :first_y_torus + //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(T2-1))][SOUTH]; + conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); + #elif defined (IS_FMESH) // :first_y_fmesh + unsigned int NORTH_ID = T1*T2*T3 + x; + connect_r2e(1,router_id(x,y),NORTH,NORTH_ID); + er_addr [NORTH_ID] = R_ADDR; + #endif//topology + }//y>0 + if(x>0){// :not_first_x + //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; + conect_r2r(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); + }else {// :first_x + + #if defined (IS_MESH) // :first_x_mesh + //assign router_chan_in[`router_id(x,y)][WEST] = {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),WEST); + + #elif defined (IS_TORUS) // :first_x_torus + //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; + conect_r2r(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); + #elif defined (IS_FMESH) // :first_x_fmesh + unsigned int WEST_ID = T1*T2*T3 + 2*T1 + y; + connect_r2e(1,router_id(x,y),WEST,WEST_ID); + er_addr [WEST_ID] = R_ADDR; + #endif//topology + } + if(y < T2-1) {// : firsty + //assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; + conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); + }else {// : lasty + + #if defined (IS_MESH) // :ly_mesh + + //assign router_chan_in[`router_id(x,y)][SOUTH]= {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),SOUTH); + + #elif defined (IS_TORUS) // :ly_torus + //assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; + conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); + #elif defined (IS_FMESH) // :ly_Fmesh + unsigned int SOUTH_ID = T1*T2*T3 + T1 + x; + connect_r2e(1,router_id(x,y),SOUTH,SOUTH_ID); + er_addr [SOUTH_ID] = R_ADDR; + #endif//topology + } + // endpoint(s) connection + // connect other local ports + for (l=0; lcurrent_r_addr = x; - router1[x]->current_r_id = x; - if(x < T1-1){// not_last_node - //assign router_chan_in[x][FORWARD] = router_chan_out [(x+1)][BACKWARD]; - //conect_r2r(1,x,FORWARD,1,(x+1),BACKWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,FORWARD,1,(x+1),BACKWARD); - num++; - } else { //last_node - #if defined (IS_LINE) // : line_last_x - //assign router_chan_in[x][FORWARD]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,FORWARD); - #else // : ring_last_x - //assign router_chan_in[x][FORWARD]= router_chan_out [0][BACKWARD]; - //conect_r2r(1,x,FORWARD,1,0,BACKWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,FORWARD,1,0,BACKWARD); - num++; - #endif - } - - if(x>0){// :not_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; - //conect_r2r(1,x,BACKWARD,1,(x-1),FORWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,BACKWARD,1,(x-1),FORWARD); - num++; - }else {// :first_x - #if defined (IS_LINE) // : line_first_x - //assign router_chan_in[x][BACKWARD]={SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,BACKWARD); - #else // : ring_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; - //conect_r2r(1,x,BACKWARD,1,(T1-1),FORWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,BACKWARD,1,(T1-1),FORWARD); - num++; - #endif - } - - // connect other local ports - for (l=0; lcurrent_r_addr = R_ADDR; - router1[ROUTER_NUM]->current_r_id = ROUTER_NUM; - - if(x < T1-1) {//: not_last_x - //assign router_chan_in[`router_id(x,y)][EAST]= router_chan_out [`router_id(x+1,y)][WEST]; - //conect_r2r(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); - num++; - - }else {// :last_x - #if defined (IS_MESH) // :last_x_mesh - // assign router_chan_in[`router_id(x,y)][EAST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),EAST); - #elif defined (IS_TORUS) // : last_x_torus - //assign router_chan_in[`router_id(x,y)][EAST] = router_chan_out [`router_id(0,y)][WEST]; - //conect_r2r(1,router_id(x,y),EAST,1,router_id(0,y),WEST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),EAST,1,router_id(0,y),WEST); - num++; - #elif defined (IS_FMESH) //:last_x_fmesh - //connect to endp - unsigned int EAST_ID = T1*T2*T3 + 2*T1 + T2 + y; - //connect_r2e(1,router_id(x,y),EAST,EAST_ID); - r2e_cnt_all[EAST_ID].r1=router_id(x,y); - r2e_cnt_all[EAST_ID].p1=EAST; - er_addr [EAST_ID] = R_ADDR; - #endif//topology - } - - - if(y>0) {// : not_first_y - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; - //conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); - num++; - }else {// :first_y - #if defined (IS_MESH) // : first_y_mesh - //assign router_chan_in[`router_id(x,y)][NORTH] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),NORTH); - #elif defined (IS_TORUS)// :first_y_torus - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(T2-1))][SOUTH]; - //conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); - num++; - #elif defined (IS_FMESH) // :first_y_fmesh - unsigned int NORTH_ID = T1*T2*T3 + x; - //connect_r2e(1,router_id(x,y),NORTH,NORTH_ID); - r2e_cnt_all[NORTH_ID].r1=router_id(x,y); - r2e_cnt_all[NORTH_ID].p1=NORTH; - er_addr [NORTH_ID] = R_ADDR; - #endif//topology - }//y>0 - - - if(x>0){// :not_first_x - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; - //conect_r2r(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); - num++; - - }else {// :first_x - - #if defined (IS_MESH) // :first_x_mesh - //assign router_chan_in[`router_id(x,y)][WEST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),WEST); - - #elif defined (IS_TORUS) // :first_x_torus - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; - //conect_r2r(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); - num++; - #elif defined (IS_FMESH) // :first_x_fmesh - unsigned int WEST_ID = T1*T2*T3 + 2*T1 + y; - //connect_r2e(1,router_id(x,y),WEST,WEST_ID); - r2e_cnt_all[WEST_ID].r1=router_id(x,y); - r2e_cnt_all[WEST_ID].p1=WEST; - er_addr [WEST_ID] = R_ADDR; - #endif//topology - } - - if(y < T2-1) {// : firsty - //assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; - // conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); - num++; - }else {// : lasty - - #if defined (IS_MESH) // :ly_mesh - - //assign router_chan_in[`router_id(x,y)][SOUTH]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),SOUTH); - - #elif defined (IS_TORUS) // :ly_torus - //assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; - // conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); - num++; - #elif defined (IS_FMESH) // :ly_Fmesh - unsigned int SOUTH_ID = T1*T2*T3 + T1 + x; - //connect_r2e(1,router_id(x,y),SOUTH,SOUTH_ID); - r2e_cnt_all[SOUTH_ID].r1=router_id(x,y); - r2e_cnt_all[SOUTH_ID].p1=SOUTH; - er_addr [SOUTH_ID] = R_ADDR; - #endif//topology - } - - - // endpoint(s) connection - // connect other local ports - for (l=0; lcurrent_r_addr = x; + router1[x]->current_r_id = x; + if(x < T1-1){// not_last_node + //assign router_chan_in[x][FORWARD] = router_chan_out [(x+1)][BACKWARD]; + //conect_r2r(1,x,FORWARD,1,(x+1),BACKWARD); + r2r_cnt_all[num]=fill_r2r_cnt(1,x,FORWARD,1,(x+1),BACKWARD); + num++; + } else { //last_node + #if defined (IS_LINE) // : line_last_x + //assign router_chan_in[x][FORWARD]= {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,x,FORWARD); + #else // : ring_last_x + //assign router_chan_in[x][FORWARD]= router_chan_out [0][BACKWARD]; + //conect_r2r(1,x,FORWARD,1,0,BACKWARD); + r2r_cnt_all[num]=fill_r2r_cnt(1,x,FORWARD,1,0,BACKWARD); + num++; + #endif + } + if(x>0){// :not_first_x + //assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; + //conect_r2r(1,x,BACKWARD,1,(x-1),FORWARD); + r2r_cnt_all[num]=fill_r2r_cnt(1,x,BACKWARD,1,(x-1),FORWARD); + num++; + }else {// :first_x + #if defined (IS_LINE) // : line_first_x + //assign router_chan_in[x][BACKWARD]={SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,x,BACKWARD); + #else // : ring_first_x + //assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; + //conect_r2r(1,x,BACKWARD,1,(T1-1),FORWARD); + r2r_cnt_all[num]=fill_r2r_cnt(1,x,BACKWARD,1,(T1-1),FORWARD); + num++; + #endif + } + // connect other local ports + for (l=0; lcurrent_r_addr = R_ADDR; + router1[ROUTER_NUM]->current_r_id = ROUTER_NUM; + if(x < T1-1) {//: not_last_x + //assign router_chan_in[`router_id(x,y)][EAST]= router_chan_out [`router_id(x+1,y)][WEST]; + //conect_r2r(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); + num++; + }else {// :last_x + #if defined (IS_MESH) // :last_x_mesh + // assign router_chan_in[`router_id(x,y)][EAST] = {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),EAST); + #elif defined (IS_TORUS) // : last_x_torus + //assign router_chan_in[`router_id(x,y)][EAST] = router_chan_out [`router_id(0,y)][WEST]; + //conect_r2r(1,router_id(x,y),EAST,1,router_id(0,y),WEST); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),EAST,1,router_id(0,y),WEST); + num++; + #elif defined (IS_FMESH) //:last_x_fmesh + //connect to endp + unsigned int EAST_ID = T1*T2*T3 + 2*T1 + T2 + y; + //connect_r2e(1,router_id(x,y),EAST,EAST_ID); + r2e_cnt_all[EAST_ID].r1=router_id(x,y); + r2e_cnt_all[EAST_ID].p1=EAST; + er_addr [EAST_ID] = R_ADDR; + #endif//topology + } + if(y>0) {// : not_first_y + //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; + //conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); + num++; + }else {// :first_y + #if defined (IS_MESH) // : first_y_mesh + //assign router_chan_in[`router_id(x,y)][NORTH] = {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),NORTH); + #elif defined (IS_TORUS)// :first_y_torus + //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(T2-1))][SOUTH]; + //conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); + num++; + #elif defined (IS_FMESH) // :first_y_fmesh + unsigned int NORTH_ID = T1*T2*T3 + x; + //connect_r2e(1,router_id(x,y),NORTH,NORTH_ID); + r2e_cnt_all[NORTH_ID].r1=router_id(x,y); + r2e_cnt_all[NORTH_ID].p1=NORTH; + er_addr [NORTH_ID] = R_ADDR; + #endif//topology + }//y>0 + if(x>0){// :not_first_x + //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; + //conect_r2r(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); + num++; + }else {// :first_x + #if defined (IS_MESH) // :first_x_mesh + //assign router_chan_in[`router_id(x,y)][WEST] = {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),WEST); + #elif defined (IS_TORUS) // :first_x_torus + //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; + //conect_r2r(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); + num++; + #elif defined (IS_FMESH) // :first_x_fmesh + unsigned int WEST_ID = T1*T2*T3 + 2*T1 + y; + //connect_r2e(1,router_id(x,y),WEST,WEST_ID); + r2e_cnt_all[WEST_ID].r1=router_id(x,y); + r2e_cnt_all[WEST_ID].p1=WEST; + er_addr [WEST_ID] = R_ADDR; + #endif//topology + } + if(y < T2-1) {// : firsty + //assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; + // conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); + num++; + }else {// : lasty + #if defined (IS_MESH) // :ly_mesh + //assign router_chan_in[`router_id(x,y)][SOUTH]= {SMARTFLIT_CHANEL_w{1'b0}}; + connect_r2gnd(1,router_id(x,y),SOUTH); + #elif defined (IS_TORUS) // :ly_torus + //assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; + // conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); + r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); + num++; + #elif defined (IS_FMESH) // :ly_Fmesh + unsigned int SOUTH_ID = T1*T2*T3 + T1 + x; + //connect_r2e(1,router_id(x,y),SOUTH,SOUTH_ID); + r2e_cnt_all[SOUTH_ID].r1=router_id(x,y); + r2e_cnt_all[SOUTH_ID].p1=SOUTH; + er_addr [SOUTH_ID] = R_ADDR; + #endif//topology + } + // endpoint(s) connection + // connect other local ports + for (l=0; l x2) ? (x1 - x2) : (x2 - x1); - unsigned int y_diff = (y1 > y2) ? (y1 - y2) : (y2 - y1); - return x_diff + y_diff; + unsigned int x1,y1,l1,x2,y2,l2; + mesh_tori_addrencod_sep(id1, &x1, &y1, &l1); + mesh_tori_addrencod_sep(id2, &x2, &y2, &l2); + #endif + unsigned int x_diff = (x1 > x2) ? (x1 - x2) : (x2 - x1); + unsigned int y_diff = (y1 > y2) ? (y1 - y2) : (y2 - y1); + return x_diff + y_diff; } - #endif diff --git a/mpsoc/src_verilator/topology/star.h b/mpsoc/src_verilator/topology/star.h index 18fc1a0..3e76ee5 100644 --- a/mpsoc/src_verilator/topology/star.h +++ b/mpsoc/src_verilator/topology/star.h @@ -1,20 +1,14 @@ #ifndef STAR_H - #define STAR_H - - + #define STAR_H void topology_connect_all_nodes_old (void){ - - - unsigned int pos; - for ( pos = 0; pos < NE; pos=pos+1 ) {// : endpoints - - //assign router_chan_out [0][pos] = chan_in_all [pos]; - //assign chan_out_all [pos] = router_chan_in [0][pos]; + unsigned int pos; + for ( pos = 0; pos < NE; pos=pos+1 ) {// : endpoints + //assign router_chan_out [0][pos] = chan_in_all [pos]; + //assign chan_out_all [pos] = router_chan_in [0][pos]; connect_r2e(1,0,pos,pos); - er_addr [pos] = 0; - - }//pos + er_addr [pos] = 0; + }//pos } void topology_connect_r2r (unsigned int n){ @@ -22,14 +16,11 @@ void topology_connect_r2r (unsigned int n){ } void topology_connect_r2e (unsigned int n){ - connect_r2e(1,0,n,n); + connect_r2e(1,0,n,n); } - - - unsigned int endp_addr_encoder ( unsigned int id){ - return id; + return id; } unsigned int endp_addr_decoder (unsigned int code){ @@ -37,13 +28,13 @@ unsigned int endp_addr_decoder (unsigned int code){ } void topology_init (void){ - router1[0]->current_r_addr = 0; - router1[0]->current_r_id = 0; - for ( int pos = 0; pos < NE; pos=pos+1 ) {// : endpoints - er_addr [pos] = 0; - - } - + #ifndef FLAT_MODE + router1[0]->current_r_addr = 0; + router1[0]->current_r_id = 0; + for ( int pos = 0; pos < NE; pos=pos+1 ) {// : endpoints + er_addr [pos] = 0; + } + #endif } #endif diff --git a/mpsoc/src_verilator/topology/topology_top.h b/mpsoc/src_verilator/topology/topology_top.h index 66bff05..361292c 100644 --- a/mpsoc/src_verilator/topology/topology_top.h +++ b/mpsoc/src_verilator/topology/topology_top.h @@ -1,143 +1,129 @@ #ifndef TOPOLOGY_TOP_H #define TOPOLOGY_TOP_H - unsigned int R2R_TABLE_SIZ =0; - - #define CNT_R2R_SIZ (NR * MAX_P) //((NR1+NR2+1)*(K+1)) - #define CNT_R2E_SIZ (NE+1) - - typedef struct R2R_CNT_TABLE { - unsigned int id1; - unsigned int t1; - unsigned int r1; - unsigned int p1; - unsigned int id2; - unsigned int t2; - unsigned int r2; - unsigned int p2; - } r2r_cnt_table_t; - - r2r_cnt_table_t r2r_cnt_all[CNT_R2R_SIZ]; - - typedef struct R2E_CNT_TABLE { - unsigned int r1; - unsigned int p1; - } r2e_cnt_table_t; - - r2e_cnt_table_t r2e_cnt_all[CNT_R2E_SIZ]; - - - int get_router_num (int NR_num, int NR_id){ - int offset=0; - if(NR_num* sizeof(int) > sizeof(router_NRs)){ - fprintf(stderr,"ERROR: NR%u is not defined\n",NR_num); - exit(1); - } - while (NR_num > 1) { - NR_num-=1; - offset += router_NRs[NR_num]; - } - return offset + NR_id; - } - - - unsigned int er_addr [NE+1]; - char start_i=0; - char start_o[NE+1]={0}; - - unsigned int Log2 (unsigned int n){ - unsigned int l=1; - while((0x1< sizeof(router_NRs)){ + fprintf(stderr,"ERROR: NR%u is not defined\n",NR_num); + exit(1); + } + while (NR_num > 1) { + NR_num-=1; + offset += router_NRs[NR_num]; + } + return offset + NR_id; + } + #endif + + unsigned int er_addr [NE+1]; + char start_i=0; + char start_o[NE+1]={0}; + + unsigned int Log2 (unsigned int n){ + unsigned int l=1; + while((0x1<>=kw; - } - return pos; + unsigned int kw=0; + unsigned int mask=0; + unsigned int pow,i,tmp; + unsigned int pos=0; + while((0x1<>=kw; + } + return pos; } - - unsigned int endp_addr_encoder ( unsigned int id){ - return bintree_addrencode(id, T1, T2); + return bintree_addrencode(id, T1, T2); } unsigned int endp_addr_decoder (unsigned int code){ - return bintree_addrdecode(code, T1, T2); + return bintree_addrdecode(code, T1, T2); } - - void topology_init (void){ - - Lw=Log2(L); - Kw=Log2(K); - LKw=L*Kw; - - - //assign current_layer_addr [ROOT_ID] = ROOT_L; - //assign current_pos_addr [ROOT_ID] = {LKw{1'b0}}; - unsigned int addr = ROOT_L << LKw; - router1[ROOT_ID]->current_r_addr = addr; - router1[ROOT_ID]->current_r_id = ROOT_ID; - - - unsigned int pos,level; - unsigned int num = 0; - //connect all up connections - for (level = 1; levelcurrent_r_addr = addr; - router2[Ri(ID1)]->current_r_id = ID1; - - //printf( "[%u] =(addr=%x), t1=%u, r1=%u, p1=%u, t2=%u, r2=%u, p2=%u \n", num,addr, r2r_cnt_all[num].t1, r2r_cnt_all[num].r1, r2r_cnt_all[num].p1, r2r_cnt_all[num].t2, r2r_cnt_all[num].r2, r2r_cnt_all[num].p2 ); - - - - - - - - num++; - }// pos - - } //level - - R2R_TABLE_SIZ=num; - - // connect }points - - for ( pos = 0; pos < NE; pos=pos+1 ) { // : }points - // node_connection T[pos] R[rid][pos %k]; - unsigned int RID= sum_powi(K,L-1)+(pos/K); - unsigned int RPORT = pos%K; - unsigned int CURRENTPOS= bintree_addrencode(pos/K,K,L); - - //assign router_chan_out [RID][RPORT] = chan_in_all [pos]; - //assign chan_out_all [pos] = router_chan_in [RID][RPORT]; - r2e_cnt_all[pos].r1=Ri(RID); - r2e_cnt_all[pos].p1=RPORT; - - er_addr [pos] = CURRENTPOS; - - } //pos - + Lw=Log2(L); + Kw=Log2(K); + LKw=L*Kw; + #ifndef FLAT_MODE + //assign current_layer_addr [ROOT_ID] = ROOT_L; + //assign current_pos_addr [ROOT_ID] = {LKw{1'b0}}; + unsigned int addr = ROOT_L << LKw; + router1[ROOT_ID]->current_r_addr = addr; + router1[ROOT_ID]->current_r_id = ROOT_ID; + unsigned int pos,level; + unsigned int num = 0; + //connect all up connections + for (level = 1; levelcurrent_r_addr = addr; + router2[Ri(ID1)]->current_r_id = ID1; + //printf( "[%u] =(addr=%x), t1=%u, r1=%u, p1=%u, t2=%u, r2=%u, p2=%u \n", num,addr, r2r_cnt_all[num].t1, r2r_cnt_all[num].r1, r2r_cnt_all[num].p1, r2r_cnt_all[num].t2, r2r_cnt_all[num].r2, r2r_cnt_all[num].p2 ); + num++; + }// pos + } //level + R2R_TABLE_SIZ=num; + // connect }points + for ( pos = 0; pos < NE; pos=pos+1 ) { // : }points + // node_connection T[pos] R[rid][pos %k]; + unsigned int RID= sum_powi(K,L-1)+(pos/K); + unsigned int RPORT = pos%K; + unsigned int CURRENTPOS= bintree_addrencode(pos/K,K,L); + //assign router_chan_out [RID][RPORT] = chan_in_all [pos]; + //assign chan_out_all [pos] = router_chan_in [RID][RPORT]; + r2e_cnt_all[pos].r1=Ri(RID); + r2e_cnt_all[pos].p1=RPORT; + er_addr [pos] = CURRENTPOS; + } //pos + #endif //FLAT_MODE } - void topology_connect_r2r (int n){ - fattree_connect(r2r_cnt_all[n]); + fattree_connect(r2r_cnt_all[n]); } void topology_connect_r2e (int n){ - connect_r2e(2,r2e_cnt_all[n].r1,r2e_cnt_all[n].p1,n); + connect_r2e(2,r2e_cnt_all[n].r1,r2e_cnt_all[n].p1,n); } /* void topology_connect_all_nodes (void){ - unsigned int pos,level; - unsigned int num=0; - //connect all up connections - for (level = 1; level Date: Sat, 19 Jul 2025 01:58:49 +0200 Subject: [PATCH 072/107] reduces OEM instances --- mpsoc/rtl/main_comp.v | 30 +++++------- mpsoc/rtl/src_noc/fattree_route.sv | 47 +++++++++---------- mpsoc/rtl/src_noc/fmesh.sv | 18 ++++--- mpsoc/rtl/src_noc/input_ports.sv | 15 +++--- mpsoc/rtl/src_noc/mesh_torus.sv | 30 +++++------- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 14 +++--- mpsoc/rtl/src_noc/router_bypass.sv | 19 ++++---- mpsoc/rtl/src_noc/tree_route.sv | 15 +++--- .../jtag_ram_test/src_verilog/lib/main_comp.v | 30 +++++------- 9 files changed, 93 insertions(+), 125 deletions(-) diff --git a/mpsoc/rtl/main_comp.v b/mpsoc/rtl/main_comp.v index 350ac23..5e286e9 100755 --- a/mpsoc/rtl/main_comp.v +++ b/mpsoc/rtl/main_comp.v @@ -30,22 +30,17 @@ module pronoc_register #( parameter W=1, - parameter RESET_TO={W{1'b0}} + parameter RESET_TO={W{1'b0}} )( input [W-1: 0] D_in, input reset, input clk, - output [W-1: 0] Q_out + output reg [W-1: 0] Q_out ); - pronoc_register_reset_init #( - .W(W) - )reg1( - .D_in(D_in), - .reset(reset), - .clk(clk), - .Q_out(Q_out), - .reset_to(RESET_TO[W-1 : 0]) - ); + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) Q_out <= W'(RESET_TO); + else Q_out <= D_in; + end endmodule @@ -203,6 +198,7 @@ module outport_sum #( endgenerate endmodule + /*********************************** * module bin_to_one_hot ************************************/ @@ -212,14 +208,12 @@ module bin_to_one_hot #( )( input [BIN_WIDTH-1 : 0] bin_code, - output [ONE_HOT_WIDTH-1 : 0] one_hot_code + output reg [ONE_HOT_WIDTH-1 : 0] one_hot_code ); - genvar i; - generate - for(i=0; i1) begin :multi assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 3eb8073..3c56979 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -1167,15 +1167,12 @@ module custom_topology_destp_decoder #( input [DSTPw-1 : 0] dest_port_in_encoded; output [P_1-1 : 0] dest_port_out; - wire [MAXW-1 : 0] dest_port_one_hot; - - bin_to_one_hot #( - .BIN_WIDTH(DSTPw), - .ONE_HOT_WIDTH(MAXW) - ) conv ( - .bin_code(dest_port_in_encoded), - .one_hot_code(dest_port_one_hot) - ); + logic [MAXW-1 : 0] dest_port_one_hot; + //bin_to_one_hot + always_comb begin + dest_port_one_hot = {MAXW{1'b0}}; + dest_port_one_hot[dest_port_in_encoded] = 1'b1; + end generate if( SELF_LOOP_EN==0) begin : nslp diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 1419aa6..f840571 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -1098,7 +1098,7 @@ module regular_topo_destp_decoder #( input swap_port_presel; input [PPSw-1 : 0] port_pre_sel; - wire [NL-1 : 0] endp_localp_onehot; + logic [NL-1 : 0] endp_localp_onehot; reg [4:0] portout; wire x,y,a,b; assign {x,y,a,b} = dest_port_coded; @@ -1115,6 +1115,11 @@ module regular_topo_destp_decoder #( endcase end //always + //bin_to_one_hot + always_comb begin + endp_localp_onehot = {NL{1'b0}}; + endp_localp_onehot[endp_localp_num] = 1'b1; + end generate if(NL==1) begin :slp if(SELF_LOOP_EN == 0) begin :nslp @@ -1130,13 +1135,6 @@ module regular_topo_destp_decoder #( end end else begin :mlp wire [P-1 : 0] destport_onehot; - bin_to_one_hot #( - .BIN_WIDTH(ELw), - .ONE_HOT_WIDTH(NL) - ) conv ( - .bin_code(endp_localp_num), - .one_hot_code(endp_localp_onehot) - ); assign destport_onehot =(portout[0])? { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/ @@ -1178,7 +1176,7 @@ module line_ring_destp_decoder #( input [DSTPw-1 : 0] dest_port_coded; input [ELw-1 : 0] endp_localp_num; output [P_1-1 : 0] dest_port_out; - wire [NL-1 : 0] endp_localp_onehot; + logic [NL-1 : 0] endp_localp_onehot; wire [2:0] portout; line_ring_decode_dstport decoder( @@ -1186,7 +1184,11 @@ module line_ring_destp_decoder #( .dstport_encoded(dest_port_coded) ); - + //bin_to_one_hot + always_comb begin + endp_localp_onehot = {NL{1'b0}}; + endp_localp_onehot[endp_localp_num] = 1'b1; + end generate if(NL==1) begin :_se if(SELF_LOOP_EN == 0) begin :nslp @@ -1202,14 +1204,6 @@ module line_ring_destp_decoder #( end end else begin :_me wire [P-1 : 0] destport_onehot; - - bin_to_one_hot #( - .BIN_WIDTH(ELw), - .ONE_HOT_WIDTH(NL) - ) conv ( - .bin_code(endp_localp_num), - .one_hot_code(endp_localp_onehot) - ); assign destport_onehot =(portout[0])? { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/ diff --git a/mpsoc/rtl/src_noc/mesh_torus_routting.sv b/mpsoc/rtl/src_noc/mesh_torus_routting.sv index a3296fa..ac186fd 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_routting.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_routting.sv @@ -364,7 +364,7 @@ module remove_receive_port_one_hot #( P_1w = log2(P_1); input [P-1 : 0] destport_in; input [P-1 : 0] receiver_port; - output [P_1-1 : 0] destport_out; + output logic [P_1-1 : 0] destport_out; wire [Pw-1 : 0] receiver_port_bin,destport_in_bin; wire [P_1w-1 : 0] destport_out_bin; @@ -388,13 +388,11 @@ module remove_receive_port_one_hot #( assign temp = (receiver_port_bin > destport_in_bin ) ? destport_in_bin : destport_in_bin -1'b1; assign destport_out_bin=temp[P_1w-1 : 0]; - bin_to_one_hot #( - .BIN_WIDTH(P_1w), - .ONE_HOT_WIDTH(P_1) - ) convert3 ( - .bin_code(destport_out_bin), - .one_hot_code(destport_out) - ); + //bin_to_one_hot + always_comb begin + destport_out = {P_1{1'b0}}; + destport_out[destport_out_bin] = 1'b1; + end endmodule /************************************** diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index 12d493a..dd52ae5 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -208,7 +208,7 @@ module smart_forward_ivc_info #( smart_ivc_info_t smart_ivc_info_all_port [P-1 : 0] [P-1 : 0]; smart_ivc_info_t smart_vc_info_o [P-1 : 0]; - wire [V-1 : 0] assigned_ovc [P-1:0]; + logic [V-1 : 0] assigned_ovc [P-1:0]; wire [V-1 : 0] non_assigned_vc_req [P-1:0]; wire [P-1 : 0] mask_gen [P-1 : 0][V-1 :0]; wire [V-1 : 0] ovc_locally_requested_next [P-1 : 0]; @@ -253,13 +253,6 @@ module smart_forward_ivc_info #( .Q_out(smart_vc_info_o[i]) ); - bin_to_one_hot #( - .BIN_WIDTH (Vw), - .ONE_HOT_WIDTH (V) - ) conv ( - .bin_code (smart_vc_info_o[i].assigned_ovc_bin), - .one_hot_code (assigned_ovc[i]) - ); assign smart_chanel_next[i].dest_e_addr= smart_vc_info_o[i].dest_e_addr; assign smart_chanel_next[i].ovc= (smart_vc_info_o[i].ovc_is_assigned)? assigned_ovc[i] : oport_info[i].non_smart_ovc_is_allocated; @@ -281,9 +274,15 @@ module smart_forward_ivc_info #( end end//port_ endgenerate -endmodule - + //bin_to_one_hot + always_comb begin + for (int port=0; port Date: Sat, 19 Jul 2025 02:34:09 +0200 Subject: [PATCH 073/107] fix linting --- mpsoc/Integration_test/Questa_lint/run.sh | 9 +++++---- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 5 +++-- mpsoc/rtl/src_noc/topology_localparam.v | 4 +++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mpsoc/Integration_test/Questa_lint/run.sh b/mpsoc/Integration_test/Questa_lint/run.sh index d7a973e..05b6fe0 100644 --- a/mpsoc/Integration_test/Questa_lint/run.sh +++ b/mpsoc/Integration_test/Questa_lint/run.sh @@ -27,11 +27,11 @@ questa_lint () { log_file="${log_dir}/${conf}.log" if [[ ! -f "$conf_file" ]]; then - echo "Configuration file $conf_file does not exist" + echo "Configuration file $conf_file does not exist" > $log_file exit 1 fi - perl "${SCRPT_DIR_PATH}/src/param_gen.pl" "$conf_file" + perl "${SCRPT_DIR_PATH}/src/param_gen.pl" "$conf_file" > $log_file export REPORT_FILENAME="${log_dir}/${conf}.txt" export FILE_LIST=$file_list_f @@ -39,8 +39,8 @@ questa_lint () { rm -rf work vlib work # Lint the design - vlog -sv -lint -f ${file_list_f} - vsim -suppress vopt-14408,vsim-16154 -c work.noc_top -do "quit" + vlog -sv -lint -f ${file_list_f} > $log_file + vsim -suppress vopt-14408,vsim-16154 -c work.noc_top -do "quit" > $log_file } report_total_errors_warnings () { @@ -57,6 +57,7 @@ run_config () { conf="$1" log_file="${log_dir}/${conf}.log" echo "▶️ Compiling configuration: $conf" + # Run and redirect stdout/stderr to log file only questa_lint "$conf" |& tee "$log_file" if [[ ${PIPESTATUS[0]} -ne 0 ]]; then echo "❌ Compilation failed for $conf (check $log_file)" diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 6c12fd2..c234183 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -142,8 +142,9 @@ module regular_topo_noc_top ( localparam EAST_ENDP_LOC=NL; localparam NORTH_ENDP_LOC=NL+1; localparam WEST_ENDP_LOC= (NX==1) ? (NL+2) : EAST_ENDP_LOC; - localparam SOUTH_ENDP_LOC= (NY==1) ? (NL+2) : NORTH_ENDP_LOC; - + localparam SOUTH_ENDP_LOC= + (NY==1 && NX==1) ? (NL+3) : + (NY==1) ? (NL+2) : NORTH_ENDP_LOC; if(x == NX-1) begin localparam [EAw-1 : 0] EAST_ADDR = EAw'(fmesh_endp_addr(EAST_ID)); assign chan_out_all [EAST_ID] = router_chan_out [fmesh_router_id(x,y)][EAST]; diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 2a3f5e7..2e22b8f 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -172,7 +172,9 @@ NR_FMESH = NR_REGULAR, MAX_P_FMESH = 4 + NL, EAw_FMESH = RAw_REGULAR + log2(MAX_P_FMESH), - NE_PER_R_FMESH = ((NX == 1) || (NY == 1)) ? NL + 3 : NL + 2; // 2 for the edge ports; + NE_PER_R_FMESH = + ((NX == 1) && (NY == 1)) ? NL + 4 : + ((NX == 1) || (NY == 1)) ? NL + 3 : NL + 2; // 2 for the edge ports; /****************** * FATTREE ******************/ From 40d5262db0004a06e14e4116ae77bf1071cd577b Mon Sep 17 00:00:00 2001 From: amonemi Date: Sun, 20 Jul 2025 01:59:28 +0200 Subject: [PATCH 074/107] remove pronoc_register module to reduce the number of oem instants --- mpsoc/rtl/src_modelsim/multicast_injector.sv | 26 ++-- mpsoc/rtl/src_noc/congestion_analyzer.sv | 120 +++++++++---------- mpsoc/rtl/src_noc/debug.sv | 53 ++++---- mpsoc/rtl/src_noc/fattree_route.sv | 89 ++++++-------- mpsoc/rtl/src_noc/flit_buffer.sv | 116 ++++++++++++------ mpsoc/rtl/src_noc/header_flit.sv | 17 ++- mpsoc/rtl/src_noc/inout_ports.sv | 31 ++--- mpsoc/rtl/src_noc/input_ports.sv | 71 +++++------ mpsoc/rtl/src_noc/mesh_torus.sv | 10 +- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 31 +++-- mpsoc/rtl/src_noc/output_ports.sv | 62 ++++++---- mpsoc/rtl/src_noc/packet_injector.sv | 44 ++++--- mpsoc/rtl/src_noc/router_bypass.sv | 85 +++++++++---- mpsoc/rtl/src_noc/router_two_stage.sv | 31 +++-- mpsoc/rtl/src_noc/ss_allocator.sv | 15 +-- mpsoc/rtl/src_noc/traffic_gen_top.sv | 25 ++-- mpsoc/rtl/src_noc/tree_route.sv | 16 ++- mpsoc/rtl/src_noc/wrra.sv | 26 ++-- mpsoc/rtl/src_synfull/dpi_interface.sv | 4 +- 19 files changed, 513 insertions(+), 359 deletions(-) diff --git a/mpsoc/rtl/src_modelsim/multicast_injector.sv b/mpsoc/rtl/src_modelsim/multicast_injector.sv index 85ad787..942f5a5 100644 --- a/mpsoc/rtl/src_modelsim/multicast_injector.sv +++ b/mpsoc/rtl/src_modelsim/multicast_injector.sv @@ -194,7 +194,7 @@ module multicast_injector ( h2t_counter_next[i]= 16'd0; // reset once header flit is received end//hdr flit wr end//always - always_ff @(`pronoc_clk_reset_edge) begin + always_ff @ (`pronoc_clk_reset_edge) begin if (`pronoc_reset) begin rsv_counter[i]<= {PCK_SIZw{1'b0}}; h2t_counter[i]<= 16'd0; @@ -219,7 +219,7 @@ module multicast_injector ( end//reset end//always for (k=0;k< REMAIN_DAT_FLIT+1;k++)begin : K_ - always_ff @(`pronoc_clk_reset_edge) begin + always_ff @ (`pronoc_clk_reset_edge) begin if (`pronoc_reset) begin pck_data_o_gen [i][k] <= {Fpay{1'b0}}; end else begin @@ -248,12 +248,22 @@ module multicast_injector ( end//for i endgenerate - wire [V-1 : 0] vc_reg; - wire tail_flag_reg, hdr_flag_reg; + logic [V-1 : 0] vc_reg; + logic tail_flag_reg, hdr_flag_reg; logic [DISTw-1: 0] distance; - pronoc_register #(.W(V)) register1 (.D_in(chan_in.flit_chanel.flit.vc), .reset (reset ), .clk (clk),.Q_out(vc_reg)); - pronoc_register #(.W(1)) register2 (.D_in(chan_in.flit_chanel.flit.hdr_flag), .reset (reset ), .clk (clk),.Q_out(hdr_flag_reg)); - pronoc_register #(.W(1)) register3 (.D_in(chan_in.flit_chanel.flit.tail_flag & chan_in.flit_chanel.flit_wr ),.reset (reset ), .clk (clk),.Q_out(tail_flag_reg)); + + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + vc_reg <= {V{1'b0}}; + hdr_flag_reg <= 1'b0; + tail_flag_reg <= 1'b0; + end else begin + vc_reg <= chan_in.flit_chanel.flit.vc; + hdr_flag_reg <= chan_in.flit_chanel.flit.hdr_flag; + tail_flag_reg <= chan_in.flit_chanel.flit.tail_flag & chan_in.flit_chanel.flit_wr; + end + end + wire [Vw-1 : 0] vc_bin; one_hot_to_bin #( .ONE_HOT_WIDTH (V), @@ -361,4 +371,4 @@ module multi_cast_injector_ovc_status #( assign empty_vc[i] = (credit[i] == credit_init_val_in[i][DEPTH_WIDTH-1:0]); end//for endgenerate -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.sv b/mpsoc/rtl/src_noc/congestion_analyzer.sv index f8312e7..c9748ca 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.sv +++ b/mpsoc/rtl/src_noc/congestion_analyzer.sv @@ -152,8 +152,8 @@ module port_presel_based_dst_ports_credit #( input reset,clk; output [PPSw-1 : 0] port_pre_sel; - reg [BVw-1 : 0] credit_per_port_next [P_1-1 : 0]; - wire [BVw-1 : 0] credit_per_port [P_1-1 : 0]; + logic [BVw-1 : 0] credit_per_port_next [P_1-1 : 0]; + logic [BVw-1 : 0] credit_per_port [P_1-1 : 0]; wire [P_1-1 : 0] credit_increased_per_port; wire [P_1-1 : 0] credit_decreased_per_port; wire [P_1-1 : 0] conjestion_cmp; @@ -163,15 +163,13 @@ module port_presel_based_dst_ports_credit #( for(i=0; i congestion_y_plus)? YDIR : XDIR; assign conjestion_cmp[X_PLUS_Y_MINUS] = (congestion_x_plus > congestion_y_min)? YDIR : XDIR; assign conjestion_cmp[X_MINUS_Y_MINUS]= (congestion_x_min > congestion_y_min)? YDIR : XDIR; - // assign port_pre_sel = conjestion_cmp; - pronoc_register #(.W(PPSw)) reg1 (.D_in(conjestion_cmp ), .reset(reset), .clk(clk), .Q_out(port_pre_sel)); + // assign port_pre_sel = conjestion_cmp; + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + port_pre_sel <= {PPSw{1'b0}}; + end else begin + port_pre_sel <= conjestion_cmp; + end + end endmodule @@ -474,15 +478,15 @@ module congestion_out_based_ivc_notgrant #( wire [IVC_CNTw-1 : 0] ivc_req_num; reg [CONGw-1 : 0] congestion_out ; - wire [PV-1 : 0] ivc_request_not_granted; - pronoc_register #( - .W(PV) - ) reg1 ( - .D_in(ivc_request_all & ~ivc_num_getting_sw_grant), - .reset(reset), - .clk(clk), - .Q_out(ivc_request_not_granted) - ); + logic [PV-1 : 0] ivc_request_not_granted; + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + ivc_request_not_granted <= {PV{1'b0}}; + end else begin + ivc_request_not_granted <= ivc_request_all & ~ivc_num_getting_sw_grant; + end + end + accumulator #( .INw(PV), .OUTw(IVC_CNTw), @@ -798,19 +802,18 @@ module congestion_out_based_avb_ovc_not_granted_ivc #( assign counter_in[SOUTH] ={ovc_not_avb[EAST] ,ovc_not_avb[NORTH] ,ovc_not_avb[WEST]}; // counting not granted requests - wire [PV-1 : 0] ivc_request_not_granted; + logic [PV-1 : 0] ivc_request_not_granted; wire [V-1 : 0] ivc_not_grnt [P_1-1 : 0]; wire [CNT_Vw-1 : 0] ivc_not_grnt_num [P_1-1 : 0]; + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + ivc_request_not_granted <= {PV{1'b0}}; + end else begin + ivc_request_not_granted <= ivc_request_all & ~ivc_num_getting_sw_grant; + end + end - pronoc_register #( - .W(PV) - ) reg1 ( - .D_in(ivc_request_all & ~ivc_num_getting_sw_grant), - .reset(reset), - .clk(clk), - .Q_out(ivc_request_not_granted) - ); assign {ivc_not_grnt[SOUTH], ivc_not_grnt[WEST], ivc_not_grnt[NORTH],ivc_not_grnt[EAST]}= ivc_request_not_granted[PV-1 : V]; genvar i; generate @@ -955,7 +958,7 @@ localparam input [PV-1 : 0] ovc_avalable_all; input [PV-1 : 0] ivc_request_all; input [PV-1 : 0] ivc_num_getting_sw_grant; - output [CONG_ALw-1 : 0] congestion_out_all; + output reg [CONG_ALw-1 : 0] congestion_out_all; input clk,reset; wire [CONG_ALw-1 : 0] congestion_out_all_next; @@ -1033,14 +1036,13 @@ localparam assign congestion_out_all_next = {CONG_ALw{1'b0}}; end endgenerate - pronoc_register #( - .W(CONG_ALw) - ) reg1 ( - .D_in(congestion_out_all_next), - .reset(reset), - .clk(clk), - .Q_out(congestion_out_all) - ); + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + congestion_out_all <= {CONG_ALw{1'b0}}; + end else begin + congestion_out_all <= congestion_out_all_next; + end + end endmodule @@ -1073,21 +1075,20 @@ module deadlock_detector #( input reset,clk; output detect; - wire [CNTw-1 : 0] counter [V-1 : 0]; + logic [CNTw-1 : 0] counter [V-1 : 0]; reg [CNTw-1 : 0] counter_next [V-1 : 0]; wire [P-1 : 0] counter_rst_gen [V-1 : 0]; wire [P-1 : 0] counter_en_gen [V-1 : 0]; wire [V-1 : 0] counter_rst,counter_en,detect_gen; - wire [PV-1 : 0] ivc_num_getting_sw_grant_reg; + logic [PV-1 : 0] ivc_num_getting_sw_grant_reg; + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + ivc_num_getting_sw_grant_reg <= {PV{1'b0}}; + end else begin + ivc_num_getting_sw_grant_reg <= ivc_num_getting_sw_grant; + end + end - pronoc_register #( - .W(PV) - ) reg1 ( - .D_in(ivc_num_getting_sw_grant), - .reset(reset), - .clk(clk), - .Q_out(ivc_num_getting_sw_grant_reg) - ); //seperate all same virtual chanels requests genvar i,j; generate @@ -1106,17 +1107,16 @@ module deadlock_detector #( else if(counter_en[i]) counter_next[i] = counter[i]+1'b1; end//always - pronoc_register #( - .W(CNTw) - ) reg2 ( - .D_in(counter_next[i]), - .reset(reset), - .clk(clk), - .Q_out(counter[i]) - ); + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + counter[i] <= {CNTw{1'b0}}; + end else begin + counter[i] <= counter_next[i]; + end + end // check counters value to detect deadlock assign detect_gen[i] = (counter[i]== MAX_CLK-1); end//i endgenerate assign detect=|detect_gen; -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index 7a9ede4..51157b9 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -25,7 +25,7 @@ module check_flit_chanel_type_is_in_order input [V-1 : 0] vc_num_in; wire [V-1 : 0] vc_num_hdr_wr, vc_num_tail_wr,vc_num_bdy_wr ; - wire [V-1 : 0] hdr_passed; + logic [V-1 : 0] hdr_passed; reg [V-1 : 0] hdr_passed_next; wire [V-1 : 0] single_flit_pck; @@ -38,14 +38,14 @@ module check_flit_chanel_type_is_in_order end `ifdef SIMULATION - pronoc_register #( - .W(V) - ) reg2 ( - .D_in(hdr_passed_next), - .reset(reset), - .clk(clk), - .Q_out(hdr_passed) - ); + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + hdr_passed <= {V{1'b0}}; + end else begin + hdr_passed <= hdr_passed_next; + end + end + always @ (posedge clk ) begin if(( hdr_passed & vc_num_hdr_wr)>0 )begin $display("%t ERROR: a header flit is received in an active IVC %m",$time); @@ -144,16 +144,15 @@ module debug_regular_topo_route_ckeck #( end//if end//always if(IS_FULL_ADAPTIVE) begin :full_adpt - wire [V-1 : 0] not_empty; - reg [V-1 : 0] not_empty_next; - pronoc_register #( - .W(V) - ) reg2 ( - .D_in(not_empty_next), - .reset(reset), - .clk(clk), - .Q_out(not_empty) - ); + reg [V-1 : 0] not_empty; + reg [V-1 : 0] not_empty_next; + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + not_empty <= {V{1'b0}}; + end else begin + not_empty <= not_empty_next; + end + end always @ (*) begin not_empty_next = not_empty; if(hdr_flg_in & flit_in_wr) begin @@ -402,7 +401,7 @@ module check_pck_size ( input [V-1 : 0] vc_num_in; input [DAw-1: 0] dest_e_addr_in; wire [NE-1 : 0] dest_mcast_all_endp [V-1 : 0]; - wire [31 : 0] pck_size_counter [V-1: 0]; + logic [31 : 0] pck_size_counter [V-1: 0]; reg [31 : 0] pck_size_counter_next [V-1: 0]; wire [DAw-1 : 0] dest_e_addr [V-1:0]; wire [V-1 : 0] vc_hdr_wr_en; @@ -422,13 +421,13 @@ module check_pck_size ( end end end - - pronoc_register #(.W(32)) reg1( - .D_in(pck_size_counter_next[i]), - .reset(reset), - .clk(clk ), - .Q_out (pck_size_counter[i]) - ); + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + pck_size_counter[i] <= 32'b0; + end else begin + pck_size_counter[i] <= pck_size_counter_next[i]; + end + end always @(posedge clk) begin if (vc_num_in == VC)begin diff --git a/mpsoc/rtl/src_noc/fattree_route.sv b/mpsoc/rtl/src_noc/fattree_route.sv index f3e1f5d..aa610e5 100644 --- a/mpsoc/rtl/src_noc/fattree_route.sv +++ b/mpsoc/rtl/src_noc/fattree_route.sv @@ -54,17 +54,14 @@ module fattree_nca_random_up_routing #( wire [Kw-1 :0] current_node_dest_port; wire [L-1 : 0] parrents_node_missmatch; - wire [K-1 : 0] counter; // a one hot counter. The value of the counter is used as a random destination port number when going to the up ports - - pronoc_register #( - .W(K), - .RESET_TO(1) - ) reg1 ( - .D_in({counter[0],counter[K-1:1]}), - .reset(reset), - .clk(clk), - .Q_out(counter) - ); + logic [K-1 : 0] counter; // a one hot counter. The value of the counter is used as a random destination port number when going to the up ports + always_ff @ (`pronoc_clk_reset_edge ) begin + if(`pronoc_reset) begin + counter <= K'(1); + end else begin + counter <= {counter[0],counter[K-1:1]}; + end + end assign current_addr [0]={Kw{1'b0}}; assign parrent_dest_addr [0]={Kw{1'b0}}; @@ -145,17 +142,14 @@ module fattree_nca_destp_up_routing #( wire [Kw-1 :0] dest_addr [L-1 : 0]; wire [Kw-1 :0] current_node_dest_port; wire [L-1 : 0] parrents_node_missmatch; - wire [K-1 : 0] counter; // a one hot counter. The value of the counter is used as a random destination port number when going to the up ports - - pronoc_register #( - .W(K), - .RESET_TO(1) - ) reg1 ( - .D_in({counter[0],counter[K-1:1]}), - .reset(reset), - .clk(clk), - .Q_out(counter) - ); + logic [K-1 : 0] counter; // a one hot counter. The value of the counter is used as a random destination port number when going to the up ports + always_ff @ (`pronoc_clk_reset_edge ) begin + if(`pronoc_reset) begin + counter <= K'(1); + end else begin + counter <= {counter[0],counter[K-1:1]}; + end + end assign current_addr [0]={Kw{1'b0}}; assign parrent_dest_addr [0]={Kw{1'b0}}; @@ -235,16 +229,14 @@ module fattree_nca_straight_up_routing #( wire [Kw-1 :0] dest_addr [L-1 : 0]; wire [Kw-1 :0] current_node_dest_port; wire [L-1 : 0] parrents_node_missmatch; - wire [K-1 : 0] counter; // a one hot counter. The value of the counter is used as a random destination port number when going to the up ports - pronoc_register #( - .W(K), - .RESET_TO(1) - ) reg1 ( - .D_in({counter[0],counter[K-1:1]}), - .reset(reset), - .clk(clk), - .Q_out(counter) - ); + logic [K-1 : 0] counter; // a one hot counter. The value of the counter is used as a random destination port number when going to the up ports + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + counter <= K'(1); + end else begin + counter <= {counter[0],counter[K-1:1]}; + end + end assign current_addr [0]={Kw{1'b0}}; assign parrent_dest_addr [0]={Kw{1'b0}}; @@ -390,8 +382,8 @@ module fattree_look_ahead_routing #( output [K: 0] lkdestport_encoded; input reset,clk; - wire [K :0] destport_encoded_delayed; - wire [LKw-1 :0] dest_addr_encoded_delayed; + logic [K :0] destport_encoded_delayed; + logic [LKw-1 :0] dest_addr_encoded_delayed; fattree_deterministic_look_ahead_routing #( .P(P) @@ -405,23 +397,16 @@ module fattree_look_ahead_routing #( .lkdestport_encoded(lkdestport_encoded) ); - pronoc_register #( - .W(K+1) - ) reg1 ( - .D_in(destport_encoded), - .reset(reset), - .clk(clk), - .Q_out(destport_encoded_delayed) - ); - - pronoc_register #( - .W(LKw) - ) reg2 ( - .D_in(dest_addr_encoded), - .reset(reset), - .clk(clk), - .Q_out(dest_addr_encoded_delayed) - ); + always_ff @ (`pronoc_clk_reset_edge ) begin + if(`pronoc_reset) begin + // reset the delayed values + destport_encoded_delayed <= {(K+1){1'b0}}; + dest_addr_encoded_delayed <= {LKw{1'b0}}; + end else begin + destport_encoded_delayed <= destport_encoded; + dest_addr_encoded_delayed <= dest_addr_encoded; + end + end endmodule @@ -857,4 +842,4 @@ module fattree_destp_generator #( assign dest_port_out= destport_masked [P_1-1 : 0 ]; end endgenerate -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 1ad129a..6c2b7d0 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -78,12 +78,12 @@ module flit_buffer output [V-1 : 0] flit_is_tail; //pointers - wire [PTRw- 1 : 0] rd_ptr [V-1 :0]; - wire [PTRw- 1 : 0] wr_ptr [V-1 :0]; + logic [PTRw- 1 : 0] rd_ptr [V-1 :0]; + logic [PTRw- 1 : 0] wr_ptr [V-1 :0]; reg [PTRw- 1 : 0] rd_ptr_next [V-1 :0]; reg [PTRw- 1 : 0] wr_ptr_next [V-1 :0]; reg [PTRw- 1 : 0] sub_rd_ptr_next [V-1 :0]; - wire [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; + logic [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; wire [ARRAYw-1 : 0] rd_ptr_array; wire [ARRAYw-1 : 0] wr_ptr_array; @@ -92,9 +92,9 @@ module flit_buffer wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_dout; wire [V-1 : 0] wr; wire [V-1 : 0] rd; - wire [DEPTHw-1 : 0] depth [V-1 :0]; - reg [DEPTHw-1 : 0] depth_next [V-1 :0]; - wire [DEPTHw-1 : 0] sub_depth [V-1 :0]; + logic [DEPTHw-1 : 0] depth [V-1 :0]; + logic [DEPTHw-1 : 0] depth_next [V-1 :0]; + logic [DEPTHw-1 : 0] sub_depth [V-1 :0]; logic [DEPTHw-1 : 0] sub_depth_next [V-1 :0]; reg [B-1 : 0] tail_fifo [V-1 : 0]; @@ -157,8 +157,15 @@ module flit_buffer if (~IS_UNICAST) begin assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = sub_rd_ptr[i]; localparam RESET_TO = ((2**Bw)==B)? 0 : B*i; - pronoc_register #(.W(PTRw),.RESET_TO(RESET_TO)) reg4 (.D_in(sub_rd_ptr_next[i]), .Q_out(sub_rd_ptr[i]), .reset(reset), .clk(clk)); - pronoc_register #(.W(DEPTHw)) sub_depth_reg (.D_in(sub_depth_next[i] ), .Q_out(sub_depth [i]), .reset(reset), .clk(clk)); + always_ff @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset) begin + sub_rd_ptr[i] <= PTRw'(RESET_TO); + sub_depth[i] <= {DEPTHw{1'b0}}; + end else begin + sub_rd_ptr[i] <= sub_rd_ptr_next[i]; + sub_depth[i] <= sub_depth_next[i]; + end + end assign vc_not_empty [i] = (sub_depth[i] > 0); end else begin : unicast assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = rd_ptr[i]; @@ -246,15 +253,20 @@ module flit_buffer ); for(i=0;i 0) counter_next = counter -1'b1; end assign credit_out = credit_in | smart_credit_in | (counter > 0); - pronoc_register #(.W(Bw+1)) reg1 (.D_in(counter_next), .reset(reset), .clk(clk), .Q_out(counter)); + always_ff @ (`pronoc_clk_reset_edge) begin + if (`pronoc_reset) begin + counter <= '0; + end else begin + counter <= counter_next; + end + end endmodule /************************** @@ -739,4 +774,4 @@ module reduction_or #( for (int i = 0; i < N; i++) Q_out |= D_in[i]; end -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index a8854cd..a63b290 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -172,7 +172,13 @@ module router_two_stage #( end //To avoid false loopback reports in Verilator - pronoc_register #(.W(ROUTER_INFO_w)) tmp_reg (.D_in(router_info_next ), .Q_out(router_info), .reset(reset), .clk(clk)); + always_ff @ (`pronoc_clk_reset_edge) begin + if (`pronoc_reset) begin + router_info <= '0; + end else begin + router_info <= router_info_next; + end + end always_comb begin router_info_next.router_id=current_r_id; @@ -342,8 +348,13 @@ module router_two_stage #( .clk(clk), .reset(reset) ); - - pronoc_register #(.W(PP_1)) reg2 (.D_in(granted_dest_port_all ), .Q_out(granted_dest_port_all_delayed), .reset(reset), .clk(clk)); + always_ff @ (`pronoc_clk_reset_edge) begin + if (`pronoc_reset) begin + granted_dest_port_all_delayed <= '0; // reset to zero vector of width PP_1 + end else begin + granted_dest_port_all_delayed <= granted_dest_port_all; + end + end crossbar #( .P (P) // router port num @@ -358,13 +369,17 @@ module router_two_stage #( //link reg generate if( ADD_PIPREG_AFTER_CROSSBAR == 1 ) begin :link_reg - reg [PFw-1 : 0] flit_out_all_pipe; reg [P-1 : 0] flit_out_wr_all_pipe; - - pronoc_register #(.W(PFw)) reg1 (.D_in(crossbar_flit_out_all ), .Q_out(flit_out_all_pipe), .reset(reset), .clk(clk)); - pronoc_register #(.W(P) ) reg2 (.D_in(crossbar_flit_out_wr_all ), .Q_out(flit_out_wr_all_pipe), .reset(reset), .clk(clk)); - + always_ff @ (`pronoc_clk_reset_edge) begin + if (`pronoc_reset) begin + flit_out_all_pipe <= '0; + flit_out_wr_all_pipe <= '0; + end else begin + flit_out_all_pipe <= crossbar_flit_out_all; + flit_out_wr_all_pipe <= crossbar_flit_out_wr_all; + end + end assign link_flit_out_all = flit_out_all_pipe; assign link_flit_out_wr_all = flit_out_wr_all_pipe; diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index 8f5a408..acafc71 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -74,7 +74,7 @@ module ss_allocator #( wire [PV-1 : 0] ivc_reset_all; wire [PV-1 : 0] single_flit_pck_all,ovc_single_flit_pck_all; wire [PV-1 : 0] decreased_credit_in_ss_ovc_all; - wire [P-1 : 0] ssa_flit_wr_all; + logic [P-1 : 0] ssa_flit_wr_all; wire [PV-1 : 0] any_ovc_granted_in_ss_port; wire [PV-1 : 0] ovc_avalable_in_ss_port; wire [PV-1 : 0] ovc_allocated_in_ss_port; @@ -157,12 +157,13 @@ module ss_allocator #( end// vc_loop for(i=0;i "verilate_mesh.sh", 'noc_param'=> { - TOPOLOGY=>"\"RING\"", - "TOPOLOGY" => "\"TORUS\"", + "TOPOLOGY"=>"\"RING\"", "ROUTE_NAME" => "\"TRANC_XY\"", "T1" => "3", "T2" => "1", diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/failed-model b/mpsoc/Integration_test/synthetic_sim/golden_ref/failed-model index 27e2a1b..c1744a2 100644 --- a/mpsoc/Integration_test/synthetic_sim/golden_ref/failed-model +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/failed-model @@ -13,27 +13,26 @@ Verification Results: %Warning-WIDTH: /gpfs/home//pronoc_verify/mpsoc/Integration_test/synthetic_sim/../../mpsoc_work/verify/rtl/src_noc/multicast.sv:399:43: Operator ASSIGNW expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'dest_e_addr' generates 4 bits. -****************************line_8_sbp6_xy : Compile *******************************: - model is generated successfully. ****************************mesh_4x4_openpiton_mcast_f : Compile *******************************: model is generated successfully. ****************************line2_2cycle_mcast_f : random traffic *******************************: - Error in running simulation: ERROR: Multicast/Broadcast is not yet supported for LINE Topology + Error in running simulation: ERROR: Multicast/Broadcast is not yet supported for LINE Topology -****************************line_8_sbp6_xy : random traffic *******************************: - Error in running simulation: 8000: ERROR: The destination port is not set for an active IVC request: d[R + ERROR: Multicast/Broadcast is not yet supported for LINE Topology ****************************mesh_4x4_openpiton_mcast_f : random traffic *******************************: - Error in running simulation: ERROR: SMART or SAA do not support muticast/braodcast packets + Error in running simulation: + ERROR: SMART or SAA do not support muticast/braodcast packets ERROR: SMART or SAA do not support muticast/braodcast packets ****************************line2_2cycle_mcast_f : transposed 1 traffic *******************************: - Error in running simulation: ERROR: Multicast/Broadcast is not yet supported for LINE Topology + Error in running simulation: + ERROR: Multicast/Broadcast is not yet supported for LINE Topology ERROR: Multicast/Broadcast is not yet supported for LINE Topology -****************************line_8_sbp6_xy : transposed 1 traffic *******************************: ****************************mesh_4x4_openpiton_mcast_f : transposed 1 traffic *******************************: - Error in running simulation: ERROR: SMART or SAA do not support muticast/braodcast packets + Error in running simulation: ERROR: SMART or SAA do not support muticast/braodcast packets - + ERROR: SMART or SAA do not support muticast/braodcast packets + diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/line-ring b/mpsoc/Integration_test/synthetic_sim/golden_ref/line-ring index 63eced9..933539f 100644 --- a/mpsoc/Integration_test/synthetic_sim/golden_ref/line-ring +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/line-ring @@ -13,6 +13,8 @@ Verification Results: model is generated successfully. ****************************line_8_b2 : Compile *******************************: model is generated successfully. +****************************line_8_sbp6_xy : Compile *******************************: + model is generated successfully. ****************************line_8_single_flit : Compile *******************************: model is generated successfully. ****************************line_8x8_ssa_xy : Compile *******************************: @@ -24,7 +26,7 @@ Verification Results: ****************************line2_openpiton : random traffic *******************************: Passed: zero load (2,8.28125) saturation (74,89.3628) ****************************line4_smart3 : random traffic *******************************: - Passed: zero load (2,8.66406) saturation (58,53.1986) + Passed: zero load (2,8.66406) saturation (62,115.304) ****************************Line_3x2_v2 : random traffic *******************************: Passed: zero load (2,9.40682) saturation (30,138.275) ****************************line_4_v1_B15 : random traffic *******************************: @@ -35,6 +37,8 @@ Verification Results: Passed: zero load (2,13.2248) saturation (38,122.456) ****************************line_8_b2 : random traffic *******************************: Passed: zero load (6,17.8996) saturation (34,105.723) +****************************line_8_sbp6_xy : random traffic *******************************: + Passed: zero load (2,9.51163) saturation (38,99.1912) ****************************line_8_single_flit : random traffic *******************************: Passed: zero load (6,7.98062) saturation (38,41.7814) ****************************line_8x8_ssa_xy : random traffic *******************************: @@ -57,6 +61,8 @@ Verification Results: Passed: zero load (2,15.1871) saturation (26,126.551) ****************************line_8_b2 : transposed 1 traffic *******************************: Passed: zero load (2,19.2832) saturation (26,144.49) +****************************line_8_sbp6_xy : transposed 1 traffic *******************************: + Passed: zero load (2,8.93525) saturation (26,114.013) ****************************line_8_single_flit : transposed 1 traffic *******************************: Passed: zero load (2,9.99617) saturation (26,65.1642) ****************************line_8x8_ssa_xy : transposed 1 traffic *******************************: diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos b/mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos index 1481828..062e4a2 100644 --- a/mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/tiny_topos @@ -8,6 +8,8 @@ Verification Results: ****************************mesh_2x2_openpiton : Compile *******************************: model is generated successfully. +****************************ring_3_2 : Compile *******************************: + model is generated successfully. ****************************star_7 : Compile *******************************: model is generated successfully. ****************************torus_3x2_adaptive : Compile *******************************: @@ -24,6 +26,8 @@ Verification Results: ****************************mesh_2x2_openpiton : random traffic *******************************: Passed: zero load (2,9.10156) saturation (66,72.3384) +****************************ring_3_2 : random traffic *******************************: + Passed: zero load (2,8.95385) saturation (62,50.9591) ****************************star_7 : random traffic *******************************: Passed: zero load (2,7.12609) saturation (62,63.5408) ****************************torus_3x2_adaptive : random traffic *******************************: @@ -40,6 +44,8 @@ Verification Results: ****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: Passed: zero load (2,8.7482) saturation (100,-) +****************************ring_3_2 : transposed 1 traffic *******************************: + Passed: zero load (6,8.3898) saturation (54,93.2034) ****************************star_7 : transposed 1 traffic *******************************: Passed: zero load (34,6.98688) saturation (100,-) ****************************torus_3x2_adaptive : transposed 1 traffic *******************************: diff --git a/mpsoc/rtl/main_comp.v b/mpsoc/rtl/main_comp.v index 5e286e9..1bd3f1d 100755 --- a/mpsoc/rtl/main_comp.v +++ b/mpsoc/rtl/main_comp.v @@ -44,63 +44,6 @@ module pronoc_register #( endmodule -module pronoc_register_reset_init #( - parameter W=1 -)( - input [W-1: 0] D_in, - input reset, - input clk, - output reg [W-1: 0] Q_out, - input [W-1 : 0] reset_to -); - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) Q_out<=reset_to; - else Q_out<=D_in; - end -endmodule - - -module pronoc_register_reset_init_ld_en #( - parameter W=1 -)( - input [W-1: 0] D_in, - input reset, - input clk, - input ld, - output reg [W-1: 0] Q_out, - input [W-1 : 0] reset_to -); - always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) Q_out<=reset_to; - else if(ld) Q_out<=D_in; - end -endmodule - - -module pronoc_register_ld_en #( - parameter W=1, - parameter RESET_TO={W{1'b0}} -)( - input [W-1: 0] D_in, - input reset, - input clk, - input ld, - output [W-1: 0] Q_out -); - pronoc_register_reset_init_ld_en #( - .W(W) - )reg1( - .D_in(D_in), - .reset(reset), - .clk(clk), - .ld(ld), - .Q_out(Q_out), - .reset_to(RESET_TO[W-1 : 0]) - ); -endmodule - - - /********************************* * multiplexer ********************************/ @@ -224,29 +167,17 @@ module one_hot_to_bin #( parameter BIN_WIDTH = (ONE_HOT_WIDTH > 1) ? $clog2(ONE_HOT_WIDTH) : 1 )( input [ONE_HOT_WIDTH-1 : 0] one_hot_code, - output [BIN_WIDTH-1 : 0] bin_code + output reg [BIN_WIDTH-1 : 0] bin_code ); - localparam MUX_IN_WIDTH = BIN_WIDTH * ONE_HOT_WIDTH; - wire [MUX_IN_WIDTH-1 : 0] bin_temp ; - genvar i; - generate - if(ONE_HOT_WIDTH>1)begin :if1 - for(i=0; i Date: Sun, 3 Aug 2025 16:18:08 +0200 Subject: [PATCH 077/107] Count number of instants in Intigration test verilator lint --- .../verilator_lint/golden_ref/report.txt | 80 +++++++++---------- mpsoc/Integration_test/verilator_lint/run.sh | 14 ++-- .../verilator_lint/src/instant_export.pl | 41 ++++++++++ 3 files changed, 90 insertions(+), 45 deletions(-) create mode 100644 mpsoc/Integration_test/verilator_lint/src/instant_export.pl diff --git a/mpsoc/Integration_test/verilator_lint/golden_ref/report.txt b/mpsoc/Integration_test/verilator_lint/golden_ref/report.txt index 3dbdb8d..0806eae 100644 --- a/mpsoc/Integration_test/verilator_lint/golden_ref/report.txt +++ b/mpsoc/Integration_test/verilator_lint/golden_ref/report.txt @@ -1,40 +1,40 @@ -Configuration | # Warnings | # Errors | -bintree_k3_L3_st | 120 | 0 | -custom1_topology | 119 | 0 | -Fattree_k3_L3_st | 121 | 0 | -fmesh_1x1_openpiton | 135 | 0 | -fmesh_2x2_openpiton | 142 | 0 | -fmesh_8x8_2cycle_xy | 116 | 0 | -fmesh_8x8_openpiton | 142 | 0 | -line4_smart3 | 160 | 0 | -line_4_v1_B15 | 144 | 0 | -line_8_single_flit | 138 | 0 | -mesh_2x2_openpiton | 154 | 0 | -mesh_3x3_v2_ssa | 141 | 0 | -mesh_4x4_2cycle_mcast_f | 114 | 0 | -mesh_4x4_LB5_B4 | 112 | 0 | -mesh_4x4_selflp_mcast_f | 113 | 0 | -mesh_4x4_smart3 | 138 | 0 | -mesh_4x4_v1_B15 | 131 | 0 | -mesh_4x4x2_bcast_f | 114 | 0 | -mesh_4x4x2_bcast_p | 114 | 0 | -mesh_4x4x2_mcast_p | 113 | 0 | -mesh_4x4x3_2cycle_xy | 121 | 0 | -mesh_4x4x3_vc_nonspec | 121 | 0 | -mesh_4x4x3_vc_spec1 | 123 | 0 | -mesh_4x4x3_vc_spec2 | 129 | 0 | -mesh_8x8_2cycle_adaptive | 121 | 0 | -mesh_8x8_2cycle_west_first | 128 | 0 | -mesh_8x8_2cycle_xy | 124 | 0 | -mesh_8x8_4vc | 124 | 0 | -mesh_8x8_4vc_4c | 124 | 0 | -mesh_8x8_4vc_hetero1 | 135 | 0 | -mesh_8x8_4vc_hetero2 | 135 | 0 | -mesh_8x8_b2 | 123 | 0 | -mesh_8x8_sbp6_xy | 137 | 0 | -mesh_8x8_single_flit | 125 | 0 | -mesh_8x8_ssa_xy | 144 | 0 | -ring_8x8_2cycle_xy | 132 | 0 | -star_6 | 124 | 0 | -star6_2cycle_mcast_par | 116 | 0 | -torus_8x8_2cycle_xy | 132 | 0 | +Configuration | # Warnings | # Errors | # Instants | +bintree_k3_L3_st | 125 | 0 | 5847 | +custom1_topology | 124 | 0 | 7076 | +Fattree_k3_L3_st | 126 | 0 | 15933 | +fmesh_1x1_openpiton | 136 | 0 | 430 | +fmesh_2x2_openpiton | 139 | 0 | 1671 | +fmesh_8x8_2cycle_xy | 119 | 0 | 38595 | +fmesh_8x8_openpiton | 139 | 0 | 26691 | +line4_smart3 | 161 | 0 | 1263 | +line_4_v1_B15 | 146 | 0 | 1071 | +line_8_single_flit | 142 | 0 | 3147 | +mesh_2x2_openpiton | 152 | 0 | 1751 | +mesh_3x3_v2_ssa | 138 | 0 | 5430 | +mesh_4x4_2cycle_mcast_f | 119 | 0 | 9811 | +mesh_4x4_LB5_B4 | 117 | 0 | 9619 | +mesh_4x4_selflp_mcast_f | 118 | 0 | 9011 | +mesh_4x4_smart3 | 138 | 0 | 7683 | +mesh_4x4_v1_B15 | 133 | 0 | 6883 | +mesh_4x4x2_bcast_f | 119 | 0 | 12291 | +mesh_4x4x2_bcast_p | 119 | 0 | 12291 | +mesh_4x4x2_mcast_p | 118 | 0 | 12291 | +mesh_4x4x3_2cycle_xy | 126 | 0 | 14099 | +mesh_4x4x3_vc_nonspec | 126 | 0 | 14099 | +mesh_4x4x3_vc_spec1 | 128 | 0 | 14707 | +mesh_4x4x3_vc_spec2 | 134 | 0 | 14707 | +mesh_8x8_2cycle_adaptive | 125 | 0 | 43971 | +mesh_8x8_2cycle_west_first | 132 | 0 | 43267 | +mesh_8x8_2cycle_xy | 128 | 0 | 40323 | +mesh_8x8_4vc | 128 | 0 | 60803 | +mesh_8x8_4vc_4c | 128 | 0 | 62083 | +mesh_8x8_4vc_hetero1 | 137 | 0 | 54173 | +mesh_8x8_4vc_hetero2 | 137 | 0 | 54485 | +mesh_8x8_b2 | 127 | 0 | 40323 | +mesh_8x8_sbp6_xy | 140 | 0 | 47363 | +mesh_8x8_single_flit | 129 | 0 | 40643 | +mesh_8x8_ssa_xy | 144 | 0 | 42755 | +ring_8x8_2cycle_xy | 136 | 0 | 40515 | +star_6 | 129 | 0 | 615 | +star6_2cycle_mcast_par | 121 | 0 | 691 | +torus_8x8_2cycle_xy | 136 | 0 | 40515 | diff --git a/mpsoc/Integration_test/verilator_lint/run.sh b/mpsoc/Integration_test/verilator_lint/run.sh index 104c52d..3ce231e 100644 --- a/mpsoc/Integration_test/verilator_lint/run.sh +++ b/mpsoc/Integration_test/verilator_lint/run.sh @@ -13,7 +13,7 @@ report_file="${log_dir}/report.txt" mkdir -p "$work" mkdir -p "$log_dir" rm -rf "$report_file" -printf "%-30s | %-10s | %-10s |\n" "Configuration" "# Warnings" "# Errors" >> "$report_file" +printf "%-30s | %-10s | %-10s | %-10s |\n" "Configuration" "# Warnings" "# Errors" "# Instants" >> "$report_file" # List of Verilator warnings to suppress @@ -29,7 +29,7 @@ verilator_lint () { conf=$1 conf_file="${conf_dir}/$conf" log_file="${log_dir}/${conf}.log" - + xml_file="${log_dir}/${conf}.xml" if [[ ! -f "$conf_file" ]]; then echo "Configuration file $conf_file does not exist" exit 1 @@ -44,15 +44,19 @@ verilator_lint () { done # Lint using Verilator - verilator --lint-only -Wall $ignore_flags -Wno-fatal -f "$file_list_f" --top-module noc_top_v > "$log_file" 2>&1 + verilator --xml-output $xml_file --lint-only -Wall $ignore_flags -Wno-fatal -f "$file_list_f" --top-module noc_top_v > "$log_file" 2>&1 + perl "${SCRPT_DIR_PATH}/src/instant_export.pl" "$xml_file" >> "$log_file" + } + report_total_errors_warnings () { conf="$1" log_file="${log_dir}/${conf}.log" warnings=$(grep '%Warning' "$log_file" | wc -l) errors=$(grep '%Error' "$log_file" | wc -l) - printf "%-30s | %-10s | %-10s |\n" "$conf" "$warnings" "$errors" >> "$report_file" + instant=$(awk '/Total module instantiations:/ { print $NF }' "$log_file") + printf "%-30s | %-10s | %-10s | %-10s |\n" "$conf" "$warnings" "$errors" "$instant" >> "$report_file" } run_config () { @@ -95,7 +99,7 @@ fi echo "Report saved in $report_file" echo "Summary:" -echo "-------------------------------|------------|------------|" +echo "-------------------------------|------------|------------|------------|" cat "$report_file" echo "Comparing with golden reference..." diff --git a/mpsoc/Integration_test/verilator_lint/src/instant_export.pl b/mpsoc/Integration_test/verilator_lint/src/instant_export.pl new file mode 100644 index 0000000..7e96b96 --- /dev/null +++ b/mpsoc/Integration_test/verilator_lint/src/instant_export.pl @@ -0,0 +1,41 @@ +#!/usr/bin/perl +use strict; +use warnings; + +die "Usage: $0 \n" unless @ARGV; +my $xml_file = shift; + +open my $fh, '<', $xml_file or die "Could not open '$xml_file': $!"; +my $instants=0; +my %insts; +while (my $line = <$fh>) { + chomp $line; # Remove the newline character + if ($line =~ / $max_key_len ? length($_) : $max_key_len for keys %insts; + +# Print sorted by value, aligned +foreach my $key (sort { $insts{$b} <=> $insts{$a} } keys %insts) { + printf "%-*s %d\n", $max_key_len, $key, $insts{$key}; +} + +close $fh; + From 6a7e6157f9797d5b706ff37ed17f8a86285df074 Mon Sep 17 00:00:00 2001 From: amonemi Date: Sun, 3 Aug 2025 16:43:19 +0200 Subject: [PATCH 078/107] reduce instants number --- mpsoc/rtl/src_noc/router_bypass.sv | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/mpsoc/rtl/src_noc/router_bypass.sv b/mpsoc/rtl/src_noc/router_bypass.sv index 9bb1b0a..69a8bf1 100644 --- a/mpsoc/rtl/src_noc/router_bypass.sv +++ b/mpsoc/rtl/src_noc/router_bypass.sv @@ -44,7 +44,7 @@ module onehot_mux_1D #( )( input [W*N-1 : 0] D_in, input [N-1 : 0] sel, - output [W-1 : 0] Q_out + output reg [W-1 : 0] Q_out ); wire [W-1 : 0] in_array [N-1 : 0]; @@ -55,15 +55,13 @@ module onehot_mux_1D #( end endgenerate - onehot_mux_2D #( - .W(W), - .N(N) - ) onehot_mux_2D ( - .D_in(in_array), - .sel(sel), - .Q_out(Q_out) - ); -endmodule + //onehot_mux_2D + always_comb begin + Q_out = {W{1'b0}}; + for (int i = 0; i < N; i++) + Q_out |= (sel[i]) ? in_array[i] : {W{1'b0}}; + end +endmodule module onehot_mux_1D_reverse #( From 6fa93186a214b04ec9cbc75ea0b2eea4a17668e4 Mon Sep 17 00:00:00 2001 From: amonemi Date: Mon, 4 Aug 2025 01:23:42 +0200 Subject: [PATCH 079/107] fix linting warning. reduce instant count --- mpsoc/rtl/src_noc/comb-spec1.sv | 28 ++++++++--------- mpsoc/rtl/src_noc/comb_spec2.sv | 2 -- mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv | 7 +---- mpsoc/rtl/src_noc/crossbar.sv | 38 ++++++++--------------- mpsoc/rtl/src_noc/inout_ports.sv | 7 +---- mpsoc/rtl/src_noc/input_ports.sv | 4 +-- mpsoc/rtl/src_noc/output_ports.sv | 2 -- mpsoc/rtl/src_noc/router_bypass.sv | 4 +-- mpsoc/rtl/src_noc/router_two_stage.sv | 26 ++++++++-------- mpsoc/rtl/src_noc/wrra.sv | 14 ++++----- 10 files changed, 52 insertions(+), 80 deletions(-) diff --git a/mpsoc/rtl/src_noc/comb-spec1.sv b/mpsoc/rtl/src_noc/comb-spec1.sv index f6e3128..90c8b8e 100755 --- a/mpsoc/rtl/src_noc/comb-spec1.sv +++ b/mpsoc/rtl/src_noc/comb-spec1.sv @@ -40,7 +40,6 @@ module comb_spec1_allocator #( granted_ovc_num_all, ivc_num_getting_ovc_grant, ivc_num_getting_sw_grant, - spec_first_arbiter_granted_ivc_all, nonspec_first_arbiter_granted_ivc_all, granted_dest_port_all, nonspec_granted_dest_port_all, @@ -73,7 +72,6 @@ module comb_spec1_allocator #( output [PV-1 : 0] ivc_num_getting_ovc_grant; output [PV-1 : 0] ivc_num_getting_sw_grant; output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; - output [PV-1 : 0] spec_first_arbiter_granted_ivc_all; output [PP_1-1 : 0] granted_dest_port_all; output [PP_1-1 : 0] nonspec_granted_dest_port_all; output [P-1 : 0] any_ivc_sw_request_granted_all; @@ -112,26 +110,26 @@ module comb_spec1_allocator #( .reset(reset) ); - wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; - wire [VV-1 : 0] masked_candidate_ovc_per_port [P-1 : 0] ; - wire [V-1 : 0] spec_first_arbiter_granted_ivc_per_port[P-1 : 0] ; - wire [V-1 : 0] spec_first_arbiter_ovc_request [P-1 : 0] ; - wire [V-1 : 0] spec_first_arbiter_ovc_granted [P-1 : 0] ; - wire [P_1-1 : 0] spec_granted_dest_port_per_port [P-1 : 0]; - wire [VP_1-1 : 0] cand_ovc_granted [P-1 : 0]; - wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; - wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; - wire [V-1 : 0] ivc_local_num_getting_ovc_grant [P-1 : 0]; + wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; + wire [VV-1 : 0] masked_candidate_ovc_per_port [P-1 : 0] ; + wire [V-1 : 0] spec_first_arbiter_granted_ivc_per_port[P-1 : 0] ; + wire [V-1 : 0] spec_first_arbiter_ovc_request [P-1 : 0] ; + wire [V-1 : 0] spec_first_arbiter_ovc_granted [P-1 : 0] ; + wire [P_1-1 : 0] spec_granted_dest_port_per_port [P-1 : 0]; + wire [VP_1-1 : 0] cand_ovc_granted [P-1 : 0]; + wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; + wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; + wire [V-1 : 0] ivc_local_num_getting_ovc_grant [P-1 : 0]; genvar i,j; generate for(i=0;i< P;i=i+1) begin :P_ for(j=0;j< V;j=j+1) begin : V_ //merge masked_candidate_ovc in each port - assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; + assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; end//for j - assign spec_first_arbiter_granted_ivc_per_port[i] =spec_first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; - assign spec_granted_dest_port_per_port[i] =spec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; + assign spec_first_arbiter_granted_ivc_per_port[i] = spec_first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; + assign spec_granted_dest_port_per_port[i] = spec_granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; // multiplex candidate OVC of first level switch allocatore winner one_hot_mux #( .IN_WIDTH (VV), diff --git a/mpsoc/rtl/src_noc/comb_spec2.sv b/mpsoc/rtl/src_noc/comb_spec2.sv index 011553d..6a2633b 100755 --- a/mpsoc/rtl/src_noc/comb_spec2.sv +++ b/mpsoc/rtl/src_noc/comb_spec2.sv @@ -41,7 +41,6 @@ module comb_spec2_allocator #( granted_ovc_num_all, ivc_num_getting_ovc_grant, ivc_num_getting_sw_grant, - spec_first_arbiter_granted_ivc_all, nonspec_first_arbiter_granted_ivc_all, granted_dest_port_all, nonspec_granted_dest_port_all, @@ -73,7 +72,6 @@ module comb_spec2_allocator #( output [PV-1 : 0] ivc_num_getting_ovc_grant; output [PV-1 : 0] ivc_num_getting_sw_grant; output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; - output [PV-1 : 0] spec_first_arbiter_granted_ivc_all; output [PP_1-1 : 0] granted_dest_port_all; output [PP_1-1 : 0] nonspec_granted_dest_port_all; output [P-1 : 0] any_ivc_sw_request_granted_all; diff --git a/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv b/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv index ea0d907..82c94a8 100755 --- a/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv +++ b/mpsoc/rtl/src_noc/combined_vc_sw_alloc.sv @@ -35,7 +35,6 @@ module combined_vc_sw_alloc #( granted_ovc_num_all, ivc_num_getting_ovc_grant, ivc_num_getting_sw_grant, - spec_first_arbiter_granted_ivc_all, nonspec_first_arbiter_granted_ivc_all, granted_dest_port_all, nonspec_granted_dest_port_all, @@ -66,7 +65,6 @@ module combined_vc_sw_alloc #( output [PV-1 : 0] ivc_num_getting_ovc_grant; output [PV-1 : 0] ivc_num_getting_sw_grant; output [PV-1 : 0] nonspec_first_arbiter_granted_ivc_all; - output [PV-1 : 0] spec_first_arbiter_granted_ivc_all; output [P-1 : 0] any_ivc_sw_request_granted_all; output [P-1 : 0] any_ovc_granted_in_outport_all; output [PP_1-1 : 0] granted_dest_port_all; @@ -139,7 +137,6 @@ module combined_vc_sw_alloc #( .granted_ovc_num_all(granted_ovc_num_all), .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant), .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant), - .spec_first_arbiter_granted_ivc_all(spec_first_arbiter_granted_ivc_all), .nonspec_first_arbiter_granted_ivc_all(nonspec_first_arbiter_granted_ivc_all), .granted_dest_port_all(granted_dest_port_all), .nonspec_granted_dest_port_all(nonspec_granted_dest_port_all), @@ -167,7 +164,6 @@ module combined_vc_sw_alloc #( .granted_ovc_num_all(granted_ovc_num_all), .ivc_num_getting_ovc_grant(ivc_num_getting_ovc_grant), .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant), - .spec_first_arbiter_granted_ivc_all(spec_first_arbiter_granted_ivc_all), .nonspec_first_arbiter_granted_ivc_all(nonspec_first_arbiter_granted_ivc_all), .granted_dest_port_all(granted_dest_port_all), .nonspec_granted_dest_port_all(nonspec_granted_dest_port_all), @@ -231,8 +227,7 @@ module combined_vc_sw_alloc #( end assign nonspec_granted_dest_port_all = granted_dest_port_all; assign spec_granted_dest_port_all = {PP_1{1'b0}}; - assign spec_ovc_num_all = {PVV{1'b0}}; - assign spec_first_arbiter_granted_ivc_all = nonspec_first_arbiter_granted_ivc_all ; + assign spec_ovc_num_all = {PVV{1'b0}}; end endgenerate endmodule \ No newline at end of file diff --git a/mpsoc/rtl/src_noc/crossbar.sv b/mpsoc/rtl/src_noc/crossbar.sv index 0bb8d6f..51094c0 100755 --- a/mpsoc/rtl/src_noc/crossbar.sv +++ b/mpsoc/rtl/src_noc/crossbar.sv @@ -39,19 +39,17 @@ module crossbar #( localparam P_1 = (SELF_LOOP_EN )? P : P-1, PP_1 = P_1 * P, - PFw = P*Fw, - P_1Fw = P_1 * Fw, P_1w = log2(P_1); input [PP_1-1 : 0] granted_dest_port_all; - input [PFw-1 : 0] flit_in_all; - output [PFw-1 : 0] flit_out_all; + input [Fw-1 : 0] flit_in_all[P-1 : 0]; + output logic [Fw-1 : 0] flit_out_all [P-1 : 0]; output [P-1 : 0] flit_out_wr_all; input [P-1 : 0] ssa_flit_wr_all; wire [P-1 : 0] flit_we_mux_out; wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; - wire [P_1Fw-1 : 0] mux_in [P-1 : 0]; + wire [Fw-1 : 0] mux_in [P-1 : 0][P_1-1 : 0]; wire [P_1-1 : 0] mux_sel_pre [P-1 : 0]; wire [P_1-1 : 0] mux_sel [P-1 : 0]; wire [P_1w-1 : 0] mux_sel_bin [P-1 : 0]; @@ -65,15 +63,15 @@ module crossbar #( if(SELF_LOOP_EN == 0) begin : nslp //remove sender port flit from flit list if(i>j) begin - assign mux_in[i][(j+1)*Fw-1 : j*Fw]= flit_in_all[(j+1)*Fw-1 : j*Fw]; + assign mux_in[i][j]= flit_in_all[j]; assign mux_sel_pre[i][j] = granted_dest_port[j][i-1]; end else if(i Date: Mon, 4 Aug 2025 12:10:24 +0200 Subject: [PATCH 080/107] fix linting warning --- mpsoc/rtl/src_noc/crossbar.sv | 23 ++++++++++------------- mpsoc/rtl/src_noc/router_two_stage.sv | 17 +++++++++-------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/mpsoc/rtl/src_noc/crossbar.sv b/mpsoc/rtl/src_noc/crossbar.sv index 51094c0..a4840a2 100755 --- a/mpsoc/rtl/src_noc/crossbar.sv +++ b/mpsoc/rtl/src_noc/crossbar.sv @@ -38,17 +38,15 @@ module crossbar #( localparam P_1 = (SELF_LOOP_EN )? P : P-1, - PP_1 = P_1 * P, P_1w = log2(P_1); - input [PP_1-1 : 0] granted_dest_port_all; + input [P_1-1 : 0] granted_dest_port_all[P-1 : 0]; input [Fw-1 : 0] flit_in_all[P-1 : 0]; output logic [Fw-1 : 0] flit_out_all [P-1 : 0]; output [P-1 : 0] flit_out_wr_all; input [P-1 : 0] ssa_flit_wr_all; wire [P-1 : 0] flit_we_mux_out; - wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; wire [Fw-1 : 0] mux_in [P-1 : 0][P_1-1 : 0]; wire [P_1-1 : 0] mux_sel_pre [P-1 : 0]; wire [P_1-1 : 0] mux_sel [P-1 : 0]; @@ -58,21 +56,20 @@ module crossbar #( genvar i,j; generate for(i=0;ij) begin - assign mux_in[i][j]= flit_in_all[j]; - assign mux_sel_pre[i][j] = granted_dest_port[j][i-1]; + assign mux_in[i][j] = flit_in_all[j]; + assign mux_sel_pre[i][j] = granted_dest_port_all[j][i-1]; end else if(i Date: Mon, 4 Aug 2025 12:58:32 +0200 Subject: [PATCH 081/107] reduce instant number --- mpsoc/rtl/src_noc/comb_nonspec.sv | 47 +++++-------------------- mpsoc/rtl/src_noc/input_ports.sv | 11 +----- mpsoc/rtl/src_noc/mesh_torus.sv | 10 +----- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 8 ++--- mpsoc/rtl/src_noc/multicast.sv | 1 - mpsoc/rtl/src_noc/noc_top.sv | 4 +-- mpsoc/rtl/src_noc/output_ports.sv | 29 ++------------- mpsoc/rtl/src_noc/wrra.sv | 24 ++----------- 8 files changed, 21 insertions(+), 113 deletions(-) diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index 847d74a..f426a48 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -177,15 +177,8 @@ module comb_nonspec_allocator # ( .Q_out(candidate_ovc_local_num[i]), .sel(first_arbiter_granted_ivc_per_port[i]) ); - - onehot_mux_1D #( - .W (1), - .N (V) - ) mux2_1 ( - .D_in(ovc_is_assigned_all[(i+1)*V-1 : i*V]), - .Q_out(ovc_assigned_local[i]), - .sel (first_arbiter_granted_ivc_per_port [i]) - ); + //one hot mux to select granted OVC + assign ovc_assigned_local[i] = |(ovc_is_assigned_all[(i+1)*V-1 : i*V] & first_arbiter_granted_ivc_per_port [i]); //demultiplexer one_hot_demux #( @@ -503,17 +496,9 @@ module nonspec_sw_alloc #( if(MIN_PCK_SIZE == 1) begin //single_flit req multiplexer assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; - onehot_mux_1D #( - .W (1), - .N (V) - ) mux2 ( - .D_in(pck_is_single_flit [i]), - .Q_out(single_flit_pck_local_grant[i]), - .sel (first_arbiter_grant[i]) - ); - + //one hot mux to select single flit packet + assign single_flit_pck_local_grant[i] = |(pck_is_single_flit[i] & first_arbiter_grant[i]); assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; - if (SELF_LOOP_EN == 0) begin add_sw_loc_one_hot #( .P(P), @@ -608,16 +593,8 @@ module swa_input_port_arbiter #( generate if(IS_WRRA) begin: wrra_ - // one hot mux - onehot_mux_1D #( - .W(1), - .N(ARBITER_WIDTH) - ) mux ( - .D_in(vc_weight_is_consumed), - .Q_out(winner_weight_consumed), - .sel(grant) - ); - + // one hot mux + assign winner_weight_consumed = |(vc_weight_is_consumed & grant); wire priority_en = (EXT_P_EN == 1) ? ext_pr_en_i & winner_weight_consumed : winner_weight_consumed; //round robin arbiter with external priority @@ -688,16 +665,8 @@ module swa_output_port_arbiter #( if(IS_WRRA) begin : wrra // second level wrra priority is only changed if the granted request weight is consumed wire pr_en; - - onehot_mux_1D #( - .W(1), - .N(ARBITER_WIDTH) - ) mux ( - .D_in(weight_consumed), - .Q_out(pr_en), - .sel(grant) - ); - + //one hot mux + assign pr_en = |(weight_consumed & grant); arbiter_priority_en #( .ARBITER_WIDTH (ARBITER_WIDTH) ) arb ( diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index dedf8bd..8e82976 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -348,7 +348,6 @@ module input_queue_per_port #( assign wr_hdr_fwft_fifo = hdr_flit_wr | (smart_hdr_en & ~ smart_ctrl_in.ivc_single_flit_pck); assign ivc_request = ivc_not_empty; - wire [V-1 : 0] flit_is_tail2; always_ff @ (`pronoc_clk_reset_edge) begin if (`pronoc_reset) begin ovc_is_assigned <= '0; @@ -816,15 +815,7 @@ module input_queue_per_port #( if(~IS_RRA) begin : wrra wire granted_flit_is_tail; - - onehot_mux_1D #( - .W(1), - .N(V) - )onehot_mux( - .D_in(flit_is_tail), - .Q_out(granted_flit_is_tail), - .sel(ivc_num_getting_sw_grant) - ); + assign granted_flit_is_tail = |(flit_is_tail & ivc_num_getting_sw_grant); weight_control#( .ARBITER_TYPE(SWA_ARBITER_TYPE), diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index a3d20e1..0cac8ed 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -623,15 +623,7 @@ module regular_topo_adaptive_lk_dest_encoder #( wire [1 : 0] ab,xy; wire sel_muxed; - - onehot_mux_1D #( - .W(1), - .N(V) - ) sel_mux ( - .D_in(sel), - .Q_out(sel_muxed), - .sel(vc_num_delayed) - ); + assign sel_muxed = |(sel & vc_num_delayed); //lkdestport = {lkdestport_x[1:0],lkdestport_y[1:0]}; // sel: 0: xdir 1: ydir diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index c234183..067b0db 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -56,8 +56,8 @@ module regular_topo_noc_top ( genvar x,y,l; generate - if( IS_RING | IS_LINE) begin : ring_line - for (x=0; x Date: Mon, 4 Aug 2025 18:34:10 +0200 Subject: [PATCH 082/107] reduce instant number --- mpsoc/rtl/src_noc/comb_nonspec.sv | 96 +++++++++++------------- mpsoc/rtl/src_noc/crossbar.sv | 18 ++--- mpsoc/rtl/src_noc/flit_buffer.sv | 84 +++++++-------------- mpsoc/rtl/src_noc/header_flit.sv | 51 +++++-------- mpsoc/rtl/src_noc/inout_ports.sv | 30 ++++---- mpsoc/rtl/src_noc/input_ports.sv | 67 ++++++----------- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 41 ++++------ mpsoc/rtl/src_noc/output_ports.sv | 22 +++--- 8 files changed, 163 insertions(+), 246 deletions(-) diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index f426a48..a26f6fc 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -117,9 +117,9 @@ module comb_nonspec_allocator # ( wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; wire [PV-1 : 0] masked_assigned_request; wire [PV-1 : 0] assigned_ovc_request_all ; - wire [VV-1 : 0] masked_candidate_ovc_per_port [P-1 : 0] ; + wire [V-1 : 0] masked_candidate_ovc_per_port [P-1 : 0][V-1:0]; wire [V-1 : 0] first_arbiter_granted_ivc_per_port[P-1 : 0] ; - wire [V-1 : 0] candidate_ovc_local_num [P-1 : 0] ; + logic [V-1 : 0] candidate_ovc_local_num [P-1 : 0] ; wire [V-1 : 0] first_arbiter_ovc_granted [PV-1 : 0]; wire [P_1-1 : 0] granted_dest_port_per_port [P-1 : 0]; wire [VP_1-1 : 0] cand_ovc_granted [P-1 : 0]; @@ -161,22 +161,19 @@ module comb_nonspec_allocator # ( assign ivc_request_all[i*V+j] = ivc_info[i][j].ivc_req; assign ovc_is_assigned_all[i*V+j] = ivc_info[i][j].ovc_is_assigned; assign assigned_ovc_not_full_all[i*V+j] =ivc_info[i][j].assigned_ovc_not_full; - assign masked_candidate_ovc_per_port[i][(j+1)*V-1 : j*V] = first_arbiter_ovc_granted [i*V+j]; + assign masked_candidate_ovc_per_port[i][j] = first_arbiter_ovc_granted [i*V+j]; assign granted_ovc_num_all[(i*VV)+((j+1)*V)-1 : (i*VV)+(j*V)]=granted_ovc_local_num_per_port[i]; end//for j assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - // multiplex candidate OVC of first level switch allocatore winner - onehot_mux_1D #( - .W(V), - .N(V) - ) mux2 ( - .D_in(masked_candidate_ovc_per_port[i]), - .Q_out(candidate_ovc_local_num[i]), - .sel(first_arbiter_granted_ivc_per_port[i]) - ); + //One-hot multiplex candidate OVC of first level switch allocator winner + always_comb begin + candidate_ovc_local_num [i] = '0; + for (int k = 0; k < V; k++) + candidate_ovc_local_num [i] |= (first_arbiter_granted_ivc_per_port[i][k]) ? masked_candidate_ovc_per_port[i][k] : '0; + end //one hot mux to select granted OVC assign ovc_assigned_local[i] = |(ovc_is_assigned_all[(i+1)*V-1 : i*V] & first_arbiter_granted_ivc_per_port [i]); @@ -309,16 +306,16 @@ module comb_nonspec_v2_allocator #( wire [V-1 : 0] masked_non_assigned_request [PV-1 : 0] ; wire [PV-1 : 0] masked_assigned_request; wire [PV-1 : 0] assigned_ovc_request_all; - wire [VV-1 : 0] masked_non_assigned_request_per_port [P-1 : 0] ; + wire [V-1 : 0] masked_non_assigned_request_per_port [P-1 : 0][V-1 : 0]; wire [V-1 : 0] first_arbiter_granted_ivc_per_port[P-1 : 0] ; - wire [V-1 : 0] candidate_ovc_local_num [P-1 : 0] ; + logic [V-1 : 0] candidate_ovc_local_num [P-1 : 0] ; wire [V-1 : 0] first_arbiter_ovc_granted [P-1:0]; wire [P_1-1 : 0] granted_dest_port_per_port [P-1 : 0]; - wire [VP_1-1 : 0] cand_ovc_granted [P-1 : 0]; - wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; + wire [VP_1-1 : 0] cand_ovc_granted [P-1 : 0]; + wire [P_1-1 : 0] ovc_allocated_all_gen [PV-1 : 0]; wire [V-1 : 0] granted_ovc_local_num_per_port [P-1 : 0]; wire [V-1 : 0] ivc_local_num_getting_ovc_grant[P-1 : 0]; - wire [V : 0] summ_in [PV-1 : 0]; + wire [V : 0] summ_in [PV-1 : 0]; assign assigned_ovc_request_all = ivc_request_all & ovc_is_assigned_all; genvar i,j; @@ -326,8 +323,8 @@ module comb_nonspec_v2_allocator #( // IVC loop for(i=0;i< PV;i=i+1) begin :PV_ // mask unavailable ovc from requests - assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; - assign masked_assigned_request [i] = assigned_ovc_not_full_all[i] & assigned_ovc_request_all[i]; + assign masked_non_assigned_request [i] = masked_ovc_request_all [(i+1)*V-1 : i*V ]; + assign masked_assigned_request [i] = assigned_ovc_not_full_all[i] & assigned_ovc_request_all[i]; // summing assigned and non-assigned VC requests assign summ_in[i] ={masked_non_assigned_request [i],masked_assigned_request [i]}; assign ivc_request_masked_all[i] = | summ_in[i]; @@ -336,20 +333,17 @@ module comb_nonspec_v2_allocator #( for(i=0;i< P;i=i+1) begin : P_ for(j=0;j< V;j=j+1) begin : V_ //merge masked_candidate_ovc in each port - assign masked_non_assigned_request_per_port[i][(j+1)*V-1 : j*V] = masked_non_assigned_request [i*V+j]; + assign masked_non_assigned_request_per_port[i][j] = masked_non_assigned_request [i*V+j]; assign granted_ovc_num_all[(i*VV)+((j+1)*V)-1 : (i*VV)+(j*V)]=granted_ovc_local_num_per_port[i]; end//for j assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - - onehot_mux_1D #( - .W(V), - .N(V) - ) mux2 ( - .D_in(masked_non_assigned_request_per_port [i]), - .Q_out(candidate_ovc_local_num [i]), - .sel (first_arbiter_granted_ivc_per_port [i]) - ); + //One-hot multiplex candidate OVC of first level switch allocator winner + always_comb begin + candidate_ovc_local_num [i] = '0; + for (int k = 0; k < V; k++) + candidate_ovc_local_num [i] |= (first_arbiter_granted_ivc_per_port[i][k]) ? masked_non_assigned_request_per_port[i][k] : '0; + end assign any_cand_ovc_exsit[i] = | candidate_ovc_local_num [i]; //first level arbiter to candidate only one OVC @@ -418,7 +412,6 @@ module nonspec_sw_alloc #( localparam P_1 = (SELF_LOOP_EN) ? P : P-1, PV = V * P, - VP_1 = V * P_1, PP_1 = P_1 * P, PVP_1 = PV * P_1; @@ -439,25 +432,23 @@ module nonspec_sw_alloc #( //separte input per port wire [V-1 : 0] ivc_granted [P-1 : 0]; wire [V-1 : 0] pck_is_single_flit [P-1 : 0]; - wire [VP_1-1 : 0] dest_port_ivc [P-1 : 0]; + wire [P_1-1 : 0] dest_port_ivc [P-1 : 0][V-1 : 0]; wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; wire [P_1-1 : 0] single_flit_granted_dst [P-1 : 0]; wire [P-1 : 0] single_flit_granted_dst_all [P-1 : 0]; - // internal wires - wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and - wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter + wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and + wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter wire [P-1 : 0] single_flit_pck_local_grant; - wire [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer - wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; - wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; + logic [P_1-1 : 0] dest_port [P-1 : 0];//output of multiplexer + wire [P_1-1 : 0] second_arbiter_request [P-1 : 0]; + wire [P_1-1 : 0] second_arbiter_grant [P-1 : 0]; wire [P_1-1 : 0] second_arbiter_weight_consumed [P-1 : 0]; wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; - wire [P-1 :0] winner_weight_consumed; + wire [P-1 : 0] winner_weight_consumed; genvar i,j; generate - for(i=0;i< P;i=i+1) begin : P_ //assign in/out to the port based wires //output @@ -466,9 +457,11 @@ module nonspec_sw_alloc #( assign first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V] = first_arbiter_grant[i]; //input assign ivc_masked[i] = ivc_request_masked_all [(i+1)*V-1 : i*V]; - assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; + //assign dest_port_ivc[i] = dest_port_all [(i+1)*VP_1-1 : i*VP_1]; assign vc_weight_is_consumed[i] = vc_weight_is_consumed_all [(i+1)*V-1 : i*V]; - + for (j=0;j destport_in_bin ) ? destport_in_bin : destport_in_bin -1'b1; assign destport_out_bin=temp[P_1w-1 : 0]; - - //bin_to_one_hot - always_comb begin - destport_out = {P_1{1'b0}}; - destport_out[destport_out_bin] = 1'b1; - end endmodule /************************************** diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index e119fdc..4a31acf 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -465,25 +465,21 @@ module oport_ovc_sig_gen #( output [VP_1-1 : 0] credit_decreased; output [VP_1-1 : 0] ovc_released; - wire [V-1 : 0] muxout1; + logic [V-1 : 0] muxout1; wire muxout2; - wire [VV-1 : 0] assigned_ovc_num_masked; + wire [V-1 : 0] assigned_ovc_num_masked[V-1 : 0]; genvar i; generate for (i=0;i Date: Mon, 4 Aug 2025 19:39:29 +0200 Subject: [PATCH 083/107] fix questasim linting warnings --- mpsoc/rtl/src_noc/comb_nonspec.sv | 54 ++++++++++++++--------------- mpsoc/rtl/src_noc/crossbar.sv | 22 ++++++------ mpsoc/rtl/src_noc/flit_buffer.sv | 56 +++++++++++++------------------ mpsoc/rtl/src_noc/inout_ports.sv | 20 ++++++----- mpsoc/rtl/src_noc/input_ports.sv | 16 +++++---- 5 files changed, 82 insertions(+), 86 deletions(-) diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index a26f6fc..6503470 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -129,7 +129,14 @@ module comb_nonspec_allocator # ( wire [V : 0] summ_in [PV-1 : 0]; assign assigned_ovc_request_all = ivc_request_all & ovc_is_assigned_all; - + //One-hot multiplex candidate OVC of first level switch allocator winner + always_comb begin + for(int m=0;m< P;m++) begin + candidate_ovc_local_num [m] = '0; + for (int k = 0; k < V; k++) + candidate_ovc_local_num [m] |= (first_arbiter_granted_ivc_per_port[m][k]) ? masked_candidate_ovc_per_port[m][k] : '0; + end + end genvar i,j; generate // IVC loop @@ -154,7 +161,6 @@ module comb_nonspec_allocator # ( end//for wire [P-1 : 0] ovc_assigned_local; - for(i=0;i< P;i=i+1) begin :P_ for(j=0;j< V;j=j+1) begin :V_ //merge masked_candidate_ovc in each port @@ -164,19 +170,10 @@ module comb_nonspec_allocator # ( assign masked_candidate_ovc_per_port[i][j] = first_arbiter_ovc_granted [i*V+j]; assign granted_ovc_num_all[(i*VV)+((j+1)*V)-1 : (i*VV)+(j*V)]=granted_ovc_local_num_per_port[i]; end//for j - assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - - //One-hot multiplex candidate OVC of first level switch allocator winner - always_comb begin - candidate_ovc_local_num [i] = '0; - for (int k = 0; k < V; k++) - candidate_ovc_local_num [i] |= (first_arbiter_granted_ivc_per_port[i][k]) ? masked_candidate_ovc_per_port[i][k] : '0; - end //one hot mux to select granted OVC assign ovc_assigned_local[i] = |(ovc_is_assigned_all[(i+1)*V-1 : i*V] & first_arbiter_granted_ivc_per_port [i]); - //demultiplexer one_hot_demux #( .IN_WIDTH(V), @@ -186,11 +183,9 @@ module comb_nonspec_allocator # ( .demux_in(candidate_ovc_local_num[i]),//repeated .demux_out(cand_ovc_granted [i]) ); - assign granted_ovc_local_num_per_port[i] = (any_ivc_sw_request_granted_all[i] )? candidate_ovc_local_num[i] : {V{1'b0}}; assign ivc_local_num_getting_ovc_grant [i] = (any_ivc_sw_request_granted_all[i] & ~ovc_assigned_local[i])? first_arbiter_granted_ivc_per_port [i] : {V{1'b0}}; assign ivc_num_getting_ovc_grant [(i+1)*V-1 : i*V] = ivc_local_num_getting_ovc_grant[i]; - end//i for(i=0;i< PV;i=i+1) begin :_PV @@ -318,6 +313,15 @@ module comb_nonspec_v2_allocator #( wire [V : 0] summ_in [PV-1 : 0]; assign assigned_ovc_request_all = ivc_request_all & ovc_is_assigned_all; + //One-hot multiplex candidate OVC of first level switch allocator winner + always_comb begin + for(int m=0;m< P;m++) begin + candidate_ovc_local_num [m] = '0; + for (int k = 0; k < V; k++) + candidate_ovc_local_num [m] |= (first_arbiter_granted_ivc_per_port[m][k]) ? masked_non_assigned_request_per_port[m][k] : '0; + end + end + genvar i,j; generate // IVC loop @@ -338,12 +342,7 @@ module comb_nonspec_v2_allocator #( end//for j assign first_arbiter_granted_ivc_per_port[i]=first_arbiter_granted_ivc_all[(i+1)*V-1 : i*V]; assign granted_dest_port_per_port[i]=granted_dest_port_all[(i+1)*P_1-1 : i*P_1]; - //One-hot multiplex candidate OVC of first level switch allocator winner - always_comb begin - candidate_ovc_local_num [i] = '0; - for (int k = 0; k < V; k++) - candidate_ovc_local_num [i] |= (first_arbiter_granted_ivc_per_port[i][k]) ? masked_non_assigned_request_per_port[i][k] : '0; - end + assign any_cand_ovc_exsit[i] = | candidate_ovc_local_num [i]; //first level arbiter to candidate only one OVC @@ -447,6 +446,15 @@ module nonspec_sw_alloc #( wire [V-1 : 0] vc_weight_is_consumed [P-1 : 0]; wire [P-1 : 0] winner_weight_consumed; + //onehot_mux to select destination port + always_comb begin + for (int m = 0; m < P; m++) begin + dest_port[m] = '0; + for (int k = 0; k < V; k++) begin + dest_port[m] |= (first_arbiter_grant[m][k]) ? dest_port_ivc [m][k] : '0; + end + end + end genvar i,j; generate for(i=0;i< P;i=i+1) begin : P_ @@ -476,14 +484,6 @@ module nonspec_sw_alloc #( .vc_weight_is_consumed(vc_weight_is_consumed[i]), .winner_weight_consumed(winner_weight_consumed[i]) ); - //onehot_mux to select destination port - always_comb begin - dest_port[i] = '0; - for (int k = 0; k < V; k++) begin - dest_port[i] |= (first_arbiter_grant[i][k]) ? dest_port_ivc [i][k] : '0; - end - end - if(MIN_PCK_SIZE == 1) begin //single_flit req multiplexer assign pck_is_single_flit[i] = pck_is_single_flit_all [(i+1)*V-1 : i*V]; diff --git a/mpsoc/rtl/src_noc/crossbar.sv b/mpsoc/rtl/src_noc/crossbar.sv index ee05431..99e3c28 100755 --- a/mpsoc/rtl/src_noc/crossbar.sv +++ b/mpsoc/rtl/src_noc/crossbar.sv @@ -53,6 +53,16 @@ module crossbar #( logic [P_1w-1 : 0] mux_sel_bin [P-1 : 0]; wire [P-1 : 0] flit_out_wr_gen [P-1 : 0]; + //one_hot_to_bin + always_comb begin + for(int m=0;m Date: Tue, 5 Aug 2025 00:42:11 +0200 Subject: [PATCH 084/107] fix bug in multicast --- mpsoc/rtl/src_noc/flit_buffer.sv | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index a9c399c..124c62e 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -85,9 +85,6 @@ module flit_buffer reg [PTRw- 1 : 0] sub_rd_ptr_next [V-1 :0]; logic [PTRw- 1 : 0] sub_rd_ptr [V-1 :0]; - wire [ARRAYw-1 : 0] rd_ptr_array; - wire [ARRAYw-1 : 0] wr_ptr_array; - wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_din; wire [RAM_DATA_WIDTH-1 : 0] fifo_ram_dout; wire [V-1 : 0] wr; @@ -153,9 +150,7 @@ module flit_buffer end //always_comb for(i=0;i 0); end else begin : unicast - assign rd_ptr_array[(i+1)*PTRw- 1 : i*PTRw] = rd_ptr[i]; assign vc_not_empty [i] = (depth[i] > 0); end end//for @@ -204,7 +198,8 @@ module flit_buffer for (int k = 0; k < V; k++) begin //One-hot_mux vc_wr_addr |= (vc_num_wr[k]) ? wr_ptr[k] : '0; - vc_rd_addr |= (vc_num_rd[k]) ? rd_ptr[k] : '0; + if (IS_UNICAST) vc_rd_addr |= (vc_num_rd[k]) ? rd_ptr[k] : '0; + else vc_rd_addr |= (vc_num_rd[k]) ? sub_rd_ptr[k] : '0; //One-hot to binary if (vc_num_wr[k]) wr_select_addr = Vw'(k); if (vc_num_rd[k]) rd_select_addr = Vw'(k); From 5c7e69eee6a46be580ff9f7e2d6bf20fde46178c Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 6 Aug 2025 13:47:37 +0200 Subject: [PATCH 085/107] add warning summery report to Intigration_test/verilator linting --- mpsoc/Integration_test/Altera/src/compare.pl | 10 ++- mpsoc/Integration_test/verilator_lint/run.sh | 7 +- mpsoc/rtl/arbiter.v | 62 ++++++++------- mpsoc/rtl/main_comp.v | 13 +--- mpsoc/rtl/src_noc/comb-spec1.sv | 13 +--- mpsoc/rtl/src_noc/comb_nonspec.sv | 35 +++------ mpsoc/rtl/src_noc/comb_spec2.sv | 25 +++--- mpsoc/rtl/src_noc/output_ports.sv | 76 +++++++++---------- mpsoc/rtl/src_noc/routing.sv | 80 +++++++++----------- 9 files changed, 148 insertions(+), 173 deletions(-) diff --git a/mpsoc/Integration_test/Altera/src/compare.pl b/mpsoc/Integration_test/Altera/src/compare.pl index 4cc0f06..632793a 100644 --- a/mpsoc/Integration_test/Altera/src/compare.pl +++ b/mpsoc/Integration_test/Altera/src/compare.pl @@ -13,6 +13,9 @@ my %data1 = parse_file($file1); my %data2 = parse_file($file2); +sub is_number { + return defined $_[0] && $_[0] =~ /^-?\d+(\.\d+)?$/; +} foreach my $design (sort keys %data2) { my @fields = sort keys %{$data2{$design}}; print "=== $design ===\n"; @@ -31,7 +34,12 @@ (($delta < 0 && $i ne 'Maxfrequency') || ($delta > 0 && $i eq 'Maxfrequency')) ? "\e[32m" : # green for negative ""; # default (0) my $reset = "\e[0m"; - printf "%-25s: %10s -> %10s (%s%s%%%s)\n", $i, $v1, $v2, $color, $delta, $reset; + #print only if both $v1 and $v2 are numbers, or one is number the other is 'N/A' + my $print_me = + (is_number($v1) && is_number($v2)) || + (is_number($v1) && $v2 eq 'N/A') || + (is_number($v2) && $v1 eq 'N/A'); + printf "%-25s: %10s -> %10s (%s%s%%%s)\n", $i, $v1, $v2, $color, $delta, $reset if($print_me); } print "\n"; } diff --git a/mpsoc/Integration_test/verilator_lint/run.sh b/mpsoc/Integration_test/verilator_lint/run.sh index 3ce231e..a7731eb 100644 --- a/mpsoc/Integration_test/verilator_lint/run.sh +++ b/mpsoc/Integration_test/verilator_lint/run.sh @@ -13,7 +13,7 @@ report_file="${log_dir}/report.txt" mkdir -p "$work" mkdir -p "$log_dir" rm -rf "$report_file" -printf "%-30s | %-10s | %-10s | %-10s |\n" "Configuration" "# Warnings" "# Errors" "# Instants" >> "$report_file" +printf "%-30s | %-10s | %-10s | %-10s | %s\n" "Configuration" "# Warnings" "# Errors" "# Instants" "Warning Summary">> "$report_file" # List of Verilator warnings to suppress @@ -55,8 +55,11 @@ report_total_errors_warnings () { log_file="${log_dir}/${conf}.log" warnings=$(grep '%Warning' "$log_file" | wc -l) errors=$(grep '%Error' "$log_file" | wc -l) + warning_sep=$(grep -oP '^%Warning-\K[A-Z0-9_]+' "$log_file" | sort | uniq -c | awk '{printf "%s(%d), ", toupper($2), $1}') + # Remove trailing comma and space + #warning_sep=${ warning_sep%, } instant=$(awk '/Total module instantiations:/ { print $NF }' "$log_file") - printf "%-30s | %-10s | %-10s | %-10s |\n" "$conf" "$warnings" "$errors" "$instant" >> "$report_file" + printf "%-30s | %-10s | %-10s | %-10s | %s\n" "$conf" "$warnings" "$errors" "$instant" "$warning_sep">> "$report_file" } run_config () { diff --git a/mpsoc/rtl/arbiter.v b/mpsoc/rtl/arbiter.v index 16708f1..40cf26a 100755 --- a/mpsoc/rtl/arbiter.v +++ b/mpsoc/rtl/arbiter.v @@ -162,21 +162,24 @@ module my_one_hot_arbiter #( endfunction // log2 localparam ARBITER_BIN_WIDTH= log2(ARBITER_WIDTH); - reg [ARBITER_BIN_WIDTH-1 : 0] low_pr; - wire [ARBITER_BIN_WIDTH-1 : 0] grant_bcd; + reg [ARBITER_BIN_WIDTH-1 : 0] low_pr; + reg [ARBITER_BIN_WIDTH-1 : 0] grant_bin; - one_hot_to_bin #( - .ONE_HOT_WIDTH(ARBITER_WIDTH) - )conv ( - .one_hot_code(grant), - .bin_code(grant_bcd) - ); + integer i; + always @(*) begin + grant_bin = '0; + for (i = 0; i < ARBITER_WIDTH; i=i+1) begin + if (grant[i]) begin + grant_bin = ARBITER_BIN_WIDTH'(i); // casting i to BIN_WIDTH + end + end + end always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin low_pr <= {ARBITER_BIN_WIDTH{1'b0}}; end else begin - if(any_grant) low_pr <= grant_bcd; + if(any_grant) low_pr <= grant_bin; end end assign any_grant = | request; @@ -291,22 +294,25 @@ module my_one_hot_arbiter_priority_en #( end endfunction // log2 - localparam ARBITER_BIN_WIDTH= log2(ARBITER_WIDTH); - reg [ARBITER_BIN_WIDTH-1 : 0] low_pr; - wire [ARBITER_BIN_WIDTH-1 : 0] grant_bcd; + localparam ARBITER_BIN_WIDTH = log2(ARBITER_WIDTH); + reg [ARBITER_BIN_WIDTH-1 : 0] low_pr; + reg [ARBITER_BIN_WIDTH-1 : 0] grant_bin; - one_hot_to_bin #( - .ONE_HOT_WIDTH (ARBITER_WIDTH) - )conv ( - .one_hot_code(grant), - .bin_code(grant_bcd) - ); + integer i; + always @(*) begin + grant_bin = '0; + for (i = 0; i < ARBITER_WIDTH; i=i+1) begin + if (grant[i]) begin + grant_bin = ARBITER_BIN_WIDTH'(i); // casting i to BIN_WIDTH + end + end + end always @ (`pronoc_clk_reset_edge )begin if(`pronoc_reset) begin low_pr <= {ARBITER_BIN_WIDTH{1'b0}}; end else begin - if(priority_en) low_pr <= grant_bcd; + if(priority_en) low_pr <= grant_bin; end end @@ -551,15 +557,19 @@ module my_one_hot_arbiter_ext_priority #( endfunction // log2 localparam ARBITER_BIN_WIDTH= log2(ARBITER_WIDTH); - wire [ARBITER_BIN_WIDTH-1 : 0] low_pr; + reg [ARBITER_BIN_WIDTH-1 : 0] low_pr; wire [ARBITER_WIDTH-1 : 0] low_pr_one_hot = {priority_in[0],priority_in[ARBITER_BIN_WIDTH-1:1]}; + //onehot to bin + integer i; + always @(*) begin + low_pr = '0; + for (i = 0; i < ARBITER_WIDTH; i=i+1) begin + if (low_pr_one_hot[i]) begin + low_pr = ARBITER_BIN_WIDTH'(i); // casting i to BIN_WIDTH + end + end + end - one_hot_to_bin #( - .ONE_HOT_WIDTH (ARBITER_WIDTH) - )conv ( - .one_hot_code(low_pr_one_hot), - .bin_code(low_pr) - ); assign any_grant = | request; generate if(ARBITER_WIDTH ==2) begin: w2 arbiter_2_one_hot arb( .D_in(request) , .Q_out(grant), .low_pr(low_pr)); end diff --git a/mpsoc/rtl/main_comp.v b/mpsoc/rtl/main_comp.v index 1bd3f1d..26df719 100755 --- a/mpsoc/rtl/main_comp.v +++ b/mpsoc/rtl/main_comp.v @@ -89,15 +89,10 @@ module one_hot_demux #( input [IN_WIDTH-1 : 0] demux_in,//repeated output [OUT_WIDTH-1 : 0] demux_out ); - - genvar i,j; - generate - for(i=0;i0 && ovc_num[i] >0 && (ovc_num[i] & ovc_status)==0) $display ("%t :Error: OVC status%d missmatch:%b & %b, %m ",$time,i,ovc_num[i] , ovc_status); + if(ovc_status >0 && ovc_num[i] >0 && (ovc_num[i] & ovc_status)==0) $display ("%t: Error: OVC status%d missmatch:%b & %b, %m ",$time,i,ovc_num[i] , ovc_status); end end//for endgenerate diff --git a/mpsoc/rtl/src_noc/routing.sv b/mpsoc/rtl/src_noc/routing.sv index 11c9c8d..d228702 100755 --- a/mpsoc/rtl/src_noc/routing.sv +++ b/mpsoc/rtl/src_noc/routing.sv @@ -305,34 +305,33 @@ module next_router_addr_selector_onehot #( next_rx, next_ry ); - localparam PRXw = P * RXw, PRYw = P * RYw; - input [P-1 : 0] destport_onehot; - input [PRXw-1: 0] neighbors_rx; - input [PRYw-1: 0] neighbors_ry; - output[RXw-1 : 0] next_rx; - output[RYw-1 : 0] next_ry; + input [P-1 : 0] destport_onehot; + input [PRXw-1: 0] neighbors_rx; + input [PRYw-1: 0] neighbors_ry; + output[RXw-1 : 0] next_rx; + output[RYw-1 : 0] next_ry; - onehot_mux_1D #( - .W(RXw), - .N(P) - ) next_x_mux ( - .D_in(neighbors_rx), - .Q_out(next_rx), - .sel(destport_onehot) - ); + wire [RXw-1:0] neighbors_rx_array [P-1: 0]; + wire [RYw-1:0] neighbors_ry_array [P-1: 0]; + genvar i; + generate for(i=0;i Date: Wed, 6 Aug 2025 14:20:23 +0200 Subject: [PATCH 086/107] fix bug --- mpsoc/rtl/src_noc/comb_nonspec.sv | 32 ++++++++++++++++--------------- mpsoc/rtl/src_noc/routing.sv | 19 +++++++++--------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index 517f35b..9b53b98 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -421,7 +421,7 @@ module nonspec_sw_alloc #( wire [P_1-1 : 0] dest_port_ivc [P-1 : 0][V-1 : 0]; wire [P_1-1 : 0] granted_dest_port [P-1 : 0]; wire [P_1-1 : 0] single_flit_granted_dst [P-1 : 0]; - wire [P-1 : 0] single_flit_granted_dst_all [P-1 : 0]; + logic [P-1 : 0] single_flit_granted_dst_all [P-1 : 0]; // internal wires wire [V-1 : 0] ivc_masked [P-1 : 0];//output of mask and wire [V-1 : 0] first_arbiter_grant [P-1 : 0];//output of first arbiter @@ -442,6 +442,22 @@ module nonspec_sw_alloc #( end end end + + //add_sw_loc_one_hot + always_comb begin + for(int m=0;m< P;m++) begin + if(MIN_PCK_SIZE == 1) begin + if (SELF_LOOP_EN == 0) begin + for(int k=0;km) single_flit_granted_dst_all[m][k] = single_flit_granted_dst[m][k-1]; + else if (k==m) single_flit_granted_dst_all[m][k] = 1'b0; + else single_flit_granted_dst_all[m][k] = single_flit_granted_dst[m][k]; + end//for + end else single_flit_granted_dst_all[m][P_1-1 : 0] = single_flit_granted_dst[m]; + end else single_flit_granted_dst_all[m] = {P{1'b0}}; + end//for + end//always + genvar i,j; generate for(i=0;i< P;i=i+1) begin : P_ @@ -477,22 +493,9 @@ module nonspec_sw_alloc #( //one hot mux to select single flit packet assign single_flit_pck_local_grant[i] = |(pck_is_single_flit[i] & first_arbiter_grant[i]); assign single_flit_granted_dst[i] = (single_flit_pck_local_grant[i])? granted_dest_port[i] : {P_1{1'b0}}; - if (SELF_LOOP_EN == 0) begin - add_sw_loc_one_hot #( - .P(P), - .SW_LOC(i) - ) add_sw_loc ( - .destport_in(single_flit_granted_dst[i]), - .destport_out(single_flit_granted_dst_all[i]) - ); - end else begin - assign single_flit_granted_dst_all[i] = single_flit_granted_dst[i]; - end - end else begin assign single_flit_pck_local_grant[i] = 1'b0; assign single_flit_granted_dst[i] = {P_1{1'b0}}; - assign single_flit_granted_dst_all[i] = {P{1'b0}}; end //second arbiter input/output generate for(j=0;j Date: Wed, 6 Aug 2025 15:03:04 +0200 Subject: [PATCH 087/107] reduce instant number --- mpsoc/perl_gui/lib/perl/topology.pl | 4 ++-- mpsoc/rtl/src_noc/crossbar.sv | 28 ++++++++++++++------------- mpsoc/rtl/src_noc/input_ports.sv | 30 +++++++++++++---------------- mpsoc/rtl/src_noc/output_ports.sv | 29 +++++++++++++++------------- 4 files changed, 46 insertions(+), 45 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/topology.pl b/mpsoc/perl_gui/lib/perl/topology.pl index 6e5e3e8..7024415 100644 --- a/mpsoc/perl_gui/lib/perl/topology.pl +++ b/mpsoc/perl_gui/lib/perl/topology.pl @@ -511,7 +511,7 @@ sub get_noc_verilator_top_modules_info { } my $topology_name=$self->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME'); my $ref=$param{$topology_name}{'ROUTER_Ps'}; - print $ref; + #print $ref; my %router_ps= %{$ref}; my $i=1; #%tops = ("Vnoc" => " --top-module noc_connection"); @@ -812,4 +812,4 @@ sub fattree_mah_distance { } return $distance; } -1 \ No newline at end of file +1 diff --git a/mpsoc/rtl/src_noc/crossbar.sv b/mpsoc/rtl/src_noc/crossbar.sv index 99e3c28..273ccbc 100755 --- a/mpsoc/rtl/src_noc/crossbar.sv +++ b/mpsoc/rtl/src_noc/crossbar.sv @@ -51,7 +51,7 @@ module crossbar #( wire [P_1-1 : 0] mux_sel_pre [P-1 : 0]; wire [P_1-1 : 0] mux_sel [P-1 : 0]; logic [P_1w-1 : 0] mux_sel_bin [P-1 : 0]; - wire [P-1 : 0] flit_out_wr_gen [P-1 : 0]; + logic [P-1 : 0] flit_out_wr_gen [P-1 : 0]; //one_hot_to_bin always_comb begin @@ -63,6 +63,19 @@ module crossbar #( end end + //add_sw_loc_one_hot + always_comb begin + for(int m=0;m< P;m++) begin + if (SELF_LOOP_EN == 0) begin + for(int k=0;km) flit_out_wr_gen[m][k] = granted_dest_port_all[m][k-1]; + else if (k==m) flit_out_wr_gen[m][k] = 1'b0; + else flit_out_wr_gen[m][k] = granted_dest_port_all[m][k]; + end//for + end else flit_out_wr_gen[m][P_1-1 : 0] = granted_dest_port_all[m]; + end//for + end//always + genvar i,j; generate for(i=0;iSW_LOC) destport_one_hot[k] = dest_port_out[k-1]; + else if (k==SW_LOC) destport_one_hot[k] = 1'b0; + else destport_one_hot[k] = dest_port_out[k]; + end//for + end else destport_one_hot[P_1-1 : 0] = dest_port_out; + end//always endmodule /****************** diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index 4d1543f..2b63b9f 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -589,7 +589,7 @@ module check_ovc #( PVV = PV * V, P_1 = (SELF_LOOP_EN )? P : P-1, PVP_1 = PV * P_1; - + input [PV-1 : 0] ovc_status; input [PVV-1 : 0] assigned_ovc_num_all; input [PV-1 : 0] ovc_is_assigned_all; @@ -598,24 +598,27 @@ module check_ovc #( wire [V-1 : 0] assigned_ovc_num [PV-1 : 0]; wire [P_1-1 : 0] destport_sel [PV-1 : 0]; - wire [P-1 : 0] destport_num [PV-1 : 0]; + logic [P-1 : 0] destport_num [PV-1 : 0]; wire [PV-1 : 0] ovc_num [PV-1 : 0]; + + //add_sw_loc_one_hot + always_comb begin + for(int m=0; m < PV; m++) begin + if (SELF_LOOP_EN == 0) begin + for(int k=0; ki/V) destport_num[m][k] = destport_sel[m][k-1]; + else if (k==i/V) destport_num[m][k] = 1'b0; + else destport_num[m][k] = destport_sel[m][k]; + end//for + end else destport_num[m][P_1-1 : 0] = destport_sel[m]; + end + end//always + genvar i,j; generate for(i=0; i Date: Wed, 6 Aug 2025 15:06:15 +0200 Subject: [PATCH 088/107] fix bug --- mpsoc/rtl/src_noc/output_ports.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index 2b63b9f..650844d 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -606,8 +606,8 @@ module check_ovc #( for(int m=0; m < PV; m++) begin if (SELF_LOOP_EN == 0) begin for(int k=0; ki/V) destport_num[m][k] = destport_sel[m][k-1]; - else if (k==i/V) destport_num[m][k] = 1'b0; + if (k>m/V) destport_num[m][k] = destport_sel[m][k-1]; + else if (k==m/V) destport_num[m][k] = 1'b0; else destport_num[m][k] = destport_sel[m][k]; end//for end else destport_num[m][P_1-1 : 0] = destport_sel[m]; From 68574863ee602f207decce0ecbdce0097826236f Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 6 Aug 2025 15:43:03 +0200 Subject: [PATCH 089/107] fix UNDRIVEN linting warning --- mpsoc/Integration_test/Questa_lint/run.sh | 3 +-- mpsoc/rtl/src_noc/flit_buffer.sv | 22 ++++++++++++---------- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 11 +++++------ mpsoc/rtl/src_noc/output_ports.sv | 1 - mpsoc/rtl/src_noc/router_top.sv | 4 +++- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/mpsoc/Integration_test/Questa_lint/run.sh b/mpsoc/Integration_test/Questa_lint/run.sh index d22899c..e482435 100644 --- a/mpsoc/Integration_test/Questa_lint/run.sh +++ b/mpsoc/Integration_test/Questa_lint/run.sh @@ -57,8 +57,7 @@ run_config () { log_file="${log_dir}/${conf}.log" echo "▶️ Compiling configuration: $conf" # Run and redirect stdout/stderr to log file only - questa_lint "$conf" - if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + if ! questa_lint "$conf"; then echo "❌ Compilation failed for $conf (check $log_file)" rm -f "${SCRPT_DIR_PATH}/src/noc_localparam.v" exit 1 diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index 124c62e..92f3246 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -111,6 +111,8 @@ module flit_buffer assign rd = (rd_en)? vc_num_rd & ~multiple_dest : ssa_rd & ~multiple_dest; end else begin : unicast assign rd = (rd_en)? vc_num_rd : ssa_rd; + assign sub_rd = '0; + assign sub_restore = '0; end if (IS_MULTI_FLIT) begin :multi @@ -150,17 +152,17 @@ module flit_buffer end //always_comb for(i=0;i 0); end else begin : unicast assign vc_not_empty [i] = (depth[i] > 0); diff --git a/mpsoc/rtl/src_noc/mesh_torus_routting.sv b/mpsoc/rtl/src_noc/mesh_torus_routting.sv index a36f7e2..cae208e 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_routting.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_routting.sv @@ -407,12 +407,11 @@ module add_sw_loc_one_hot #( input [P_1-1 : 0] destport_in; output reg [P-1 : 0] destport_out; - integer i; - always @(*)begin - for(i=0;iSW_LOC) destport_out[i] = destport_in[i-1]; - else if (i==SW_LOC) destport_out[i] = 1'b0; - else destport_out[i] = destport_in[i]; + always_comb begin + for(int i=0;iSW_LOC) destport_out[i] = destport_in[i-1]; + else if (i==SW_LOC) destport_out[i] = 1'b0; + else destport_out[i] = destport_in[i]; end//for end endmodule diff --git a/mpsoc/rtl/src_noc/output_ports.sv b/mpsoc/rtl/src_noc/output_ports.sv index 650844d..f1908f6 100755 --- a/mpsoc/rtl/src_noc/output_ports.sv +++ b/mpsoc/rtl/src_noc/output_ports.sv @@ -595,7 +595,6 @@ module check_ovc #( input [PV-1 : 0] ovc_is_assigned_all; input [PVP_1-1 : 0] dest_port_all; input clk,reset; - wire [V-1 : 0] assigned_ovc_num [PV-1 : 0]; wire [P_1-1 : 0] destport_sel [PV-1 : 0]; logic [P-1 : 0] destport_num [PV-1 : 0]; diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 4b32358..548e891 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -219,10 +219,12 @@ module router_top #( end else begin for(i=0;i Date: Wed, 6 Aug 2025 16:39:36 +0200 Subject: [PATCH 090/107] fix bug in Quartus compilation --- .../golden_ref/{report.csv => report.txt} | 0 mpsoc/Integration_test/Altera/run.sh | 10 ++- mpsoc/rtl/main_comp.v | 10 +-- mpsoc/rtl/src_noc/comb-spec1.sv | 8 +- mpsoc/rtl/src_noc/comb_nonspec.sv | 76 +++++++++---------- mpsoc/rtl/src_noc/comb_spec2.sv | 2 +- mpsoc/rtl/src_noc/output_ports.sv | 4 +- 7 files changed, 53 insertions(+), 57 deletions(-) rename mpsoc/Integration_test/Altera/golden_ref/{report.csv => report.txt} (100%) diff --git a/mpsoc/Integration_test/Altera/golden_ref/report.csv b/mpsoc/Integration_test/Altera/golden_ref/report.txt similarity index 100% rename from mpsoc/Integration_test/Altera/golden_ref/report.csv rename to mpsoc/Integration_test/Altera/golden_ref/report.txt diff --git a/mpsoc/Integration_test/Altera/run.sh b/mpsoc/Integration_test/Altera/run.sh index 2c04070..e8b2a83 100755 --- a/mpsoc/Integration_test/Altera/run.sh +++ b/mpsoc/Integration_test/Altera/run.sh @@ -12,7 +12,7 @@ log_work="${PRONOC_WORK}/verify/logs" mkdir -p $log_work mkdir -p $log_dir - +report="report.txt" quartus_get_result () { @@ -121,7 +121,7 @@ compile () { } report_all_configurations () { - output_file="$log_dir/report.csv" + output_file="$log_dir/$report" > "$output_file" # Empty the file at start # Initialize a set to track unique metric names declare -A all_keys @@ -182,5 +182,7 @@ done report_all_configurations -perl ${SCRPT_DIR_PATH}/src/compare.pl "$golden_dir/report.csv" "$log_dir/report.csv" -echo "All configurations processed. Results are in $log_dir/report.csv" +perl ${SCRPT_DIR_PATH}/src/compare.pl "$golden_dir/$report" "$log_dir/$report" +echo "All configurations processed. Results are in $log_dir/$report" + + diff --git a/mpsoc/rtl/main_comp.v b/mpsoc/rtl/main_comp.v index 26df719..fde6876 100755 --- a/mpsoc/rtl/main_comp.v +++ b/mpsoc/rtl/main_comp.v @@ -90,7 +90,7 @@ module one_hot_demux #( output [OUT_WIDTH-1 : 0] demux_out ); genvar i; - generate for (i = 0; i < SEL_WIDTH; i=i+1) begin + generate for (i = 0; i < SEL_WIDTH; i=i+1) begin : D_ assign demux_out[i*IN_WIDTH +: IN_WIDTH] = (demux_sel[i]==1'b1) ? demux_in : {IN_WIDTH{1'b0}}; end endgenerate endmodule @@ -111,10 +111,10 @@ module outport_sum #( ); genvar i,j; - wire [IN_WIDTH-1 : 0] in_sep [IN_NUM-1 : 0]; - wire [IN_NUM-2 : 0] gen [OUT_WIDTH-1 : 0]; + wire [IN_WIDTH-1 : 0] in_sep [IN_NUM-1 : 0]; + wire [IN_NUM-2 : 0] gen [OUT_WIDTH-1 : 0]; generate - for(i=0;ij) begin diff --git a/mpsoc/rtl/src_noc/comb_nonspec.sv b/mpsoc/rtl/src_noc/comb_nonspec.sv index 9b53b98..57b857f 100755 --- a/mpsoc/rtl/src_noc/comb_nonspec.sv +++ b/mpsoc/rtl/src_noc/comb_nonspec.sv @@ -161,8 +161,8 @@ module comb_nonspec_allocator # ( end//for wire [P-1 : 0] ovc_assigned_local; - for(i=0;i< P;i=i+1) begin :P_ - for(j=0;j< V;j=j+1) begin :V_ + for(i=0;i< P;i=i+1) begin : P_ + for(j=0;j< V;j=j+1) begin : V_ //merge masked_candidate_ovc in each port assign ivc_request_all[i*V+j] = ivc_info[i][j].ivc_req; assign ovc_is_assigned_all[i*V+j] = ivc_info[i][j].ovc_is_assigned; @@ -175,7 +175,7 @@ module comb_nonspec_allocator # ( //one hot mux to select granted OVC assign ovc_assigned_local[i] = |(ovc_is_assigned_all[(i+1)*V-1 : i*V] & first_arbiter_granted_ivc_per_port [i]); //Onehot demultiplexer - for (j = 0; j < P_1; j++) begin + for (j = 0; j < P_1; j++) begin : P_ assign cand_ovc_granted [i][j*V +: V] = (granted_dest_port_per_port [i][j]==1'b1) ? candidate_ovc_local_num[i] : {V{1'b0}}; end assign granted_ovc_local_num_per_port[i] = (any_ivc_sw_request_granted_all[i] )? candidate_ovc_local_num[i] : {V{1'b0}}; @@ -184,7 +184,7 @@ module comb_nonspec_allocator # ( end//i for(i=0;i< PV;i=i+1) begin :_PV - for(j=0;jj) begin: hh + end else if((i/V)>j) begin assign ovc_allocated_all_gen[i][j] = cand_ovc_granted[j][i-V]; end end//j @@ -371,7 +371,7 @@ module comb_nonspec_v2_allocator #( end//i endgenerate -endmodule +endmodule /******************************************** * nonspeculative switch allocator @@ -498,7 +498,7 @@ module nonspec_sw_alloc #( assign single_flit_granted_dst[i] = {P_1{1'b0}}; end //second arbiter input/output generate - for(j=0;j Date: Wed, 13 Aug 2025 15:38:35 +0200 Subject: [PATCH 091/107] improve phy_noc generator --- mpsoc/script/phy_noc_gen/phy_noc.pl | 60 +++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/mpsoc/script/phy_noc_gen/phy_noc.pl b/mpsoc/script/phy_noc_gen/phy_noc.pl index 7917c69..32c1a3a 100644 --- a/mpsoc/script/phy_noc_gen/phy_noc.pl +++ b/mpsoc/script/phy_noc_gen/phy_noc.pl @@ -42,12 +42,14 @@ } -my %replace; -$replace{"import pronoc_pkg::*;"} = "import pronoc_pkg_${noc_id}::*;"; -$replace{"noc_localparam.v"} = "noc_localparam_${noc_id}.v"; -$replace{"topology_localparam.v"} = "topology_localparam_${noc_id}.v"; -$replace{"pronoc_pkg"} = "pronoc_pkg_${noc_id}"; -$replace{"NOC_ID=0"} = "NOC_ID=\"$ARGV[0]\""; +#Note that white spaces in replace keys are autumatically translated to \s* +my %replace = ( + 'import pronoc_pkg::*;' => "import pronoc_pkg_${noc_id}::*;", + 'noc_localparam.v' => "noc_localparam_${noc_id}.v", + 'topology_localparam.v' => "topology_localparam_${noc_id}.v", + 'pronoc_pkg' => "pronoc_pkg_${noc_id}", + 'NOC_ID = 0' => "NOC_ID=\"$ARGV[0]\"", +); @@ -104,8 +106,16 @@ foreach my $param (@params) { # Extract the parameter name while skipping 'int', 'signed', 'unsigned' if ($param =~ /^\s*(?:int|signed|unsigned)?\s*(\w+)/) { - push @param_list ,$1; - } + my $param_name = $1; + $param_name =~ s/^\s+|\s+$//g; # Trim spaces + $param_name =~ s/[,;)\]\s]+$//g; # Strip trailing punctuation/whitespace + # Check if valid identifier (standard or escaped) + if ($param_name =~ /^(?:[a-zA-Z_]\w*$|\\\S+)$/) { + push @param_list, $param_name; + } else { + #print "Ignore: \"$param_name\"\n"; + } + } } } } @@ -166,8 +176,19 @@ my %key_replacements = map { $_ => "${_}_${noc_id}" } @replaces; my $key_regex = join '|', map { quotemeta } @replaces; -# Compile replace hash regex -my $replace_regex = join '|', map { quotemeta } keys %replace; +# Compile replace hash regex (spaces become \s*) +my $replace_regex = join '|', + map { + my $pattern = $_; + + # Escape all regex metacharacters except space + $pattern =~ s/([^\w\s])/\\$1/g; + + # Convert literal spaces to \s* + $pattern =~ s/ /\\s*/g; + + $pattern; + } sort keys %replace; foreach my $file (@files) { @@ -189,7 +210,8 @@ $line =~ s/\b($module_regex)\b/$module_replacements{$1}/g; # Replace keys in %replace hash - $line =~ s/($replace_regex)/$replace{$1}/g; + $line =~ s/($replace_regex)/$replace{space_match($1)}/g; + #print "$line =~ s/($replace_regex)/\$replace{$1}/g;\n"; # Replace file names $line =~ s/($file_regex)/$file_replacements{$1}/g; @@ -202,6 +224,22 @@ print $output_fh $line; } +sub space_match { + my $in = shift; + + # 1. Exact match + return $in if exists $replace{$in}; + # 2. Pattern match (spaces → \s*) + foreach my $key (sort keys %replace) { + my $new_key = $key; + $new_key =~ s/ /\\s*/g; # replace space with \s* + if ($in =~ /^$new_key$/) { + return $key; + } + } + # 3. Default return + return $in; +} # Close the input and output files close($input_fh); From 868f7839a67c46458a2663c18015bd2170b6f44c Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 1 Oct 2025 17:16:38 +0200 Subject: [PATCH 092/107] use internal lib in phy_noc.pl --- mpsoc/script/phy_noc_gen/phy_noc.pl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mpsoc/script/phy_noc_gen/phy_noc.pl b/mpsoc/script/phy_noc_gen/phy_noc.pl index 32c1a3a..90a0a62 100644 --- a/mpsoc/script/phy_noc_gen/phy_noc.pl +++ b/mpsoc/script/phy_noc_gen/phy_noc.pl @@ -8,6 +8,9 @@ #add home dir in perl 5.6 use FindBin; use lib $FindBin::Bin; + +use lib "$FindBin::Bin/../../Integration_test/synthetic_sim/src/perl_lib"; + use constant::boolean; @@ -18,9 +21,9 @@ use File::Basename; use File::Copy; +use Cwd 'realpath'; my $dirname = dirname(__FILE__); -my $noc_dir = "$dirname/../../rtl/src_noc"; - +my $noc_dir = realpath("$dirname/../../rtl/src_noc"); my $noc_id = $ARGV[0]; my $out_dir= $ARGV[1]; @@ -224,6 +227,8 @@ print $output_fh $line; } + + sub space_match { my $in = shift; From fbeb5c4fa17867c9bb2ad2d33c7e9105ff7918e0 Mon Sep 17 00:00:00 2001 From: amonemi Date: Wed, 15 Oct 2025 11:37:35 +0200 Subject: [PATCH 093/107] Merge branch ft/select-routing-mode --- .github/workflows/main.yml | 6 +- mpsoc/Integration_test/FPGA-kc07/src/src.pl | 2 +- .../configurations/mesh_8x8_2cycle_adaptive | 2 +- .../VCS/Golden_ref/line4_smart3.log | 8 +- .../VCS/Golden_ref/mesh_3x3_v2_ssa.log | 8 +- .../Golden_ref/mesh_4x4_2cycle_mcast_f.log | 8 +- .../VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log | 8 +- .../Golden_ref/line4_smart3_vc_static.txt | 4 +- .../{deafult_noc_param => default_noc_param} | 2 + .../conv_route/Fattree_k3_L3_st | 10 + .../conv_route/bintree_k3_L3_st | 10 + .../conv_route/custom1_topology | 11 + .../conv_route/fmesh_2x2_openpiton | 15 + .../configurations/conv_route/mesh_3x3_v2_ssa | 13 + .../conv_route/mesh_4x4_2cycle_mcast_f | 9 + .../conv_route/mesh_4x4_selflp_mcast_f | 10 + .../configurations/conv_route/mesh_4x4_smart3 | 16 + .../conv_route/mesh_4x4x2_bcast_f | 11 + .../conv_route/mesh_8x8_2cycle_adaptive | 7 + .../conv_route/mesh_8x8_sbp6_xy | 6 + .../conv_route/mesh_8x8_single_flit | 9 + .../conv_route/ring_8x8_2cycle_xy | 9 + .../configurations/conv_route/star_6 | 9 + .../conv_route/torus_8x8_2cycle_xy | 7 + .../general/mesh_8x8_2cycle_adaptive | 2 +- .../tiny_topos/torus_3x2_adaptive | 2 +- .../synthetic_sim/golden_ref/conv_route | 91 ++++ .../synthetic_sim/golden_ref/general | 8 +- .../Integration_test/synthetic_sim/src/src.pl | 5 +- .../configurations/mesh_8x8_2cycle_adaptive | 2 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 26 +- .../perl_gui/lib/perl/topology_verilog_gen.pl | 509 ++++++++++-------- mpsoc/rtl/src_noc/fmesh.sv | 4 +- mpsoc/rtl/src_noc/header_flit.sv | 13 +- mpsoc/rtl/src_noc/input_ports.sv | 49 +- mpsoc/rtl/src_noc/mesh_torus.sv | 23 +- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 8 +- mpsoc/rtl/src_noc/noc_localparam.v | 76 +-- mpsoc/rtl/src_noc/packet_injector.sv | 4 +- mpsoc/rtl/src_noc/router_two_stage.sv | 21 +- mpsoc/rtl/src_noc/routing.sv | 86 ++- mpsoc/rtl/src_noc/topology_localparam.v | 5 +- mpsoc/rtl/src_noc/traffic_gen_top.sv | 4 +- mpsoc/rtl/src_openpiton/wrapper.sv | 28 +- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 28 +- .../src_topology/common/custom_conv_routing.v | 43 ++ .../custom1/Tcustom1Rcustom_conv_routing.v | 420 +++++++++++++++ .../Tcustom1Rcustom_look_ahead_routing.v | 36 +- ...custom1Rcustom_look_ahead_routing_genvar.v | 80 +-- ...routing.v => Tcustom1Rcustom_ni_routing.v} | 12 +- ....v => Tcustom1Rcustom_ni_routing_genvar.v} | 42 +- mpsoc/rtl/src_topology/custom1/custom1.png | Bin 83516 -> 137543 bytes mpsoc/rtl/src_topology/custom_flist.f | 16 +- mpsoc/rtl/src_topology/param.obj | 44 +- mpsoc/script/parameter.sh | 6 +- mpsoc/script/verilator_2D_mesh.sh | 14 +- mpsoc/smart-netrace/src/src.pl | 2 +- mpsoc/src_c/plot/parameter.v | 2 +- mpsoc/src_verilator/simulator.cpp | 2 +- mpsoc/src_verilator/traffic_task_graph.h | 308 +++++------ 60 files changed, 1531 insertions(+), 690 deletions(-) rename mpsoc/Integration_test/{deafult_noc_param => default_noc_param} (97%) create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/Fattree_k3_L3_st create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/bintree_k3_L3_st create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/custom1_topology create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/fmesh_2x2_openpiton create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_3x3_v2_ssa create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_2cycle_mcast_f create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_selflp_mcast_f create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_smart3 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4x2_bcast_f create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_2cycle_adaptive create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_sbp6_xy create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_single_flit create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/star_6 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy create mode 100644 mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route create mode 100644 mpsoc/rtl/src_topology/common/custom_conv_routing.v create mode 100644 mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conv_routing.v rename mpsoc/rtl/src_topology/custom1/{Tcustom1Rcustom_conventional_routing.v => Tcustom1Rcustom_ni_routing.v} (96%) rename mpsoc/rtl/src_topology/custom1/{Tcustom1Rcustom_conventional_routing_genvar.v => Tcustom1Rcustom_ni_routing_genvar.v} (92%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a4da3bc..1f35a7e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,13 +5,13 @@ on: branches: [ "**" ] jobs: - synthetic-sim-split-mode: + sim-split-mode: runs-on: ubuntu-latest container: image: verilator/verilator:4.104 strategy: matrix: - conf_name: [general, line-ring, multicast, vc_alloc, tiny_topos] + conf_name: [general, line-ring, multicast, vc_alloc, conv_route, tiny_topos] env: ROOT: ${{ github.workspace }}/mpsoc PRONOC_WORK: ${{ github.workspace }}/mpsoc_work @@ -45,7 +45,7 @@ jobs: retention-days: 7 tiny-topos-flat-mode: - needs: synthetic-sim-split-mode + needs: sim-split-mode runs-on: ubuntu-latest container: image: verilator/verilator:4.104 diff --git a/mpsoc/Integration_test/FPGA-kc07/src/src.pl b/mpsoc/Integration_test/FPGA-kc07/src/src.pl index 2e8ac8f..9ba2f89 100755 --- a/mpsoc/Integration_test/FPGA-kc07/src/src.pl +++ b/mpsoc/Integration_test/FPGA-kc07/src/src.pl @@ -18,7 +18,7 @@ use warnings; my $pp; -$pp= do "$src/deafult_noc_param"; +$pp= do "$src/default_noc_param"; die "Error reading: $@" if $@; my $param = $pp->{'noc_param'}; diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive index 20550e3..0aaa94e 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_adaptive @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"DUATO\"", + "ROUTE_NAME" => "\"FULL_ADPT\"", "ESCAP_VC_MASK" => "2'b01" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log b/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log index d85091a..d8603c4 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log @@ -203,18 +203,18 @@ pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "DUATO")" +pronoc_pkg, "(ROUTE_NAME == "FULL_ADPT")" A left 16-bit expression is compared to a right 40-bit expression. Comparing 'ROUTE_NAME' of type string - with '"DUATO"' of type string. + with '"FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_FULL_ADPT")" A left 16-bit expression is compared to a right 88-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_DUATO"' of type string. + with '"TRANC_FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log index 026af74..45a5716 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log @@ -203,18 +203,18 @@ pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "DUATO")" +pronoc_pkg, "(ROUTE_NAME == "FULL_ADPT")" A left 16-bit expression is compared to a right 40-bit expression. Comparing 'ROUTE_NAME' of type string - with '"DUATO"' of type string. + with '"FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_FULL_ADPT")" A left 16-bit expression is compared to a right 88-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_DUATO"' of type string. + with '"TRANC_FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log index 50f404b..e9554f1 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log @@ -203,18 +203,18 @@ pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "DUATO")" +pronoc_pkg, "(ROUTE_NAME == "FULL_ADPT")" A left 16-bit expression is compared to a right 40-bit expression. Comparing 'ROUTE_NAME' of type string - with '"DUATO"' of type string. + with '"FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_FULL_ADPT")" A left 16-bit expression is compared to a right 88-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_DUATO"' of type string. + with '"TRANC_FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log index b608185..3a062f2 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log @@ -203,18 +203,18 @@ pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "DUATO")" +pronoc_pkg, "(ROUTE_NAME == "FULL_ADPT")" A left 16-bit expression is compared to a right 40-bit expression. Comparing 'ROUTE_NAME' of type string - with '"DUATO"' of type string. + with '"FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_DUATO")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_FULL_ADPT")" A left 16-bit expression is compared to a right 88-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_DUATO"' of type string. + with '"TRANC_FULL_ADPT"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt index cc2f40e..af4ca57 100644 --- a/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt +++ b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt @@ -2101,9 +2101,9 @@ Module : FileName : ./../../rtl/src_noc/./topology_localparam.v LineNumber : 145 - Statement : (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", + Statement : (ROUTE_NAME == "FULL_ADPT" || ROUTE_NAME == "TRANC_FULL_ADPT" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", RTL_EXPRESSION : (Operators == and || used) - Node_Value : (Expr: ((ROUTE_NAME == "DUATO") || (ROUTE_NAME == "TRANC_DUATO"))) + Node_Value : (Expr: ((ROUTE_NAME == "FULL_ADPT") || (ROUTE_NAME == "TRANC_FULL_ADPT"))) ----------------------------------------------------------------------------- Tag : ExprParen Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] diff --git a/mpsoc/Integration_test/deafult_noc_param b/mpsoc/Integration_test/default_noc_param similarity index 97% rename from mpsoc/Integration_test/deafult_noc_param rename to mpsoc/Integration_test/default_noc_param index bf7dd61..0ec3ed9 100644 --- a/mpsoc/Integration_test/deafult_noc_param +++ b/mpsoc/Integration_test/default_noc_param @@ -10,6 +10,7 @@ $model = bless({ "LB" => "B", "Fpay" => "32", "ROUTE_NAME" => "\"XY\"", + "ROUTE_MODE" => "\"LOOKAHEAD\"", "PCK_TYPE" => " \"MULTI_FLIT\"", "MIN_PCK_SIZE" => "2", "BYTE_EN" => "0", @@ -55,6 +56,7 @@ $model = bless({ 'LB', 'Fpay', 'ROUTE_NAME', + 'ROUTE_MODE', 'PCK_TYPE', 'MIN_PCK_SIZE', 'BYTE_EN', diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/Fattree_k3_L3_st b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/Fattree_k3_L3_st new file mode 100644 index 0000000..069ecc8 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/Fattree_k3_L3_st @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"FATTREE\"", + "T1" => "3", + "T2" => "3", + "B" => "5", + "ROUTE_NAME" => "\"NCA_STRAIGHT_UP\"", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/bintree_k3_L3_st b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/bintree_k3_L3_st new file mode 100644 index 0000000..9b5a564 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/bintree_k3_L3_st @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TREE\"", + "T1" => "3", + "T2" => "3", + "B" => "5", + "ROUTE_NAME" => "\"NCA\"", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/custom1_topology b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/custom1_topology new file mode 100644 index 0000000..b2d125b --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/custom1_topology @@ -0,0 +1,11 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=>"\"custom1\"", + "CUSTOM_TOPOLOGY_NAME"=>"\"custom1\"", + "T1" => "16", + "T2" => "16", + "T3" => "5", + "ROUTE_NAME" =>"\"custom\"", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/fmesh_2x2_openpiton b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/fmesh_2x2_openpiton new file mode 100644 index 0000000..adab76f --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/fmesh_2x2_openpiton @@ -0,0 +1,15 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "2", + "T2" => "2", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "1", + "SELF_LOOP_EN" => "1", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_3x3_v2_ssa b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_3x3_v2_ssa new file mode 100644 index 0000000..94d2a4f --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_3x3_v2_ssa @@ -0,0 +1,13 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "3", + "T2" => "3", + "SELF_LOOP_EN" => "1", + "SSA_EN"=> "1", + "LB" => 16, + "DEBUG_EN" => "0", + "MIN_PCK_SIZE" => "1", + "Fpay" => "64", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_2cycle_mcast_f b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_2cycle_mcast_f new file mode 100644 index 0000000..d1d279d --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_2cycle_mcast_f @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_selflp_mcast_f b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_selflp_mcast_f new file mode 100644 index 0000000..a2367b7 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_selflp_mcast_f @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "CAST_TYPE" => "\"MULTICAST_FULL\"", + "Fpay" => "64", + "SELF_LOOP_EN" => "1", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_smart3 new file mode 100644 index 0000000..352b170 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_smart3 @@ -0,0 +1,16 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "3", + "TOPOLOGY"=> "\"FMESH\"", + "T1" => "4", + "T2" => "4", + "V" => "1", + "ESCAP_VC_MASK" => "1'b1", + "B" => "4", + "LB" => "16", + "Fpay" => "64", + "SSA_EN" => "0", + "SELF_LOOP_EN" => "1", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4x2_bcast_f b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4x2_bcast_f new file mode 100644 index 0000000..23eb21a --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4x2_bcast_f @@ -0,0 +1,11 @@ +$model = bless( { + 'noc_param'=> { + "T1" => "4", + "T2" => "4", + "T3" => "2", + "CAST_TYPE" => "\"BROADCAST_FULL\"", + "MCAST_ENDP_LIST" => "32'b1100110001111", + "Fpay" => "64", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_2cycle_adaptive b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_2cycle_adaptive new file mode 100644 index 0000000..ad4952e --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_2cycle_adaptive @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "ROUTE_NAME" => "\"FULL_ADPT\"", + "ESCAP_VC_MASK" => "2'b01", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_sbp6_xy b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_sbp6_xy new file mode 100644 index 0000000..1c97e29 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_sbp6_xy @@ -0,0 +1,6 @@ +$model = bless( { + 'noc_param'=> { + "SMART_MAX" => "6", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_single_flit b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_single_flit new file mode 100644 index 0000000..f0579e4 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_8x8_single_flit @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "B" => "5", + "LB" => "5", + "MIN_PCK_SIZE" => "1", + "PCK_TYPE" => " \"SINGLE_FLIT\"", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy new file mode 100644 index 0000000..35e24e5 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy @@ -0,0 +1,9 @@ +$model = bless( { + 'compile' => "verilate_mesh.sh", + 'noc_param'=> { + TOPOLOGY=>"\"RING\"", + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/star_6 b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/star_6 new file mode 100644 index 0000000..ab0bc8a --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/star_6 @@ -0,0 +1,9 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"STAR\"", + "T1" => "6", + "T2" => "1", + "B" => "5", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy new file mode 100644 index 0000000..58317ed --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy @@ -0,0 +1,7 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => "\"TORUS\"", + "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_MODE" => "\"CONVENTIONAL\"", + } +}, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_adaptive b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_adaptive index 20550e3..0aaa94e 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_adaptive +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_adaptive @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"DUATO\"", + "ROUTE_NAME" => "\"FULL_ADPT\"", "ESCAP_VC_MASK" => "2'b01" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive index 2df56e6..5c9c6ec 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/torus_3x2_adaptive @@ -1,7 +1,7 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_DUATO\"", + "ROUTE_NAME" => "\"TRANC_FULL_ADPT\"", "T1" => "3", "T2" => "2", } diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route b/mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route new file mode 100644 index 0000000..013fab1 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route @@ -0,0 +1,91 @@ +Verification Results: +****************************bintree_k3_L3_st : Compile *******************************: + model is generated successfully. +****************************custom1_topology : Compile *******************************: + model is generated successfully. +****************************Fattree_k3_L3_st : Compile *******************************: + model is generated successfully. +****************************fmesh_2x2_openpiton : Compile *******************************: + model is generated successfully. +****************************mesh_3x3_v2_ssa : Compile *******************************: + model is generated successfully. +****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: + model is generated successfully. +****************************mesh_4x4_selflp_mcast_f : Compile *******************************: + model is generated successfully. +****************************mesh_4x4_smart3 : Compile *******************************: + model is generated successfully. +****************************mesh_4x4x2_bcast_f : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_2cycle_adaptive : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_sbp6_xy : Compile *******************************: + model is generated successfully. +****************************mesh_8x8_single_flit : Compile *******************************: + model is generated successfully. +****************************ring_8x8_2cycle_xy : Compile *******************************: + model is generated successfully. +****************************star_6 : Compile *******************************: + model is generated successfully. +****************************torus_8x8_2cycle_xy : Compile *******************************: + model is generated successfully. +****************************bintree_k3_L3_st : random traffic *******************************: + Passed: zero load (2,14.5705) saturation (14,400.884) +****************************custom1_topology : random traffic *******************************: + Passed: zero load (2,13.0626) saturation (42,65.4283) +****************************Fattree_k3_L3_st : random traffic *******************************: + Passed: zero load (2,13.5991) saturation (62,98.8008) +****************************fmesh_2x2_openpiton : random traffic *******************************: + Passed: zero load (2,8.27536) saturation (54,67.4686) +****************************mesh_3x3_v2_ssa : random traffic *******************************: + Passed: zero load (2,9.86859) saturation (70,77.4433) +****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: + Passed: zero load (2,14.4623) saturation (22,261.684) +****************************mesh_4x4_selflp_mcast_f : random traffic *******************************: + Passed: zero load (2,14.366) saturation (22,257.065) +****************************mesh_4x4_smart3 : random traffic *******************************: + Passed: zero load (2,10.1271) saturation (42,72.4117) +****************************mesh_4x4x2_bcast_f : random traffic *******************************: + Passed: zero load (2,20.5192) saturation (6,1071.58) +****************************mesh_8x8_2cycle_adaptive : random traffic *******************************: + Passed: zero load (2,18.2154) saturation (34,186.128) +****************************mesh_8x8_sbp6_xy : random traffic *******************************: + Passed: zero load (2,11.1597) saturation (34,119.674) +****************************mesh_8x8_single_flit : random traffic *******************************: + Passed: zero load (2,12.7369) saturation (58,65.8427) +****************************ring_8x8_2cycle_xy : random traffic *******************************: + Passed: zero load (2,16.8517) saturation (38,120.208) +****************************star_6 : random traffic *******************************: + Passed: zero load (2,7.27692) saturation (62,57.3078) +****************************torus_8x8_2cycle_xy : random traffic *******************************: + Passed: zero load (2,16.8517) saturation (38,120.208) +****************************bintree_k3_L3_st : transposed 1 traffic *******************************: + Passed: zero load (2,14.5436) saturation (14,430.149) +****************************custom1_topology : transposed 1 traffic *******************************: + Passed: zero load (2,12.6827) saturation (34,68.3986) +****************************Fattree_k3_L3_st : transposed 1 traffic *******************************: + Passed: zero load (26,13.4638) saturation (100,-) +****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: + Passed: zero load (2,8.99642) saturation (54,71.4902) +****************************mesh_3x3_v2_ssa : transposed 1 traffic *******************************: + Passed: zero load (6,9.72718) saturation (54,69.363) +****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: + Passed: zero load (2,14.8953) saturation (26,146.747) +****************************mesh_4x4_selflp_mcast_f : transposed 1 traffic *******************************: + Passed: zero load (2,14.6488) saturation (22,166.723) +****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: + Passed: zero load (2,10.5055) saturation (34,60.2796) +****************************mesh_4x4x2_bcast_f : transposed 1 traffic *******************************: + Passed: zero load (2,21.0549) saturation (6,863.495) +****************************mesh_8x8_2cycle_adaptive : transposed 1 traffic *******************************: + Passed: zero load (2,19.3604) saturation (26,108.443) +****************************mesh_8x8_sbp6_xy : transposed 1 traffic *******************************: + Passed: zero load (2,11.3748) saturation (18,119.786) +****************************mesh_8x8_single_flit : transposed 1 traffic *******************************: + Passed: zero load (2,14.0386) saturation (26,70.9042) +****************************ring_8x8_2cycle_xy : transposed 1 traffic *******************************: + Passed: zero load (2,18.0133) saturation (18,134.597) +****************************star_6 : transposed 1 traffic *******************************: + Passed: zero load (2,6.83981) saturation (100,-) +****************************torus_8x8_2cycle_xy : transposed 1 traffic *******************************: + Passed: zero load (2,18.0133) saturation (18,134.597) diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/general b/mpsoc/Integration_test/synthetic_sim/golden_ref/general index a0c25e1..edfbf3e 100644 --- a/mpsoc/Integration_test/synthetic_sim/golden_ref/general +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/general @@ -52,7 +52,7 @@ Verification Results: ****************************Fattree_k3_L3_st : random traffic *******************************: Passed: zero load (2,13.5991) saturation (62,98.8008) ****************************fmesh_1x1_openpiton : random traffic *******************************: - Passed: zero load (2,7.06202) saturation (66,51.0968) + Passed: zero load (2,6.28966) saturation (66,50.4578) ****************************fmesh_2x2_openpiton : random traffic *******************************: Passed: zero load (2,8.27536) saturation (54,67.4686) ****************************fmesh_8x8_2cycle_xy : random traffic *******************************: @@ -62,7 +62,7 @@ Verification Results: ****************************mesh_2x2_openpiton : random traffic *******************************: Passed: zero load (2,9.10156) saturation (66,72.3384) ****************************mesh_3x3_v2_ssa : random traffic *******************************: - Passed: zero load (2,10.2442) saturation (74,99.0811) + Passed: zero load (2,9.86859) saturation (70,77.4433) ****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: Passed: zero load (2,14.4623) saturation (22,261.684) ****************************mesh_4x4_smart3 : random traffic *******************************: @@ -98,7 +98,7 @@ Verification Results: ****************************Fattree_k3_L3_st : transposed 1 traffic *******************************: Passed: zero load (26,13.4638) saturation (100,-) ****************************fmesh_1x1_openpiton : transposed 1 traffic *******************************: - Passed: zero load (46,6.99433) saturation (100,-) + Passed: zero load (58,6.52308) saturation (100,-) ****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: Passed: zero load (2,8.99642) saturation (54,71.4902) ****************************fmesh_8x8_2cycle_xy : transposed 1 traffic *******************************: @@ -108,7 +108,7 @@ Verification Results: ****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: Passed: zero load (2,8.7482) saturation (100,-) ****************************mesh_3x3_v2_ssa : transposed 1 traffic *******************************: - Passed: zero load (10,10.3955) saturation (54,77.1181) + Passed: zero load (6,9.72718) saturation (54,69.363) ****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: Passed: zero load (2,14.8953) saturation (26,146.747) ****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: diff --git a/mpsoc/Integration_test/synthetic_sim/src/src.pl b/mpsoc/Integration_test/synthetic_sim/src/src.pl index 08918d3..ae49515 100755 --- a/mpsoc/Integration_test/synthetic_sim/src/src.pl +++ b/mpsoc/Integration_test/synthetic_sim/src/src.pl @@ -28,7 +28,7 @@ my $src_verilator = "$root/src_verilator"; my $src_c = "$root/src_c"; my $src = "$script_path"; -my $noc_default_param_file= "$root/Integration_test/deafult_noc_param"; +my $noc_default_param_file= "$root/Integration_test/default_noc_param"; #require "$root/perl_gui/lib/perl/common.pl"; require "$root/perl_gui/lib/perl/topology.pl"; @@ -144,7 +144,8 @@ sub get_model_parameter { my $model =shift; my $o; $o= do $model; - my %new_param=%{$o}; + my $pp = $o->{'noc_param'}; + my %new_param=%{$pp}; die "Error reading: $@" if $@; my %temp; foreach my $p (@params){ diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive index 20550e3..0aaa94e 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_adaptive @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"DUATO\"", + "ROUTE_NAME" => "\"FULL_ADPT\"", "ESCAP_VC_MASK" => "2'b01" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index c784c5a..cb4217c 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -732,8 +732,8 @@ sub noc_config{ $param="ROUTE_NAME"; $type="Combo-box"; if($router_type eq '"VC_BASED"'){ - $content=($topology eq '"MESH"' || $topology eq '"FMESH"')? '"XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN","DUATO"' : - ($topology eq '"TORUS"')? '"TRANC_XY","TRANC_WEST_FIRST","TRANC_NORTH_LAST","TRANC_NEGETIVE_FIRST","TRANC_DUATO"': + $content=($topology eq '"MESH"' || $topology eq '"FMESH"')? '"XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN","FULL_ADPT"' : + ($topology eq '"TORUS"')? '"TRANC_XY","TRANC_WEST_FIRST","TRANC_NORTH_LAST","TRANC_NEGETIVE_FIRST","TRANC_FULL_ADPT"': ($topology eq '"RING"')? '"TRANC_XY"' : ($topology eq '"LINE"')? '"XY"': ($topology eq '"FATTREE"')? '"NCA_RND_UP","NCA_STRAIGHT_UP","NCA_DST_UP"': @@ -751,7 +751,10 @@ sub noc_config{ ($topology eq '"FATTREE"')? '"NCA_STRAIGHT_UP"' : ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; - my $info_mesh="Select the routing algorithm: XY(DoR) , partially adaptive (Turn models). Fully adaptive (Duato) "; + my $info_mesh="Select the routing algorithm. Options are: + - XY: Deterministic routing (Dimension-Order Routing, DoR). + - WEST_FIRST, NORTH_LAST, NEGATIVE_FIRST, ODD_EVEN: Partially adaptive routing algorithms based on turn model restrictions. + - FULL_ADPT: Fully adaptive routing based on Duato's algorithm; requires at least two virtual channels (VCs) per port."; my $info_fat="Nearest common ancestor (NCA) where the up port is selected randomly (RND), based on destination endpoint address (DST) or it is the top port that is located in front of the port which has received the packet (STRAIGHT) "; @@ -762,6 +765,21 @@ sub noc_config{ options are $content"; my $show_routing =($topology eq '"STAR"' )? 0 : $show_noc; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_routing,$noc_param,1); + #routing_mode + $label='Routing Mode'; + $param="ROUTE_MODE"; + $type="Combo-box"; + $content='"LOOKAHEAD","CONVENTIONAL"'; + $default='"LOOKAHEAD"'; + $info = "Select the routing algorithm mode: + -CONVENTIONAL: + The destination output port is computed + in the same cycle, prior to VC/SW allocation. + -LOOKAHEAD: + The routing decision is performed one router + ahead, in parallel with VC/SW allocation."; + $noc_param_comment{$param}="$info"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,1,$noc_param,1); } #PCK_TYPE @@ -924,7 +942,7 @@ sub noc_config{ $default= "${default}1"; $info="Select the escap VC for fully adaptive routing."; $noc_param_comment{$param}="$info"; - if( $route eq '"TRANC_DUATO"' or $route eq '"DUATO"' ){ + if( $route eq '"TRANC_FULL_ADPT"' or $route eq '"FULL_ADPT"' ){ ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set, $noc_param,undef); } else{ diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index a141067..abd52b7 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -540,21 +540,97 @@ sub get_wires_assignment_genvar_v{ return ($assign,$r2r_h,$r2e_h,$init_h,$gnd_h,$R_num); } - - sub generate_routing_v { my ($self,$info,$dir)=@_; my @ends=get_list_of_all_endpoints($self); my @routers=get_list_of_all_routers($self); - ######################### - # conventional_routing - ######################### #create routing file my $name=$self->object_get_attribute('save_as'); my $rname=$self->object_get_attribute('routing_name'); my $Vname="T${name}R${rname}"; + gen_ni_routing_file($self,$info,$dir,$Vname); + gen_ni_genvar_route($self,$info,$dir,$Vname); + gen_lkhead_genvar_routing_file ($self,$info,$dir,$Vname,'look_ahead'); + gen_lkhead_conv_routing_file($self,$info,$dir,$Vname,'look_ahead'); + gen_lkhead_conv_routing_file($self,$info,$dir,$Vname,'conv'); +} + +########## +# ni_genvar_route +######### +sub gen_ni_genvar_route{ + my ($self,$info,$dir,$Vname)=@_; + #create routing file + my $top="$dir/${Vname}_ni_routing_genvar.v"; + my $r; + my @ends=get_list_of_all_endpoints($self); + my @routers=get_list_of_all_routers($self); + open my $fd, ">$top" or $r = "$!\n"; + if(defined $r) { + add_colored_info($info,"Error in creating $top: $r",'red'); + return; + } + print $fd autogen_warning(); + print $fd get_license_header($top); + my $route_str=" generate\n"; + foreach my $src (@ends){ + my $PNUM=$self->object_get_attribute($src,"PNUM"); + my $src_num=get_scolar_pos($src,@ends); + my %route; + $route_str=$route_str." if(SRC_E_ADDR == $src_num) begin : SRC$src_num + always@(*)begin + destport= 0; + case(dest_e_addr)\n"; + + foreach my $dst (@ends){ + my $dest_num = get_scolar_pos($dst,@ends); + my $ref = $self->object_get_attribute('Route',"${src}::$dst"); + next if(!defined $ref); + my @path = @{$ref}; + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); + #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; + $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; + } + foreach my $q (sort {$a <=> $b} keys %route){ + $route_str=$route_str." $route{$q}: begin + destport= $q; + end\n"; + } + $route_str=$route_str." default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end\n end//SRC$src_num\n\n"; + } + $route_str=$route_str." endgenerate\n"; + print $fd "module ${Vname}_ni_routing_genvar #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter SRC_E_ADDR=0 +) ( + dest_e_addr, + destport +); + input [EAw-1 :0] dest_e_addr; + output reg [DSTPw-1 :0] destport; + +$route_str + +endmodule +"; + close($fd); + add_info($info,"$top file is created\n "); +} + +################ +# ni_route +############### +sub gen_ni_routing_file { + my ($self,$info,$dir,$Vname)=@_; + my @ends=get_list_of_all_endpoints($self); + my @routers=get_list_of_all_routers($self); my $r; - my $top="$dir/${Vname}_conventional_routing.v"; + my $top="$dir/${Vname}_ni_routing.v"; open my $fd, ">$top" or $r = "$!\n"; if(defined $r) { add_colored_info($info,"Error in creating $top: $r",'red'); @@ -564,15 +640,13 @@ sub generate_routing_v { print $fd get_license_header($top); my $route_str=" always@(*)begin destport=0; - case(src_e_addr) //source address of each individual NI is fixed. So this CASE will be optimized by the synthesizer for each endpoint. -"; + case(src_e_addr) //source address of each individual NI is fixed. So this CASE will be optimized by the synthesizer for each endpoint.\n"; foreach my $src (@ends){ my $PNUM=$self->object_get_attribute($src,"PNUM"); my $src_num=get_scolar_pos($src,@ends); my %route; $route_str=$route_str." $src_num: begin - case(dest_e_addr) -"; + case(dest_e_addr)\n"; foreach my $dst (@ends){ my $dest_num = get_scolar_pos($dst,@ends); my $ref = $self->object_get_attribute('Route',"${src}::$dst"); @@ -580,13 +654,12 @@ sub generate_routing_v { my @path = @{$ref}; my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; - $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; + $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; } foreach my $q (sort {$a <=> $b} keys %route){ $route_str=$route_str." $route{$q}: begin destport= $q; - end -"; + end\n"; } $route_str=$route_str." default: begin @@ -599,10 +672,10 @@ sub generate_routing_v { destport= {DSTPw{1\'bX}}; end endcase\n end\n"; - print $fd "module ${Vname}_conventional_routing #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 + print $fd "module ${Vname}_ni_routing #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 ) ( dest_e_addr, @@ -611,38 +684,50 @@ sub generate_routing_v { ); input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; + output reg [DSTPw-1 :0] destport; $route_str -endmodule +endmodule "; -close($fd); -add_info($info,"$top file is created\n "); - -################## -# look_ahead_routing -################### - -#create routing file - $top="$dir/${Vname}_look_ahead_routing.v"; - open $fd, ">$top" or $r = "$!\n"; + close($fd); + add_info($info,"$top file is created\n "); +} +#################### +# gen_lkhead_genvar_routing_file +#################### +sub gen_lkhead_genvar_routing_file { + my ( $self,$info,$dir,$Vname,$mode)=@_; + #conventional or look_ahead + my $top="$dir/${Vname}_${mode}_routing_genvar.v"; + my $r; + my @ends=get_list_of_all_endpoints($self); + my @routers=get_list_of_all_routers($self); + my $localparam=""; + my $i=0; + foreach my $src (@ends){ + $localparam= $localparam."localparam [EAw-1 : 0] E$i=$i;\n"; + $i++; + } + open my $fd, ">$top" or $r = "$!\n"; if(defined $r) { add_colored_info($info,"Error in creating $top: $r",'red'); return; } print $fd autogen_warning(); - print $fd get_license_header($top); - $route_str=" always@(*)begin + print $fd get_license_header($top); + my $route_str=" always@(*)begin destport=0; case(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. "; - -foreach my $router (@routers){ - my $PNUM=$self->object_get_attribute($router,"PNUM"); - my $router_num=get_scolar_pos($router,@routers); - my %route; - $route_str=$route_str." $router_num: begin + $route_str=" generate\n"; + foreach my $router (@routers){ + my $PNUM=$self->object_get_attribute($router,"PNUM"); + my $router_num=get_scolar_pos($router,@routers); + my %route; + $route_str=$route_str." if(CURRENT_R_ADDR == $router_num) begin :R$router_num + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) "; # for each src-dest check if $router include in path @@ -653,17 +738,17 @@ sub generate_routing_v { my @path = @{$ref}; my $loc= get_scolar_pos($router,@path); next if(!defined $loc);# this router does not exist in path skip it - my $next_router1=$path[$loc+1]; - my $next_router2=$path[$loc+2]; + my $next_router1=($mode eq 'look_ahead')? $path[$loc+1] : $path[$loc]; + my $next_router2=($mode eq 'look_ahead')? $path[$loc+2] : $path[$loc+1]; next if(!defined $next_router2); - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); next if(!defined $p1); my $src_num=get_scolar_pos($src,@ends); my $dest_num = get_scolar_pos($dst,@ends); $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; #print "@path\n"; #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; - #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; + #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; #print"***************************\n"; } @@ -672,190 +757,113 @@ sub generate_routing_v { $route_str=$route_str." $route{$q}: begin destport= $q; end -"; - } - $route_str.=" default: begin - destport= {DSTPw{1\'bX}}; - end - endcase\n end//$router_num\n"; +"; } - $route_str.=" default: begin - destport= {DSTPw{1\'bX}}; - end - endcase\n end\n"; - - my $localparam=""; - my $i=0; - foreach my $src (@ends){ - $localparam= $localparam."localparam [EAw-1 : 0] E$i=$i;\n"; - $i++; - } + $route_str=$route_str." endcase\n end\n end//R$router_num\n\n"; + } + $route_str=$route_str." endgenerate\n"; print $fd " - `include \"pronoc_def.v\" -/******************* -* ${Vname}_look_ahead_routing -*******************/ -module ${Vname}_look_ahead_routing #( +/***************************** +* ${Vname}_${mode}_routing_genvar +******************************/ +module ${Vname}_${mode}_routing_genvar #( parameter RAw = 3, parameter EAw = 3, - parameter DSTPw=4 + parameter DSTPw=4, + parameter CURRENT_R_ADDR=0 )( - reset, - clk, - current_r_addr, dest_e_addr, src_e_addr, - destport + destport, + reset, + clk ); - input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; - output [DSTPw-1 :0] destport; + output [DSTPw-1 :0] destport; input reset,clk; + reg [EAw-1 :0] dest_e_addr_delay; reg [EAw-1 :0] src_e_addr_delay; always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset)begin + if(`pronoc_reset) begin dest_e_addr_delay<={EAw{1'b0}}; src_e_addr_delay<={EAw{1'b0}}; end else begin dest_e_addr_delay<=dest_e_addr; src_e_addr_delay<=src_e_addr; - end + end end - - ${Vname}_look_ahead_routing_comb #( - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw) - ) lkp_cmb ( - .current_r_addr(current_r_addr), + ${Vname}_${mode}_routing_genvar_comb #( + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw), + .CURRENT_R_ADDR(CURRENT_R_ADDR) + ) lkp_cmb ( .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), - .destport(destport) + .destport(destport) ); -endmodule +endmodule /******************* -* ${Vname}_look_ahead_routing_comb -*******************/ -module ${Vname}_look_ahead_routing_comb #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 -)( - current_r_addr, +* ${Vname}_${mode}_routing_genvar_comb +********************/ +module ${Vname}_${mode}_routing_genvar_comb #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4, + parameter CURRENT_R_ADDR=0 +) ( dest_e_addr, src_e_addr, destport ); - input [RAw-1 :0] current_r_addr; input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; - + output reg [DSTPw-1 :0] destport; $localparam -$route_str +$route_str endmodule "; + close($fd); + add_info($info,"$top file is created\n "); -close($fd); -add_info($info,"$top file is created\n "); +} -######################### -# conventional_routing_genvar -######################### - #create routing file - $top="$dir/${Vname}_conventional_routing_genvar.v"; - open $fd, ">$top" or $r = "$!\n"; - if(defined $r) { - add_colored_info($info,"Error in creating $top: $r",'red'); - return; - } - print $fd autogen_warning(); - print $fd get_license_header($top); - $route_str=" generate -"; - foreach my $src (@ends){ - my $PNUM=$self->object_get_attribute($src,"PNUM"); - my $src_num=get_scolar_pos($src,@ends); - my %route; - $route_str=$route_str." if(SRC_E_ADDR == $src_num) begin : SRC$src_num - always@(*)begin - destport= 0; - case(dest_e_addr) -"; - - foreach my $dst (@ends){ - my $dest_num = get_scolar_pos($dst,@ends); - my $ref = $self->object_get_attribute('Route',"${src}::$dst"); - next if(!defined $ref); - my @path = @{$ref}; - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] ); - #print " ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$path[1],$path[2] );\n"; - $route{$p1} = (defined $route{$p1})? $route{$p1}.",$dest_num" : "$dest_num"; - } - foreach my $q (sort {$a <=> $b} keys %route){ - $route_str=$route_str." $route{$q}: begin - destport= $q; - end -"; - } - $route_str=$route_str." default: begin - destport= {DSTPw{1\'bX}}; - end - endcase\n end\n end//SRC$src_num\n\n"; - } - $route_str=$route_str." endgenerate\n"; - print $fd "module ${Vname}_conventional_routing_genvar #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4, - parameter SRC_E_ADDR=0 -) ( - dest_e_addr, - destport -); - input [EAw-1 :0] dest_e_addr; - output reg [DSTPw-1 :0] destport; - -$route_str - -endmodule -"; -close($fd); -add_info($info,"$top file is created\n "); +########### +# gen_lkhead_conv_routing_file +########## +sub gen_lkhead_conv_routing_file { + my ( $self,$info,$dir,$Vname,$mode)=@_; + #conventional or look_ahead + my $r; + my @ends=get_list_of_all_endpoints($self); + my @routers=get_list_of_all_routers($self); -################## -# look_ahead_routing_genvar -################### -#create routing file - $top="$dir/${Vname}_look_ahead_routing_genvar.v"; - open $fd, ">$top" or $r = "$!\n"; + my $top="$dir/${Vname}_${mode}_routing.v"; + open my $fd, ">$top" or $r = "$!\n"; if(defined $r) { add_colored_info($info,"Error in creating $top: $r",'red'); return; } print $fd autogen_warning(); - print $fd get_license_header($top); - $route_str=" always@(*)begin + print $fd get_license_header($top); + my $route_str=" always@(*)begin destport=0; case(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. "; - $route_str=" generate\n"; - - foreach my $router (@routers){ - my $PNUM=$self->object_get_attribute($router,"PNUM"); - my $router_num=get_scolar_pos($router,@routers); - my %route; - $route_str=$route_str." if(CURRENT_R_ADDR == $router_num) begin :R$router_num - always@(*)begin - destport= 0; +foreach my $router (@routers){ + my $PNUM=$self->object_get_attribute($router,"PNUM"); + my $router_num=get_scolar_pos($router,@routers); + my %route; + $route_str=$route_str." $router_num: begin case({src_e_addr,dest_e_addr}) "; # for each src-dest check if $router include in path @@ -866,17 +874,17 @@ sub generate_routing_v { my @path = @{$ref}; my $loc= get_scolar_pos($router,@path); next if(!defined $loc);# this router does not exist in path skip it - my $next_router1=$path[$loc+1]; - my $next_router2=$path[$loc+2]; + my $next_router1=($mode eq 'look_ahead')? $path[$loc+1] : $path[$loc]; + my $next_router2=($mode eq 'look_ahead')? $path[$loc+2] : $path[$loc+1]; next if(!defined $next_router2); - my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); + my ($p1,$p2)= get_connection_port_num_between_two_nodes($self,$next_router1,$next_router2); next if(!defined $p1); my $src_num=get_scolar_pos($src,@ends); my $dest_num = get_scolar_pos($dst,@ends); $route{$p1} = (defined $route{$p1})? $route{$p1}.",{E$src_num,E$dest_num}" : "{E$src_num,E$dest_num}"; #print "@path\n"; #print "(current_router, next_router1, next_router2)=($router, $next_router1, $next_router2)\n"; - #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; + #print "($p1,$p2)= get_connection_port_num_between_two_nodes(\$self,$next_router1,$next_router2)\n"; #print "\$route{$p1} ={E$src_num,E$dest_num}\n"; #print"***************************\n"; } @@ -887,37 +895,50 @@ sub generate_routing_v { end "; } - $route_str=$route_str." endcase\n end\n end//R$router_num\n\n"; + $route_str.=" default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end//$router_num\n"; } - $route_str=$route_str." endgenerate\n"; + $route_str.=" default: begin + destport= {DSTPw{1\'bX}}; + end + endcase\n end\n"; + + my $localparam=""; + my $i=0; + foreach my $src (@ends){ + $localparam= $localparam."localparam [EAw-1 : 0] E$i=$i;\n"; + $i++; + } print $fd " + `include \"pronoc_def.v\" -/***************************** -* ${Vname}_look_ahead_routing_genvar -******************************/ -module ${Vname}_look_ahead_routing_genvar #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4, - parameter CURRENT_R_ADDR=0 +/******************* +* ${Vname}_${mode}_routing +*******************/ +module ${Vname}_${mode}_routing #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 )( + reset, + clk, + current_r_addr, dest_e_addr, src_e_addr, - destport, - reset, - clk + destport ); - + input [RAw-1 :0] current_r_addr; input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; output [DSTPw-1 :0] destport; input reset,clk; - reg [EAw-1 :0] dest_e_addr_delay; reg [EAw-1 :0] src_e_addr_delay; always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin + if(`pronoc_reset)begin dest_e_addr_delay<={EAw{1'b0}}; src_e_addr_delay<={EAw{1'b0}}; end else begin @@ -925,46 +946,51 @@ sub generate_routing_v { src_e_addr_delay<=src_e_addr; end end - ${Vname}_look_ahead_routing_genvar_comb #( - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw), - .CURRENT_R_ADDR(CURRENT_R_ADDR) - ) lkp_cmb ( + + ${Vname}_${mode}_routing_comb #( + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw) + ) lkp_cmb ( + .current_r_addr(current_r_addr), .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), - .destport(destport) + .destport(destport) ); endmodule /******************* -* ${Vname}_look_ahead_routing_genvar_comb -********************/ -module ${Vname}_look_ahead_routing_genvar_comb #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4, - parameter CURRENT_R_ADDR=0 -) ( +* ${Vname}_${mode}_routing_comb +*******************/ +module ${Vname}_${mode}_routing_comb #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + current_r_addr, dest_e_addr, src_e_addr, destport ); + input [RAw-1 :0] current_r_addr; input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; + output reg [DSTPw-1 :0] destport; + $localparam -$route_str +$route_str -endmodule +endmodule "; - close($fd); - add_info($info,"$top file is created\n "); -} - +close($fd); +add_info($info,"$top file is created\n "); +} +############## +#generate_connection_v +############## sub generate_connection_v{ my($self,$info,$dir)=@_; #create connection top file @@ -988,7 +1014,7 @@ sub generate_connection_v{ my $MAX_P=0; foreach my $p (@routers){ my $Pnum=$self->object_get_attribute("$p",'PNUM'); - $MAX_P =$Pnum if($Pnum>$MAX_P ); + $MAX_P =$Pnum if($Pnum>$MAX_P ); } my $NE= scalar @ends; my $NR= scalar @routers; @@ -1043,7 +1069,7 @@ sub generate_connection_v{ } my $routers=' genvar i; - generate + generate '; my $offset=0; my $assign=""; @@ -1126,6 +1152,9 @@ sub generate_connection_v{ close $fd; } +############## +# +############## sub add_noc_custom_h{ my ($self,$info,$dir)=@_; my $name=$self->object_get_attribute('save_as'); @@ -1163,11 +1192,11 @@ sub add_routing_instance_v{ my $str=" //do not modify this line ===${Vname}=== if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : $Vname - ${Vname}_conventional_routing #( + ${Vname}_ni_routing #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) - ) the_conventional_routing ( + ) the_ni_routing ( .dest_e_addr(dest_e_addr), .src_e_addr(src_e_addr), .destport(destport) @@ -1184,13 +1213,13 @@ sub add_routing_instance_v{ } my $r = check_file_has_string($file, "===${Vname}==="); if ($r==1){ - add_info($info,"The instance ${Vname}_conventional_routing exists in $file. This file is not modified\n ",'blue'); + add_info($info,"The instance ${Vname}_ni_routing exists in $file. This file is not modified\n ",'blue'); }else{ my $text = read_file_cntent($file,' '); my @a = split('endgenerate',$text); save_file($file,"$a[0] $str $a[1]"); - add_info($info,"$file has been modified. The ${Vname}_conventional_routing has been added to the file\n ",'blue'); + add_info($info,"$file has been modified. The ${Vname}_ni_routing has been added to the file\n ",'blue'); } ##################################### # custom_lkh_routing @@ -1228,6 +1257,40 @@ sub add_routing_instance_v{ save_file($file,"$a[0] $str $a[1]"); add_info($info,"$file has been modified. The ${Vname}_look_ahead_routing has been added to the file\n ",'blue'); } + ##################################### + # custom_conv_routing + #################################### + $str=" + //do not modify this line ===${Vname}=== + if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : ${Vname} + ${Vname}_conv_routing_comb #( + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw) + ) the_routing ( + .current_r_addr(current_r_addr), + .dest_e_addr(dest_e_addr), + .src_e_addr(src_e_addr), + .destport(destport) + ); + end + endgenerate +"; + $file = "$dir/../common/custom_conv_routing.v"; + unless (-f $file){ + add_colored_info($info,"$file dose not exist\n",'red'); + return; + } + $r = check_file_has_string($file, "===${Vname}==="); + if ($r==1){ + add_info($info,"The instance ${Vname}_conv_routing exist in $file. This file is not modified\n ",'blue'); + + }else{ + my $text = read_file_cntent($file,' '); + my @a = split('endgenerate',$text); + save_file($file,"$a[0] $str $a[1]"); + add_info($info,"$file has been modified. The ${Vname}_conv_routing has been added to the file\n ",'blue'); + } } sub add_noc_instance_v{ diff --git a/mpsoc/rtl/src_noc/fmesh.sv b/mpsoc/rtl/src_noc/fmesh.sv index 02dd5a3..88e5bc8 100644 --- a/mpsoc/rtl/src_noc/fmesh.sv +++ b/mpsoc/rtl/src_noc/fmesh.sv @@ -16,7 +16,7 @@ module fmesh_addr_encoder ( generate for(i=0; i< NE; i=i+1) begin : endpoints //Endpoint decoded address - localparam ENDP= fmesh_endp_addr(i); + localparam unsigned ENDP = fmesh_endp_addr(i); assign codes[i] = EAw'(ENDP); end endgenerate @@ -38,7 +38,7 @@ module fmesh_addr_coder ( generate for(i=0; i< NE; i=i+1) begin : endpoints //Endpoint decoded address - localparam ENDP= fmesh_endp_addr(i); + localparam unsigned ENDP= fmesh_endp_addr(i); assign codes[EAw'(ENDP)] = i; end endgenerate diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index 42a1586..b7cfb27 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -247,18 +247,11 @@ module header_flit_update_lk_route_ovc #( end else begin : no_predict assign lk_dest =lk_mux_out; end - endgenerate + endgenerate generate if(IS_REGULAR_TOPO & (~IS_DETERMINISTIC))begin :coded - regular_topo_adaptive_lk_dest_encoder #( - .V(V), - .P(P), - .DSTPw(DSTPw), - .Fw(Fw), - .DST_P_MSB(DST_P_MSB), - .DST_P_LSB(DST_P_LSB) - ) dest_encoder ( + regular_topo_adaptive_lk_dest_encoder dest_encoder ( .sel(sel), .dest_coded_out(dest_coded), .vc_num_delayed(vc_num_delayed), @@ -284,7 +277,7 @@ module header_flit_update_lk_route_ovc #( always_comb begin flit_out = {flit_in[Fw-1 : Fw-2],ovc_num,flit_in[FPAYw-1 :0]}; - if(hdr_flag) flit_out[DST_P_MSB : DST_P_LSB]= dest_coded; + if(hdr_flag & IS_LOOKAHEAD) flit_out[DST_P_MSB : DST_P_LSB]= dest_coded; end endgenerate endmodule diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 31da49e..6f3bee2 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -209,7 +209,6 @@ module input_queue_per_port #( credit_init_val_out, ctrl_in ); - import pronoc_pkg::*; localparam @@ -254,7 +253,6 @@ module input_queue_per_port #( PLw = (IS_FMESH) ? Pw : ELw, VPLw= V * PLw, PRAw= P * RAw; - input reset, clk; input router_info_t router_info; @@ -289,7 +287,7 @@ module input_queue_per_port #( input ssa_ctrl_t ssa_ctrl_in; output [CRDTw-1 : 0 ] credit_init_val_out [V-1 : 0]; input ctrl_chanel_t ctrl_in [P-1 : 0]; - + wire [RAw-1 : 0] current_r_addr = router_info.router_addr; wire [PRAw-1: 0] neighbors_r_addr = router_info.neighbors_r_addr[PRAw-1: 0]; @@ -313,7 +311,7 @@ module input_queue_per_port #( logic [V-1 : 0] assigned_ovc_num [V-1:0]; logic [V-1 : 0] assigned_ovc_one_hot [V-1 : 0]; logic [Vw-1 : 0] assigned_onc_bin [V-1 : 0]; - + wire [DSTPw-1 : 0] lk_destination_in_encoded; wire [WEIGHTw-1 : 0] weight_in; wire [Fw-1 : 0] buffer_out; @@ -414,8 +412,8 @@ module input_queue_per_port #( .ep(endp_p_in), .valid() ); - end + /* verilator lint_off WIDTH */ if(IS_FATTREE & (ROUTE_NAME == "NCA_STRAIGHT_UP")) begin : fat /* verilator lint_on WIDTH */ @@ -668,7 +666,6 @@ module input_queue_per_port #( .destport_in(dest_port_multi[i]), .destport_out(dest_port_encoded[i]) ); - //check if we have multiple port to send a packet to is_onehot0 #( .IN_WIDTH(DSTPw) @@ -680,25 +677,27 @@ module input_queue_per_port #( end else begin : unicast assign multiple_dest[i] = 1'b0; - + if(IS_LOOKAHEAD) begin //lk_dst_fifo - fwft_fifo #( - .DATA_WIDTH(DSTPw), - .MAX_DEPTH (MAX_PCK), - .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) - ) lk_dest_fifo ( - .din (lk_destination_in_encoded), - .wr_en (wr_hdr_fwft_fifo_delay [i]), // Write enable - .rd_en (rd_hdr_fwft_fifo_delay [i]), // Read the next word - .dout (lk_destination_encoded [i]), // Data out - .full (), - .nearly_full (), - .recieve_more_than_0 (), - .recieve_more_than_1 (), - .reset (reset), - .clk (clk) - ); - + fwft_fifo #( + .DATA_WIDTH(DSTPw), + .MAX_DEPTH (MAX_PCK), + .IGNORE_SAME_LOC_RD_WR_WARNING(IGNORE_SAME_LOC_RD_WR_WARNING) + ) lk_dest_fifo ( + .din (lk_destination_in_encoded), + .wr_en (wr_hdr_fwft_fifo_delay [i]), // Write enable + .rd_en (rd_hdr_fwft_fifo_delay [i]), // Read the next word + .dout (lk_destination_encoded [i]), // Data out + .full (), + .nearly_full (), + .recieve_more_than_0 (), + .recieve_more_than_1 (), + .reset (reset), + .clk (clk) + ); + end else begin + assign lk_destination_encoded [i] = {DSTPw{1'b0}}; + end// IS_LOOKAHEAD if( IS_DETERMINISTIC ) begin : dtrmn_dest //destport_fifo fwft_fifo #( @@ -862,7 +861,7 @@ module input_queue_per_port #( end end - if( IS_UNICAST ) begin : unicast + if( IS_UNICAST & IS_LOOKAHEAD) begin : unicast look_ahead_routing #( .P(P) ) lk_routing ( diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 0cac8ed..73d6cae 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -599,22 +599,15 @@ endmodule /******************* * regular_topo_adaptive_lk_dest_encoder -********************/ -module regular_topo_adaptive_lk_dest_encoder #( - parameter V=4, - parameter P=5, - parameter DSTPw=P-1, - parameter Fw=37, - parameter DST_P_MSB=11, - parameter DST_P_LSB=8 -)( +********************/ +module regular_topo_adaptive_lk_dest_encoder ( sel, flit_in, dest_coded_out, vc_num_delayed, lk_dest ); - + import pronoc_pkg::*; input [V-1 : 0] sel; output [DSTPw-1 : 0]dest_coded_out; input [V-1 : 0] vc_num_delayed; @@ -624,12 +617,16 @@ module regular_topo_adaptive_lk_dest_encoder #( wire [1 : 0] ab,xy; wire sel_muxed; assign sel_muxed = |(sel & vc_num_delayed); - + localparam + //To avoid warning for Tree topology + MSB1 = (DSTPw >= 4)? 3 : 1, + LSB1 = (DSTPw >= 4)? 2 : 0, + BIT_CHANGE = (DSTPw >= 4)? 2 : 0; //lkdestport = {lkdestport_x[1:0],lkdestport_y[1:0]}; // sel: 0: xdir 1: ydir - assign ab = (sel_muxed)? lk_dest[1:0] : lk_dest[3:2]; + assign ab = (sel_muxed)? lk_dest[1:0] : lk_dest[MSB1:LSB1]; //if ab==00 change x and y direction - assign xy = (ab>0)? flit_in[DST_P_MSB : DST_P_LSB+2] : ~flit_in[DST_P_MSB : DST_P_LSB+2] ; + assign xy = (ab>0)? flit_in[DST_P_MSB : DST_P_LSB+BIT_CHANGE] : ~flit_in[DST_P_MSB : DST_P_LSB+BIT_CHANGE] ; assign dest_coded_out={xy,ab}; endmodule diff --git a/mpsoc/rtl/src_noc/mesh_torus_routting.sv b/mpsoc/rtl/src_noc/mesh_torus_routting.sv index cae208e..533533f 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_routting.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_routting.sv @@ -542,7 +542,7 @@ module regular_topo_conventional_routing #( ); end //ODD_EVEN /* verilator lint_off WIDTH */ - else if(ROUTE_NAME == "DUATO") begin : duato_routing_blk + else if(ROUTE_NAME == "FULL_ADPT") begin : duato_routing_blk /* verilator lint_on WIDTH */ duato_mesh_routing #( .NX (NX), @@ -554,7 +554,7 @@ module regular_topo_conventional_routing #( .dest_y (dest_y), .destport (destport) ); - end //DUATO + end //FULL_ADPT `ifdef SIMULATION else begin : not_supported initial $display ("Error: %s is an unsupported routing algorithm for %s topology \n",ROUTE_NAME,TOPOLOGY); end `endif @@ -616,7 +616,7 @@ module regular_topo_conventional_routing #( ); end // TRANC_NEGETIVE_FIRST /* verilator lint_off WIDTH */ - else if(ROUTE_NAME == "TRANC_DUATO") begin : tranc_duato_routing_blk + else if(ROUTE_NAME == "TRANC_FULL_ADPT") begin : tranc_duato_routing_blk /* verilator lint_on WIDTH */ tranc_duato_routing #( .NX (NX), @@ -628,7 +628,7 @@ module regular_topo_conventional_routing #( .dest_y (dest_y), .destport (destport) ); - end //TRANC_DUATO + end //TRANC_FULL_ADPT `ifdef SIMULATION else begin : not_supported2 initial $display("Error: %s is an unsupported routing algorithm for %s topology",ROUTE_NAME,TOPOLOGY); end `endif diff --git a/mpsoc/rtl/src_noc/noc_localparam.v b/mpsoc/rtl/src_noc/noc_localparam.v index 9af3342..726d04f 100644 --- a/mpsoc/rtl/src_noc/noc_localparam.v +++ b/mpsoc/rtl/src_noc/noc_localparam.v @@ -1,40 +1,40 @@ /************************************************************************** -** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE -** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. ****************************************************************************/ /********************************************************************** -** File: noc_localparam.v +** File: noc_localparam.v ** -** Copyright (C) 2014-2022 Alireza Monemi +** Copyright (C) 2014-2022 Alireza Monemi ** -** This file is part of ProNoC 2.2.0 +** This file is part of ProNoC 2.2.0 ** -** ProNoC ( stands for Prototype Network-on-chip) is free software: -** you can redistribute it and/or modify it under the terms of the GNU -** Lesser General Public License as published by the Free Software Foundation, -** either version 2 of the License, or (at your option) any later version. +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. ** -** ProNoC 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 Lesser General -** Public License for more details. +** ProNoC 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 Lesser General +** Public License for more details. ** -** You should have received a copy of the GNU Lesser General Public -** License along with ProNoC. If not, see . +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . ******************************************************************************/ - - `ifdef NOC_LOCAL_PARAM + `ifdef NOC_LOCAL_PARAM - - + + //NoC parameters - localparam NOC_ID=0; + localparam NOC_ID=0; //NOC_ID : Unique identifier for the NoC. Will be modified by phy_noc_gen.pl script + localparam TOPOLOGY="MESH"; //TOPOLOGY : Specifies the NoC topology. // Options include "MESH","FMESH","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM" @@ -65,8 +65,20 @@ //Fpay : The packet payload width in bits localparam ROUTE_NAME="XY"; - //ROUTE_NAME : Select the routing algorithm: XY(DoR) , partially adaptive (Turn models). Fully adaptive (Duato) - // options are "XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN","DUATO" + //ROUTE_NAME : Select the routing algorithm. Options are: + // - XY: Deterministic routing (Dimension-Order Routing, DoR). + // - WEST_FIRST, NORTH_LAST, NEGATIVE_FIRST, ODD_EVEN: Partially adaptive routing algorithms based on turn model restrictions. + // - FULL_ADPT: Fully adaptive routing based on Duato's algorithm; requires at least two virtual channels (VCs) per port. + // options are "XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN","FULL_ADPT" + + localparam ROUTE_MODE="LOOKAHEAD"; + //ROUTE_MODE : Select the routing algorithm mode: + // -Conventional: + // The destination output port is computed + // in the same cycle, prior to VC/SW allocation. + // -Lookahead: + // The routing decision is performed one router + // ahead, in parallel with VC/SW allocation. localparam PCK_TYPE="MULTI_FLIT"; //PCK_TYPE : Packet type. @@ -174,17 +186,15 @@ localparam CLASS_SETTING={V{1'b1}}; localparam CVw=(C==0)? V : C * V; - - - - //simulation parameter - //localparam MAX_RATIO = 1000; - localparam MAX_PCK_NUM = 1000000000; - localparam MAX_PCK_SIZ = 16383; - localparam MAX_SIM_CLKs= 1000000000; - localparam TIMSTMP_FIFO_NUM = 16; - - + + + //simulation parameter + //localparam MAX_RATIO = 1000; + localparam MAX_PCK_NUM = 1000000000; + localparam MAX_PCK_SIZ = 16383; + localparam MAX_SIM_CLKs= 1000000000; + localparam TIMSTMP_FIFO_NUM = 16; + `endif diff --git a/mpsoc/rtl/src_noc/packet_injector.sv b/mpsoc/rtl/src_noc/packet_injector.sv index 855181f..82ec1de 100644 --- a/mpsoc/rtl/src_noc/packet_injector.sv +++ b/mpsoc/rtl/src_noc/packet_injector.sv @@ -67,7 +67,9 @@ module packet_injector ( assign current_r_addr = chan_in.ctrl_chanel.router_addr; generate - if(CAST_TYPE == "UNICAST") begin : uni + if((CAST_TYPE == "UNICAST") && (IS_LOOKAHEAD==1'b1)) begin : uni + //The router is configured with lookaheadrouting. + //The header flit is supposed to carry the destinaion output port conventional_routing #( .LOCATED_IN_NI(1) ) routing_module ( diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index 95378e3..a56c270 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -167,7 +167,7 @@ module router_two_stage #( return LOCAL; end else return 0; //TODO complete it for fattree and bin tree endfunction - + always_comb begin current_r_addr = router_config_in.router_addr; current_r_id = 0; @@ -198,9 +198,7 @@ module router_two_stage #( end end end - - - + genvar i,j; generate for (i=0; i SOUTH) ) : + (IS_RING | IS_LINE) ? ((SW_LOC==LOCAL) || (SW_LOC > BACKWARD) ) : 0; + hdr_flit_t hdr_flit_i; + wire [DSTPw-1 :0] destport; + header_flit_info #( + .DATA_w (0) + ) extractor ( + .flit(chan_in.flit), + .hdr_flit(hdr_flit_i), + .data_o( ) + ); + conventional_routing #( + .LOCATED_IN_NI(LOCATED_IN_NI) // Only needed for mesh and odd-even routing + ) conv_route ( + .reset(reset), + .clk(clk), + .current_r_addr(current_r_addr), + .src_e_addr(hdr_flit_i.src_e_addr), + .dest_e_addr(hdr_flit_i.dest_e_addr), + .destport(destport) + ); + if((IS_DETERMINISTIC == 1'b0) && (LOCATED_IN_NI==0) && (IS_REGULAR_TOPO==1'b1)) begin + regular_topo_adaptive_lk_dest_encoder encoder( + .sel({V{1'b1}}), + .flit_in(chan_in.flit), + .dest_coded_out(destport_out), + .vc_num_delayed({V{1'b1}}), + .lk_dest(destport) + ); + end else begin + assign destport_out = destport; + end + assign chan_out = chan_out_tmp; + end else begin : multi + multicast_chan_in_process #( + .SW_LOC(SW_LOC), + .P(P) + )multi_cast( + .endp_port(endp_port), + .current_r_addr(current_r_addr), + .chan_in(chan_in), + .chan_out(chan_out), + .clk(clk) + ); + end + endgenerate +endmodule diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 2e22b8f..c16f8f5 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -38,7 +38,8 @@ IS_UNICAST = (CAST_TYPE == "UNICAST"), IS_BROADCAST_FULL = (CAST_TYPE == "BROADCAST_FULL"), IS_ONE_HOT_MUX = (MUX_TYPE == "ONE_HOT"), - IS_VCA_ATOMIC = (VC_REALLOCATION_TYPE == "ATOMIC"); + IS_VCA_ATOMIC = (VC_REALLOCATION_TYPE == "ATOMIC"), + IS_LOOKAHEAD = ( ROUTE_MODE=="LOOKAHEAD"); /* verilator lint_on WIDTH */ //MESH, TORUS Topology p=5 @@ -152,7 +153,7 @@ /* verilator lint_off WIDTH */ ROUTE_TYPE_REGULAR = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : - (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", + (ROUTE_NAME == "FULL_ADPT" || ROUTE_NAME == "TRANC_FULL_ADPT" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", /* verilator lint_on WIDTH */ R2R_CHANELS_REGULAR= (IS_RING || IS_LINE)? 2 : 4, R2E_CHANELS_REGULAR= NL, diff --git a/mpsoc/rtl/src_noc/traffic_gen_top.sv b/mpsoc/rtl/src_noc/traffic_gen_top.sv index 7c9a633..9342d13 100644 --- a/mpsoc/rtl/src_noc/traffic_gen_top.sv +++ b/mpsoc/rtl/src_noc/traffic_gen_top.sv @@ -851,7 +851,9 @@ module packet_gen assign pck_ready = ~buffer_empty & valid_dst; generate - if( IS_UNICAST ) begin : uni + if((CAST_TYPE == "UNICAST") && (IS_LOOKAHEAD==1'b1)) begin : conv + //The router is configured with lookaheadrouting. + //The header flit is supposed to carry the destinaion output port conventional_routing #( .LOCATED_IN_NI(1) ) routing_module ( diff --git a/mpsoc/rtl/src_openpiton/wrapper.sv b/mpsoc/rtl/src_openpiton/wrapper.sv index bc5a24c..69c21fc 100644 --- a/mpsoc/rtl/src_openpiton/wrapper.sv +++ b/mpsoc/rtl/src_openpiton/wrapper.sv @@ -356,18 +356,22 @@ module piton_to_pronoc_wrapper #( .piton_end_addr_coded_o(dest_coded) ); - - conventional_routing #( - .LOCATED_IN_NI(1) - ) routing_module ( - .reset(reset), - .clk(clk), - .current_r_addr(current_r_addr_i), - .dest_e_addr(dest_e_addr), - .src_e_addr(src_e_addr), - .destport(destport) - ); - + generate + if((CAST_TYPE == "UNICAST") && (IS_LOOKAHEAD==1'b1)) begin : conv + //The router is configured with lookaheadrouting. + //The header flit is supposed to carry the destinaion output port + conventional_routing #( + .LOCATED_IN_NI(1) + ) routing_module ( + .reset(reset), + .clk(clk), + .current_r_addr(current_r_addr_i), + .dest_e_addr(dest_e_addr), + .src_e_addr(src_e_addr), + .destport(destport) + ); + end + endgenerate //endp_addr_decoder decod1 ( .id_out(TILE_NUM), .code_in(current_e_addr)); localparam DATA_w = HEAD_DATw + Fpay - 64; wire [DATA_w-1 : 0] head_data; diff --git a/mpsoc/rtl/src_peripheral/ni/ni_master.sv b/mpsoc/rtl/src_peripheral/ni/ni_master.sv index 4441fab..ab97dc8 100644 --- a/mpsoc/rtl/src_peripheral/ni/ni_master.sv +++ b/mpsoc/rtl/src_peripheral/ni/ni_master.sv @@ -708,19 +708,21 @@ Shared registers for all VCs assign send_vc_enable_binary = 1'b0; assign receive_vc_enable_binary = 1'b0; end - endgenerate - - conventional_routing #( - .LOCATED_IN_NI(1) - ) route_compute ( - .reset(reset), - .clk(clk), - .current_r_addr(current_r_addr), - .src_e_addr(current_e_addr), - .dest_e_addr(dest_e_addr), - .destport(destport) - ); - + if((CAST_TYPE == "UNICAST") && (IS_LOOKAHEAD==1'b1)) begin : uni + //The router is configured with lookaheadrouting. + //The header flit is supposed to carry the destinaion output port + conventional_routing #( + .LOCATED_IN_NI(1) + ) route_compute ( + .reset(reset), + .clk(clk), + .current_r_addr(current_r_addr), + .src_e_addr(current_e_addr), + .dest_e_addr(dest_e_addr), + .destport(destport) + ); + end + endgenerate header_flit_generator #( .DATA_w(HDw) ) hdr_flit_gen ( diff --git a/mpsoc/rtl/src_topology/common/custom_conv_routing.v b/mpsoc/rtl/src_topology/common/custom_conv_routing.v new file mode 100644 index 0000000..330acb2 --- /dev/null +++ b/mpsoc/rtl/src_topology/common/custom_conv_routing.v @@ -0,0 +1,43 @@ +`timescale 1ns / 1ps + +module custom_conv_routing #( + parameter TOPOLOGY = "CUSTOM_NAME", + parameter ROUTE_NAME = "CUSTOM_NAME", + parameter ROUTE_TYPE = "DETERMINISTIC", + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + current_r_addr, + dest_e_addr, + src_e_addr, + destport +); + + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output [DSTPw-1 :0] destport; + + + generate + + //do not modify this line ===Tcustom1Rcustom=== + if(TOPOLOGY == "custom1" && ROUTE_NAME== "custom" ) begin : Tcustom1Rcustom + Tcustom1Rcustom_conv_routing_comb #( + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw) + ) the_routing ( + .current_r_addr(current_r_addr), + .dest_e_addr(dest_e_addr), + .src_e_addr(src_e_addr), + .destport(destport) + ); + end + endgenerate + + + + +endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conv_routing.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conv_routing.v new file mode 100644 index 0000000..0bfd980 --- /dev/null +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conv_routing.v @@ -0,0 +1,420 @@ + +/************************************************************************** +** WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE +** OVERWRITTEN AND LOST. Rename this file if you wish to do any modification. +****************************************************************************/ + + +/********************************************************************** +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conv_routing.v +** +** Copyright (C) 2014-2022 Alireza Monemi +** +** This file is part of ProNoC 2.2.0 +** +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. +** +** ProNoC 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 Lesser General +** Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . +******************************************************************************/ + + +`include "pronoc_def.v" +/******************* +* Tcustom1Rcustom_conv_routing +*******************/ +module Tcustom1Rcustom_conv_routing #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + reset, + clk, + current_r_addr, + dest_e_addr, + src_e_addr, + destport +); + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output [DSTPw-1 :0] destport; + input reset,clk; + reg [EAw-1 :0] dest_e_addr_delay; + reg [EAw-1 :0] src_e_addr_delay; + + always @ (`pronoc_clk_reset_edge )begin + if(`pronoc_reset)begin + dest_e_addr_delay<={EAw{1'b0}}; + src_e_addr_delay<={EAw{1'b0}}; + end else begin + dest_e_addr_delay<=dest_e_addr; + src_e_addr_delay<=src_e_addr; + end + end + + Tcustom1Rcustom_conv_routing_comb #( + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw) + ) lkp_cmb ( + .current_r_addr(current_r_addr), + .dest_e_addr(dest_e_addr_delay), + .src_e_addr(src_e_addr_delay), + .destport(destport) + ); +endmodule + +/******************* +* Tcustom1Rcustom_conv_routing_comb +*******************/ +module Tcustom1Rcustom_conv_routing_comb #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 +)( + current_r_addr, + dest_e_addr, + src_e_addr, + destport +); + input [RAw-1 :0] current_r_addr; + input [EAw-1 :0] dest_e_addr; + input [EAw-1 :0] src_e_addr; + output reg [DSTPw-1 :0] destport; + +localparam [EAw-1 : 0] E0=0; +localparam [EAw-1 : 0] E1=1; +localparam [EAw-1 : 0] E2=2; +localparam [EAw-1 : 0] E3=3; +localparam [EAw-1 : 0] E4=4; +localparam [EAw-1 : 0] E5=5; +localparam [EAw-1 : 0] E6=6; +localparam [EAw-1 : 0] E7=7; +localparam [EAw-1 : 0] E8=8; +localparam [EAw-1 : 0] E9=9; +localparam [EAw-1 : 0] E10=10; +localparam [EAw-1 : 0] E11=11; +localparam [EAw-1 : 0] E12=12; +localparam [EAw-1 : 0] E13=13; +localparam [EAw-1 : 0] E14=14; +localparam [EAw-1 : 0] E15=15; + + + always@(*)begin + destport=0; + case(current_r_addr) //current_r_addr of each individual router is fixed. So this CASE will be optimized by the synthesizer for each router. + 0: begin + case({src_e_addr,dest_e_addr}) + {E1,E0},{E2,E0},{E3,E0},{E4,E0},{E5,E0},{E6,E0},{E7,E0},{E8,E0},{E9,E0},{E10,E0},{E11,E0},{E12,E0},{E13,E0},{E14,E0},{E15,E0}: begin + destport= 0; + end + {E0,E1},{E0,E2},{E0,E3},{E0,E7},{E0,E10}: begin + destport= 1; + end + {E0,E4},{E0,E5},{E0,E6},{E0,E8},{E0,E9},{E0,E11},{E0,E12},{E0,E13},{E0,E14},{E0,E15}: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//0 + 1: begin + case({src_e_addr,dest_e_addr}) + {E0,E1},{E2,E1},{E3,E1},{E4,E1},{E5,E1},{E6,E1},{E7,E1},{E8,E1},{E9,E1},{E10,E1},{E11,E1},{E12,E1},{E13,E1},{E14,E1},{E15,E1}: begin + destport= 0; + end + {E1,E0},{E1,E4},{E1,E7},{E1,E8},{E1,E9},{E1,E10},{E1,E12},{E1,E15},{E2,E0},{E2,E7},{E2,E9},{E2,E10},{E2,E12}: begin + destport= 1; + end + {E1,E2},{E1,E3},{E1,E5},{E1,E6},{E1,E11},{E1,E13},{E1,E14}: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//1 + 2: begin + case({src_e_addr,dest_e_addr}) + {E0,E2},{E1,E2},{E3,E2},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E8,E2},{E9,E2},{E10,E2},{E11,E2},{E12,E2},{E13,E2},{E14,E2},{E15,E2}: begin + destport= 0; + end + {E1,E3},{E1,E5},{E1,E6},{E1,E11},{E1,E13},{E1,E14},{E2,E3},{E2,E4},{E2,E5},{E2,E6},{E2,E8},{E2,E11},{E2,E13},{E2,E14},{E2,E15}: begin + destport= 1; + end + {E2,E0},{E2,E1},{E2,E7},{E2,E9},{E2,E10},{E2,E12}: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//2 + 3: begin + case({src_e_addr,dest_e_addr}) + {E0,E3},{E1,E3},{E2,E3},{E4,E3},{E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E11,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin + destport= 0; + end + {E3,E2},{E3,E10},{E3,E11},{E3,E12}: begin + destport= 1; + end + {E3,E0},{E3,E1},{E3,E4},{E3,E5},{E3,E6},{E3,E7},{E3,E8},{E3,E9},{E3,E13},{E3,E14},{E3,E15}: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//3 + 4: begin + case({src_e_addr,dest_e_addr}) + {E0,E4},{E1,E4},{E2,E4},{E3,E4},{E5,E4},{E6,E4},{E7,E4},{E8,E4},{E9,E4},{E10,E4},{E11,E4},{E12,E4},{E13,E4},{E14,E4},{E15,E4}: begin + destport= 0; + end + {E3,E1},{E3,E6},{E3,E7},{E3,E8},{E3,E13},{E3,E14},{E4,E1},{E4,E6},{E4,E7},{E4,E8},{E4,E10},{E4,E13}: begin + destport= 1; + end + {E4,E3},{E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin + destport= 2; + end + {E3,E0},{E3,E5},{E3,E9},{E3,E15},{E4,E0},{E4,E2},{E4,E5},{E4,E9},{E4,E11},{E4,E12},{E4,E14},{E4,E15}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//4 + 5: begin + case({src_e_addr,dest_e_addr}) + {E0,E5},{E1,E5},{E2,E5},{E3,E5},{E4,E5},{E6,E5},{E7,E5},{E8,E5},{E9,E5},{E10,E5},{E11,E5},{E12,E5},{E13,E5},{E14,E5},{E15,E5}: begin + destport= 0; + end + {E0,E14},{E0,E15},{E3,E15},{E4,E12},{E4,E15},{E5,E1},{E5,E7},{E5,E8},{E5,E10},{E5,E11},{E5,E12},{E5,E15},{E6,E1},{E6,E2},{E6,E7},{E6,E8},{E6,E10},{E6,E11},{E6,E12},{E6,E14},{E6,E15},{E9,E2},{E9,E11},{E9,E15}: begin + destport= 1; + end + {E0,E4},{E0,E6},{E0,E13},{E5,E2},{E5,E3},{E5,E4},{E5,E6},{E5,E13},{E5,E14},{E9,E3},{E9,E4},{E9,E6},{E9,E13},{E9,E14}: begin + destport= 2; + end + {E3,E0},{E3,E9},{E4,E0},{E4,E9},{E5,E0},{E5,E9},{E6,E0},{E6,E9},{E11,E0},{E13,E0},{E13,E9},{E14,E9},{E15,E0},{E15,E9}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//5 + 6: begin + case({src_e_addr,dest_e_addr}) + {E0,E6},{E1,E6},{E2,E6},{E3,E6},{E4,E6},{E5,E6},{E7,E6},{E8,E6},{E9,E6},{E10,E6},{E11,E6},{E12,E6},{E13,E6},{E14,E6},{E15,E6}: begin + destport= 0; + end + {E0,E4},{E0,E13},{E4,E2},{E4,E11},{E4,E14},{E5,E2},{E5,E3},{E5,E4},{E5,E13},{E5,E14},{E6,E3},{E6,E4},{E6,E13},{E9,E3},{E9,E4},{E9,E13},{E9,E14}: begin + destport= 1; + end + {E3,E0},{E3,E5},{E3,E9},{E3,E15},{E4,E0},{E4,E5},{E4,E9},{E4,E12},{E4,E15},{E6,E0},{E6,E1},{E6,E2},{E6,E5},{E6,E7},{E6,E8},{E6,E9},{E6,E10},{E6,E11},{E6,E12},{E6,E14},{E6,E15}: begin + destport= 2; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//6 + 7: begin + case({src_e_addr,dest_e_addr}) + {E0,E7},{E1,E7},{E2,E7},{E3,E7},{E4,E7},{E5,E7},{E6,E7},{E8,E7},{E9,E7},{E10,E7},{E11,E7},{E12,E7},{E13,E7},{E14,E7},{E15,E7}: begin + destport= 0; + end + {E1,E4},{E1,E8},{E1,E9},{E1,E12},{E1,E15},{E2,E9},{E2,E12},{E7,E2},{E7,E3},{E7,E4},{E7,E5},{E7,E6},{E7,E8},{E7,E9},{E7,E11},{E7,E12},{E7,E13},{E7,E14},{E7,E15}: begin + destport= 1; + end + {E1,E0},{E1,E10},{E2,E0},{E2,E10},{E3,E10},{E4,E10},{E7,E0},{E7,E10},{E11,E10},{E13,E10},{E14,E0},{E14,E10}: begin + destport= 2; + end + {E0,E1},{E3,E1},{E4,E1},{E5,E1},{E6,E1},{E7,E1},{E8,E1},{E9,E1},{E10,E1},{E11,E1},{E12,E1},{E13,E1},{E14,E1},{E15,E1}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//7 + 8: begin + case({src_e_addr,dest_e_addr}) + {E0,E8},{E1,E8},{E2,E8},{E3,E8},{E4,E8},{E5,E8},{E6,E8},{E7,E8},{E9,E8},{E10,E8},{E11,E8},{E12,E8},{E13,E8},{E14,E8},{E15,E8}: begin + destport= 0; + end + {E1,E9},{E1,E12},{E1,E15},{E2,E9},{E2,E12},{E7,E9},{E7,E12},{E8,E0},{E8,E4},{E8,E5},{E8,E9},{E8,E10},{E8,E12}: begin + destport= 1; + end + {E1,E4},{E7,E2},{E7,E3},{E7,E4},{E7,E5},{E7,E6},{E7,E11},{E7,E13},{E7,E14},{E7,E15},{E8,E2},{E8,E3},{E8,E6},{E8,E11},{E8,E13},{E8,E14},{E8,E15}: begin + destport= 2; + end + {E3,E1},{E3,E7},{E3,E10},{E4,E1},{E4,E7},{E4,E10},{E8,E1},{E8,E7},{E9,E1},{E9,E7},{E11,E1},{E11,E7},{E11,E10},{E13,E1},{E13,E7},{E13,E10},{E14,E0},{E14,E1},{E14,E7},{E14,E10}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//8 + 9: begin + case({src_e_addr,dest_e_addr}) + {E0,E9},{E1,E9},{E2,E9},{E3,E9},{E4,E9},{E5,E9},{E6,E9},{E7,E9},{E8,E9},{E10,E9},{E11,E9},{E12,E9},{E13,E9},{E14,E9},{E15,E9}: begin + destport= 0; + end + {E0,E8},{E0,E11},{E0,E12},{E9,E1},{E9,E7},{E9,E8},{E9,E10},{E9,E12}: begin + destport= 1; + end + {E0,E4},{E0,E5},{E0,E6},{E0,E13},{E0,E14},{E0,E15},{E9,E2},{E9,E3},{E9,E4},{E9,E5},{E9,E6},{E9,E11},{E9,E13},{E9,E14},{E9,E15}: begin + destport= 2; + end + {E3,E0},{E4,E0},{E5,E0},{E6,E0},{E8,E0},{E9,E0},{E11,E0},{E12,E0},{E13,E0},{E15,E0}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//9 + 10: begin + case({src_e_addr,dest_e_addr}) + {E0,E10},{E1,E10},{E2,E10},{E3,E10},{E4,E10},{E5,E10},{E6,E10},{E7,E10},{E8,E10},{E9,E10},{E11,E10},{E12,E10},{E13,E10},{E14,E10},{E15,E10}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E10,E2},{E10,E3},{E10,E4},{E10,E5},{E10,E6},{E10,E8},{E10,E9},{E10,E11},{E10,E12},{E10,E13},{E10,E14},{E10,E15}: begin + destport= 1; + end + {E0,E1},{E0,E7},{E5,E1},{E5,E7},{E6,E1},{E6,E7},{E10,E1},{E10,E7},{E12,E1},{E12,E7},{E15,E1},{E15,E7}: begin + destport= 2; + end + {E1,E0},{E2,E0},{E7,E0},{E10,E0},{E14,E0}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//10 + 11: begin + case({src_e_addr,dest_e_addr}) + {E0,E11},{E1,E11},{E2,E11},{E3,E11},{E4,E11},{E5,E11},{E6,E11},{E7,E11},{E8,E11},{E9,E11},{E10,E11},{E12,E11},{E13,E11},{E14,E11},{E15,E11}: begin + destport= 0; + end + {E1,E5},{E1,E6},{E1,E13},{E1,E14},{E2,E4},{E2,E5},{E2,E6},{E2,E8},{E2,E13},{E2,E14},{E2,E15},{E3,E10},{E3,E12},{E11,E0},{E11,E1},{E11,E4},{E11,E5},{E11,E6},{E11,E7},{E11,E8},{E11,E9},{E11,E10},{E11,E12},{E11,E13},{E11,E14},{E11,E15}: begin + destport= 1; + end + {E0,E2},{E3,E2},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E8,E2},{E9,E2},{E10,E2},{E11,E2},{E12,E2},{E13,E2},{E14,E2},{E15,E2}: begin + destport= 2; + end + {E0,E3},{E1,E3},{E2,E3},{E11,E3}: begin + destport= 3; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//11 + 12: begin + case({src_e_addr,dest_e_addr}) + {E0,E12},{E1,E12},{E2,E12},{E3,E12},{E4,E12},{E5,E12},{E6,E12},{E7,E12},{E8,E12},{E9,E12},{E10,E12},{E11,E12},{E13,E12},{E14,E12},{E15,E12}: begin + destport= 0; + end + {E0,E2},{E0,E3},{E0,E11},{E1,E15},{E8,E4},{E8,E5},{E10,E2},{E10,E3},{E10,E4},{E10,E5},{E10,E6},{E10,E11},{E10,E13},{E10,E14},{E10,E15},{E12,E2},{E12,E3},{E12,E4},{E12,E5},{E12,E6},{E12,E11},{E12,E13},{E12,E14},{E12,E15}: begin + destport= 1; + end + {E1,E9},{E2,E9},{E7,E9},{E8,E0},{E8,E9},{E10,E9},{E11,E9},{E12,E0},{E12,E9}: begin + destport= 2; + end + {E5,E1},{E5,E7},{E5,E10},{E6,E1},{E6,E7},{E6,E10},{E8,E10},{E9,E10},{E12,E1},{E12,E7},{E12,E10},{E15,E1},{E15,E7},{E15,E10}: begin + destport= 3; + end + {E0,E8},{E5,E8},{E6,E8},{E9,E1},{E9,E7},{E9,E8},{E10,E8},{E12,E8},{E15,E8}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//12 + 13: begin + case({src_e_addr,dest_e_addr}) + {E0,E13},{E1,E13},{E2,E13},{E3,E13},{E4,E13},{E5,E13},{E6,E13},{E7,E13},{E8,E13},{E9,E13},{E10,E13},{E11,E13},{E12,E13},{E14,E13},{E15,E13}: begin + destport= 0; + end + {E0,E4},{E1,E4},{E2,E4},{E5,E3},{E5,E4},{E6,E3},{E6,E4},{E7,E3},{E7,E4},{E8,E3},{E8,E4},{E9,E3},{E9,E4},{E10,E3},{E10,E4},{E11,E4},{E12,E3},{E12,E4},{E13,E3},{E13,E4},{E14,E3},{E14,E4},{E15,E3},{E15,E4}: begin + destport= 2; + end + {E1,E6},{E2,E6},{E3,E6},{E4,E6},{E7,E6},{E8,E6},{E10,E6},{E11,E6},{E12,E6},{E13,E6},{E14,E6},{E15,E6}: begin + destport= 3; + end + {E3,E1},{E3,E7},{E3,E8},{E3,E14},{E4,E1},{E4,E2},{E4,E7},{E4,E8},{E4,E10},{E4,E11},{E4,E14},{E5,E2},{E5,E14},{E9,E14},{E13,E0},{E13,E1},{E13,E2},{E13,E5},{E13,E7},{E13,E8},{E13,E9},{E13,E10},{E13,E11},{E13,E12},{E13,E14},{E13,E15}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//13 + 14: begin + case({src_e_addr,dest_e_addr}) + {E0,E14},{E1,E14},{E2,E14},{E3,E14},{E4,E14},{E5,E14},{E6,E14},{E7,E14},{E8,E14},{E9,E14},{E10,E14},{E11,E14},{E12,E14},{E13,E14},{E15,E14}: begin + destport= 0; + end + {E1,E5},{E1,E13},{E2,E5},{E2,E15},{E3,E12},{E7,E5},{E7,E15},{E8,E15},{E11,E0},{E11,E5},{E11,E9},{E11,E12},{E11,E15},{E13,E0},{E13,E5},{E13,E9},{E13,E12},{E13,E15},{E14,E5},{E14,E9},{E14,E12},{E14,E15}: begin + destport= 1; + end + {E1,E4},{E1,E6},{E2,E4},{E2,E6},{E2,E13},{E7,E3},{E7,E4},{E7,E6},{E7,E13},{E8,E3},{E8,E6},{E8,E13},{E11,E4},{E11,E6},{E11,E13},{E14,E3},{E14,E4},{E14,E6},{E14,E13}: begin + destport= 2; + end + {E2,E8},{E3,E1},{E3,E7},{E3,E8},{E3,E10},{E4,E1},{E4,E7},{E4,E8},{E4,E10},{E11,E1},{E11,E7},{E11,E8},{E11,E10},{E13,E1},{E13,E7},{E13,E8},{E13,E10},{E14,E0},{E14,E1},{E14,E7},{E14,E8},{E14,E10}: begin + destport= 3; + end + {E0,E2},{E0,E3},{E0,E11},{E4,E2},{E4,E11},{E5,E2},{E5,E11},{E6,E2},{E6,E11},{E7,E2},{E7,E11},{E8,E2},{E8,E11},{E9,E2},{E9,E11},{E10,E2},{E10,E11},{E12,E2},{E12,E11},{E13,E2},{E13,E11},{E14,E2},{E14,E11},{E15,E2},{E15,E11}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//14 + 15: begin + case({src_e_addr,dest_e_addr}) + {E0,E15},{E1,E15},{E2,E15},{E3,E15},{E4,E15},{E5,E15},{E6,E15},{E7,E15},{E8,E15},{E9,E15},{E10,E15},{E11,E15},{E12,E15},{E13,E15},{E14,E15}: begin + destport= 0; + end + {E3,E12},{E4,E12},{E5,E1},{E5,E7},{E5,E8},{E5,E10},{E5,E12},{E6,E1},{E6,E7},{E6,E8},{E6,E10},{E6,E12},{E11,E9},{E11,E12},{E13,E12},{E14,E12},{E15,E1},{E15,E7},{E15,E8},{E15,E10},{E15,E12}: begin + destport= 1; + end + {E0,E2},{E0,E3},{E0,E11},{E0,E14},{E5,E11},{E6,E2},{E6,E11},{E6,E14},{E9,E2},{E9,E11},{E10,E2},{E10,E11},{E10,E14},{E12,E2},{E12,E11},{E12,E14},{E15,E2},{E15,E11},{E15,E14}: begin + destport= 2; + end + {E1,E13},{E8,E4},{E10,E3},{E10,E4},{E10,E6},{E10,E13},{E12,E3},{E12,E4},{E12,E6},{E12,E13},{E15,E3},{E15,E4},{E15,E6},{E15,E13}: begin + destport= 3; + end + {E1,E5},{E2,E5},{E7,E5},{E8,E5},{E10,E5},{E11,E0},{E11,E5},{E12,E5},{E13,E0},{E13,E5},{E13,E9},{E14,E5},{E14,E9},{E15,E0},{E15,E5},{E15,E9}: begin + destport= 4; + end + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end//15 + default: begin + destport= {DSTPw{1'bX}}; + end + endcase + end + + +endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v index c933352..bacdb03 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing.v @@ -30,11 +30,11 @@ `include "pronoc_def.v" /******************* * Tcustom1Rcustom_look_ahead_routing -*******************/ +*******************/ module Tcustom1Rcustom_look_ahead_routing #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 )( reset, clk, @@ -46,40 +46,40 @@ module Tcustom1Rcustom_look_ahead_routing #( input [RAw-1 :0] current_r_addr; input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; - output [DSTPw-1 :0] destport; + output [DSTPw-1 :0] destport; input reset,clk; reg [EAw-1 :0] dest_e_addr_delay; reg [EAw-1 :0] src_e_addr_delay; always @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset)begin + if(`pronoc_reset)begin dest_e_addr_delay<={EAw{1'b0}}; src_e_addr_delay<={EAw{1'b0}}; end else begin dest_e_addr_delay<=dest_e_addr; src_e_addr_delay<=src_e_addr; - end + end end Tcustom1Rcustom_look_ahead_routing_comb #( - .RAw(RAw), - .EAw(EAw), - .DSTPw(DSTPw) + .RAw(RAw), + .EAw(EAw), + .DSTPw(DSTPw) ) lkp_cmb ( .current_r_addr(current_r_addr), .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), - .destport(destport) + .destport(destport) ); -endmodule +endmodule /******************* * Tcustom1Rcustom_look_ahead_routing_comb -*******************/ +*******************/ module Tcustom1Rcustom_look_ahead_routing_comb #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 )( current_r_addr, dest_e_addr, @@ -89,7 +89,7 @@ module Tcustom1Rcustom_look_ahead_routing_comb #( input [RAw-1 :0] current_r_addr; input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; + output reg [DSTPw-1 :0] destport; localparam [EAw-1 : 0] E0=0; localparam [EAw-1 : 0] E1=1; @@ -433,6 +433,6 @@ localparam [EAw-1 : 0] E15=15; end endcase end - + endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v index 94ecf6a..0116eb1 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v @@ -61,14 +61,14 @@ module Tcustom1Rcustom_look_ahead_routing_genvar #( end end Tcustom1Rcustom_look_ahead_routing_genvar_comb #( - .RAw(RAw), - .EAw(EAw), + .RAw(RAw), + .EAw(EAw), .DSTPw(DSTPw), - .CURRENT_R_ADDR(CURRENT_R_ADDR) + .CURRENT_R_ADDR(CURRENT_R_ADDR) ) lkp_cmb ( .dest_e_addr(dest_e_addr_delay), .src_e_addr(src_e_addr_delay), - .destport(destport) + .destport(destport) ); endmodule @@ -76,8 +76,8 @@ endmodule * Tcustom1Rcustom_look_ahead_routing_genvar_comb ********************/ module Tcustom1Rcustom_look_ahead_routing_genvar_comb #( - parameter RAw = 3, - parameter EAw = 3, + parameter RAw = 3, + parameter EAw = 3, parameter DSTPw=4, parameter CURRENT_R_ADDR=0 ) ( @@ -108,8 +108,8 @@ localparam [EAw-1 : 0] E15=15; generate if(CURRENT_R_ADDR == 0) begin :R0 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E9},{E0,E10}: begin destport= 0; @@ -125,8 +125,8 @@ localparam [EAw-1 : 0] E15=15; end//R0 if(CURRENT_R_ADDR == 1) begin :R1 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E1,E2},{E1,E7},{E2,E7}: begin destport= 0; @@ -142,8 +142,8 @@ localparam [EAw-1 : 0] E15=15; end//R1 if(CURRENT_R_ADDR == 2) begin :R2 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E1,E11},{E2,E1},{E2,E11}: begin destport= 0; @@ -159,8 +159,8 @@ localparam [EAw-1 : 0] E15=15; end//R2 if(CURRENT_R_ADDR == 3) begin :R3 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E3,E4},{E3,E11}: begin destport= 0; @@ -179,8 +179,8 @@ localparam [EAw-1 : 0] E15=15; end//R3 if(CURRENT_R_ADDR == 4) begin :R4 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E3,E13},{E4,E3},{E4,E13},{E5,E3},{E6,E3},{E7,E3},{E8,E3},{E9,E3},{E10,E3},{E12,E3},{E13,E3},{E14,E3},{E15,E3}: begin destport= 0; @@ -202,8 +202,8 @@ localparam [EAw-1 : 0] E15=15; end//R4 if(CURRENT_R_ADDR == 5) begin :R5 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E6},{E0,E15},{E3,E9},{E3,E15},{E4,E9},{E4,E15},{E5,E6},{E5,E9},{E5,E15},{E6,E9},{E6,E15},{E9,E6},{E9,E15},{E13,E9},{E14,E9},{E15,E9}: begin destport= 0; @@ -222,8 +222,8 @@ localparam [EAw-1 : 0] E15=15; end//R5 if(CURRENT_R_ADDR == 6) begin :R6 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E13},{E3,E5},{E4,E5},{E5,E13},{E6,E5},{E6,E13},{E9,E13}: begin destport= 0; @@ -245,8 +245,8 @@ localparam [EAw-1 : 0] E15=15; end//R6 if(CURRENT_R_ADDR == 7) begin :R7 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E1},{E1,E8},{E1,E10},{E2,E10},{E3,E1},{E3,E10},{E4,E1},{E4,E10},{E5,E1},{E6,E1},{E7,E1},{E7,E8},{E7,E10},{E8,E1},{E9,E1},{E10,E1},{E11,E1},{E11,E10},{E12,E1},{E13,E1},{E13,E10},{E14,E1},{E14,E10},{E15,E1}: begin destport= 0; @@ -265,8 +265,8 @@ localparam [EAw-1 : 0] E15=15; end//R7 if(CURRENT_R_ADDR == 8) begin :R8 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E1,E12},{E2,E12},{E3,E7},{E4,E7},{E7,E12},{E7,E14},{E8,E7},{E8,E12},{E8,E14},{E9,E7},{E11,E7},{E13,E7},{E14,E7}: begin destport= 0; @@ -288,8 +288,8 @@ localparam [EAw-1 : 0] E15=15; end//R8 if(CURRENT_R_ADDR == 9) begin :R9 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E5},{E0,E12},{E3,E0},{E4,E0},{E5,E0},{E6,E0},{E8,E0},{E9,E0},{E9,E5},{E9,E12},{E11,E0},{E12,E0},{E13,E0},{E15,E0}: begin destport= 0; @@ -311,8 +311,8 @@ localparam [EAw-1 : 0] E15=15; end//R9 if(CURRENT_R_ADDR == 10) begin :R10 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E7},{E1,E0},{E2,E0},{E5,E7},{E6,E7},{E7,E0},{E10,E0},{E10,E7},{E10,E12},{E12,E7},{E14,E0},{E15,E7}: begin destport= 0; @@ -334,8 +334,8 @@ localparam [EAw-1 : 0] E15=15; end//R10 if(CURRENT_R_ADDR == 11) begin :R11 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E2},{E0,E3},{E1,E3},{E1,E14},{E2,E3},{E2,E14},{E3,E2},{E4,E2},{E5,E2},{E6,E2},{E7,E2},{E8,E2},{E9,E2},{E10,E2},{E11,E2},{E11,E3},{E11,E14},{E12,E2},{E13,E2},{E14,E2},{E15,E2}: begin destport= 0; @@ -354,8 +354,8 @@ localparam [EAw-1 : 0] E15=15; end//R11 if(CURRENT_R_ADDR == 12) begin :R12 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E8},{E1,E9},{E1,E15},{E2,E9},{E5,E8},{E5,E10},{E6,E8},{E6,E10},{E7,E9},{E8,E9},{E8,E10},{E9,E8},{E9,E10},{E10,E8},{E10,E9},{E10,E15},{E11,E9},{E12,E8},{E12,E9},{E12,E10},{E12,E15},{E15,E8},{E15,E10}: begin destport= 0; @@ -374,8 +374,8 @@ localparam [EAw-1 : 0] E15=15; end//R12 if(CURRENT_R_ADDR == 13) begin :R13 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E4},{E1,E4},{E1,E6},{E2,E4},{E2,E6},{E3,E6},{E3,E14},{E4,E6},{E4,E14},{E5,E4},{E5,E14},{E6,E4},{E7,E4},{E7,E6},{E8,E4},{E8,E6},{E9,E4},{E9,E14},{E10,E4},{E10,E6},{E11,E4},{E11,E6},{E12,E4},{E12,E6},{E13,E4},{E13,E6},{E13,E14},{E14,E4},{E14,E6},{E15,E4},{E15,E6}: begin destport= 0; @@ -397,8 +397,8 @@ localparam [EAw-1 : 0] E15=15; end//R13 if(CURRENT_R_ADDR == 14) begin :R14 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E11},{E2,E8},{E2,E13},{E2,E15},{E3,E8},{E4,E8},{E4,E11},{E5,E11},{E6,E11},{E7,E11},{E7,E13},{E7,E15},{E8,E11},{E8,E13},{E8,E15},{E9,E11},{E10,E11},{E11,E8},{E11,E13},{E11,E15},{E12,E11},{E13,E8},{E13,E11},{E13,E15},{E14,E8},{E14,E11},{E14,E13},{E14,E15},{E15,E11}: begin destport= 0; @@ -420,8 +420,8 @@ localparam [EAw-1 : 0] E15=15; end//R14 if(CURRENT_R_ADDR == 15) begin :R15 - always@(*)begin - destport= 0; + always@(*)begin + destport= 0; case({src_e_addr,dest_e_addr}) {E0,E14},{E1,E5},{E1,E13},{E2,E5},{E3,E12},{E4,E12},{E5,E12},{E6,E12},{E6,E14},{E7,E5},{E8,E5},{E10,E5},{E10,E13},{E10,E14},{E11,E5},{E11,E12},{E12,E5},{E12,E13},{E12,E14},{E13,E5},{E13,E12},{E14,E5},{E14,E12},{E15,E5},{E15,E12},{E15,E13},{E15,E14}: begin destport= 0; @@ -440,6 +440,6 @@ localparam [EAw-1 : 0] E15=15; end//R15 endgenerate - -endmodule + +endmodule diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing.v similarity index 96% rename from mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v rename to mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing.v index 46e6a3e..094583d 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing.v @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing.v +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing.v ** ** Copyright (C) 2014-2022 Alireza Monemi ** @@ -25,10 +25,10 @@ ** You should have received a copy of the GNU Lesser General Public ** License along with ProNoC. If not, see . ******************************************************************************/ -module Tcustom1Rcustom_conventional_routing #( - parameter RAw = 3, - parameter EAw = 3, - parameter DSTPw=4 +module Tcustom1Rcustom_ni_routing #( + parameter RAw = 3, + parameter EAw = 3, + parameter DSTPw=4 ) ( dest_e_addr, @@ -37,7 +37,7 @@ module Tcustom1Rcustom_conventional_routing #( ); input [EAw-1 :0] dest_e_addr; input [EAw-1 :0] src_e_addr; - output reg [DSTPw-1 :0] destport; + output reg [DSTPw-1 :0] destport; always@(*)begin destport=0; diff --git a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing_genvar.v similarity index 92% rename from mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v rename to mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing_genvar.v index 1ad3a54..e2b52dd 100644 --- a/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v +++ b/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing_genvar.v @@ -6,7 +6,7 @@ /********************************************************************** -** File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_conventional_routing_genvar.v +** File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/custom1/Tcustom1Rcustom_ni_routing_genvar.v ** ** Copyright (C) 2014-2022 Alireza Monemi ** @@ -25,9 +25,9 @@ ** You should have received a copy of the GNU Lesser General Public ** License along with ProNoC. If not, see . ******************************************************************************/ -module Tcustom1Rcustom_conventional_routing_genvar #( - parameter RAw = 3, - parameter EAw = 3, +module Tcustom1Rcustom_ni_routing_genvar #( + parameter RAw = 3, + parameter EAw = 3, parameter DSTPw=4, parameter SRC_E_ADDR=0 ) ( @@ -35,11 +35,11 @@ module Tcustom1Rcustom_conventional_routing_genvar #( destport ); input [EAw-1 :0] dest_e_addr; - output reg [DSTPw-1 :0] destport; + output reg [DSTPw-1 :0] destport; generate if(SRC_E_ADDR == 0) begin : SRC0 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 1,2,3,7,10: begin @@ -56,7 +56,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC0 if(SRC_E_ADDR == 1) begin : SRC1 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 0,4,7,8,9,10,12,15: begin @@ -73,7 +73,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC1 if(SRC_E_ADDR == 2) begin : SRC2 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 3,4,5,6,8,11,13,14,15: begin @@ -90,7 +90,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC2 if(SRC_E_ADDR == 3) begin : SRC3 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 2,10,11,12: begin @@ -107,7 +107,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC3 if(SRC_E_ADDR == 4) begin : SRC4 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 1,6,7,8,10,13: begin @@ -127,7 +127,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC4 if(SRC_E_ADDR == 5) begin : SRC5 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 1,7,8,10,11,12,15: begin @@ -147,7 +147,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC5 if(SRC_E_ADDR == 6) begin : SRC6 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 3,4,13: begin @@ -164,7 +164,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC6 if(SRC_E_ADDR == 7) begin : SRC7 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 2,3,4,5,6,8,9,11,12,13,14,15: begin @@ -184,7 +184,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC7 if(SRC_E_ADDR == 8) begin : SRC8 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 0,4,5,9,10,12: begin @@ -204,7 +204,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC8 if(SRC_E_ADDR == 9) begin : SRC9 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 1,7,8,10,12: begin @@ -224,7 +224,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC9 if(SRC_E_ADDR == 10) begin : SRC10 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 2,3,4,5,6,8,9,11,12,13,14,15: begin @@ -244,7 +244,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC10 if(SRC_E_ADDR == 11) begin : SRC11 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 0,1,4,5,6,7,8,9,10,12,13,14,15: begin @@ -264,7 +264,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC11 if(SRC_E_ADDR == 12) begin : SRC12 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 2,3,4,5,6,11,13,14,15: begin @@ -287,7 +287,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC12 if(SRC_E_ADDR == 13) begin : SRC13 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 3,4: begin @@ -307,7 +307,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC13 if(SRC_E_ADDR == 14) begin : SRC14 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 5,9,12,15: begin @@ -330,7 +330,7 @@ module Tcustom1Rcustom_conventional_routing_genvar #( end//SRC14 if(SRC_E_ADDR == 15) begin : SRC15 - always@(*)begin + always@(*)begin destport= 0; case(dest_e_addr) 1,7,8,10,12: begin diff --git a/mpsoc/rtl/src_topology/custom1/custom1.png b/mpsoc/rtl/src_topology/custom1/custom1.png index 4cdeaf08ef2b15af35f7a8d9c1dfc5fb3bee2ada..584d953c128037c26f6cbc962ad5bf1c94fcf6ec 100644 GIT binary patch literal 137543 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 DP0>y;pWBsQn(jsBZ~j&m*o-z415l-5G7wuOEp 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

p*2B9Oa_e2N82`Gnz@el9MT#%POscdYIBi;6Dw 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 vMnP0E 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 T`NLQLG5~?6tDnm{r-UW|NmVo* diff --git a/mpsoc/rtl/src_topology/custom_flist.f b/mpsoc/rtl/src_topology/custom_flist.f index 84acb86..d5173d1 100644 --- a/mpsoc/rtl/src_topology/custom_flist.f +++ b/mpsoc/rtl/src_topology/custom_flist.f @@ -1,10 +1,12 @@ +incdir+./ -./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v -./custom1/custom1_noc_genvar.sv -./custom1/Tcustom1Rcustom_conventional_routing_genvar.v -./custom1/custom1_noc.sv -./custom1/Tcustom1Rcustom_conventional_routing.v -./custom1/Tcustom1Rcustom_look_ahead_routing.v +./common/custom_lkh_routing.v ./common/custom_ni_routing.v +./common/custom_conv_routing.v ./common/custom_noc_top.sv -./common/custom_lkh_routing.v +./custom1/Tcustom1Rcustom_conv_routing.v +./custom1/Tcustom1Rcustom_ni_routing_genvar.v +./custom1/Tcustom1Rcustom_ni_routing.v +./custom1/custom1_noc.sv +./custom1/Tcustom1Rcustom_look_ahead_routing.v +./custom1/Tcustom1Rcustom_look_ahead_routing_genvar.v +./custom1/custom1_noc_genvar.sv diff --git a/mpsoc/rtl/src_topology/param.obj b/mpsoc/rtl/src_topology/param.obj index 64460e3..fdf2aff 100644 --- a/mpsoc/rtl/src_topology/param.obj +++ b/mpsoc/rtl/src_topology/param.obj @@ -1,5 +1,5 @@ ####################################################################### -## File: /home/alireza/work/git/ProNoC-repos/github-pronoc/mpsoc/rtl/src_topology/param.obj +## File: /home/alireza/work/git/hca_git/git-hub/ProNoC/mpsoc/rtl/src_topology/param.obj ## ## Copyright (C) 2014-2022 Alireza Monemi ## @@ -9,21 +9,15 @@ ## MAY CAUSE UNEXPECTED BEHAVIOR. ################################################################################ $Topology = { - '"custom1"' => { + '"mesh4x4"' => { 'T1' => 16, - 'T2' => 16, - 'ROUTE_NAME' => '"custom"', - 'T3' => 5, + 'ROUTE_NAME' => '"custom","m4"', 'ROUTER_Ps' => { - '3' => 4, - '4' => 8, - '5' => 4 + '5' => 16 }, + 'T2' => 16, + 'T3' => 5, 'er_addr' => [ - 0, - 1, - 2, - 3, 4, 5, 6, @@ -32,18 +26,31 @@ $Topology = { 9, 10, 11, + 0, + 1, + 2, + 3, 12, 13, 14, 15 ] }, - '"mesh4x4"' => { + '"custom1"' => { + 'ROUTE_NAME' => '"custom"', + 'T1' => 16, 'T3' => 5, 'ROUTER_Ps' => { - '5' => 16 + '3' => 4, + '4' => 8, + '5' => 4 }, + 'T2' => 16, 'er_addr' => [ + 0, + 1, + 2, + 3, 4, 5, 6, @@ -52,17 +59,10 @@ $Topology = { 9, 10, 11, - 0, - 1, - 2, - 3, 12, 13, 14, 15 - ], - 'T2' => 16, - 'ROUTE_NAME' => '"custom","m4"', - 'T1' => 16 + ] } }; diff --git a/mpsoc/script/parameter.sh b/mpsoc/script/parameter.sh index 262210a..583199a 100755 --- a/mpsoc/script/parameter.sh +++ b/mpsoc/script/parameter.sh @@ -24,8 +24,8 @@ CORE_NUM(){ FIRST_ARBITER_EXT_P_EN=0 ROUTE_NAME="XY" # Routing algorithm - # mesh : "XY" , "WEST_FIRST" , "NORTH_LAST" , "NEGETIVE_FIRST" , "DUATO" - # torus: "TRANC_XY" , "TRANC_WEST_FIRST", "TRANC_NORTH_LAST", "TRANC_NEGETIVE_FIRST", "TRANC_DUATO" + # mesh : "XY" , "WEST_FIRST" , "NORTH_LAST" , "NEGETIVE_FIRST" , "FULL_ADPT" + # torus: "TRANC_XY" , "TRANC_WEST_FIRST", "TRANC_NORTH_LAST", "TRANC_NEGETIVE_FIRST", "TRANC_FULL_ADPT" CLASS_SETTING="{CVw{1'b1}}" @@ -113,7 +113,7 @@ generate_parameter_v (){ printf " parameter MAX_PCK_SIZ=$MAX_PCK_SIZ;\n" >> parameter.v printf " parameter TIMSTMP_FIFO_NUM=$TIMSTMP_FIFO_NUM;\n" >> parameter.v printf " parameter ROUTE_TYPE = (ROUTE_NAME == \"XY\" || ROUTE_NAME == \"TRANC_XY\" )? \"DETERMINISTIC\" : \n" >> parameter.v - printf " (ROUTE_NAME == \"DUATO\" || ROUTE_NAME == \"TRANC_DUATO\" )? \"FULL_ADAPTIVE\": \"PAR_ADAPTIVE\"; \n" >> parameter.v + printf " (ROUTE_NAME == \"FULL_ADPT\" || ROUTE_NAME == \"TRANC_FULL_ADPT\" )? \"FULL_ADAPTIVE\": \"PAR_ADAPTIVE\"; \n" >> parameter.v printf " parameter DEBUG_EN=$DEBUG_EN;\n" >> parameter.v printf " parameter ROUTE_SUBFUNC= \"$ROUTE_SUBFUNC\";\n">> parameter.v printf " parameter AVC_ATOMIC_EN= $AVC_ATOMIC_EN;\n">> parameter.v diff --git a/mpsoc/script/verilator_2D_mesh.sh b/mpsoc/script/verilator_2D_mesh.sh index d91e71d..4a1d247 100755 --- a/mpsoc/script/verilator_2D_mesh.sh +++ b/mpsoc/script/verilator_2D_mesh.sh @@ -41,9 +41,9 @@ CORE_NUM(){ COMBINATION_TYPE="COMB_NONSPEC" # "BASELINE" or "COMB_SPEC1" or "COMB_SPEC2" or "COMB_NONSPEC" FIRST_ARBITER_EXT_P_EN=1 TOPOLOGY="MESH" #"MESH" or "TORUS" - ROUTE_NAME="DUATO" # Routing algorithm - # mesh : "XY" , "WEST_FIRST" , "NORTH_LAST" , "NEGETIVE_FIRST" , "DUATO" - # torus: "TRANC_XY" , "TRANC_WEST_FIRST", "TRANC_NORTH_LAST", "TRANC_NEGETIVE_FIRST", "TRANC_DUATO" + ROUTE_NAME="FULL_ADPT" # Routing algorithm + # mesh : "XY" , "WEST_FIRST" , "NORTH_LAST" , "NEGETIVE_FIRST" , "FULL_ADPT" + # torus: "TRANC_XY" , "TRANC_WEST_FIRST", "TRANC_NORTH_LAST", "TRANC_NEGETIVE_FIRST", "TRANC_FULL_ADPT" CONGESTION_INDEX="VC" #"CREDIT","VC" CLASS_SETTING="4'b1111" #0: no class. packets can be sent to any available OVC @@ -113,7 +113,7 @@ generate_parameter_v (){ printf " parameter MAX_DELAY_BTWN_PCKTS=$MAX_DELAY_BTWN_PCKTS;\n" >> parameter.v printf " parameter DEBUG_EN=$DEBUG_EN;\n" >> parameter.v printf " parameter ROUTE_TYPE = (ROUTE_NAME == \"XY\" || ROUTE_NAME == \"TRANC_XY\" )? \"DETERMINISTIC\" : \n" >> parameter.v - printf " (ROUTE_NAME == \"DUATO\" || ROUTE_NAME == \"TRANC_DUATO\" )? \"FULL_ADAPTIVE\": \"PAR_ADAPTIVE\"; \n" >> parameter.v + printf " (ROUTE_NAME == \"FULL_ADPT\" || ROUTE_NAME == \"TRANC_FULL_ADPT\" )? \"FULL_ADAPTIVE\": \"PAR_ADAPTIVE\"; \n" >> parameter.v printf " parameter ADD_PIPREG_AFTER_CROSSBAR= $ADD_PIPREG_AFTER_CROSSBAR;\n" >> parameter.v printf " parameter CVw=(C==0)? V : C * V;\n" >> parameter.v printf " parameter [CVw-1: 0] CLASS_SETTING = $CLASS_SETTING;\n">> parameter.v @@ -168,7 +168,7 @@ for PACKET_SIZE in 3 2 4 6 for TRAFFIC in "RANDOM" "TRANSPOSE1" "TRANSPOSE2" "HOTSPOT" do - for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "DUATO" + for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" do # regenerate NoC generate_parameter_v @@ -190,7 +190,7 @@ for PACKET_SIZE in 3 2 4 6 #run multiple testbench files in the same time cd $multiple_path - for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "DUATO" + for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" do ./$ROUTE_NAME$TRAFFIC"_"$PACKET_SIZE $ROUTE_NAME$TRAFFIC"_"$PACKET_SIZE & @@ -200,7 +200,7 @@ for PACKET_SIZE in 3 2 4 6 wait # merge the result in one file - for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "DUATO" + for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" do data_file=$data_path/$TRAFFIC"_"$PACKET_SIZE"_all.txt" plot_file=$plot_path/$TRAFFIC"_"$PACKET_SIZE".eps" diff --git a/mpsoc/smart-netrace/src/src.pl b/mpsoc/smart-netrace/src/src.pl index 417b0f9..3ce2da7 100755 --- a/mpsoc/smart-netrace/src/src.pl +++ b/mpsoc/smart-netrace/src/src.pl @@ -21,7 +21,7 @@ use warnings; my $pp; - $pp= do "$src/deafult_noc_param"; + $pp= do "$src/default_noc_param"; die "Error reading: $@" if $@; my $param = $pp->{'noc_param'}; diff --git a/mpsoc/src_c/plot/parameter.v b/mpsoc/src_c/plot/parameter.v index 01b9350..aa4c112 100755 --- a/mpsoc/src_c/plot/parameter.v +++ b/mpsoc/src_c/plot/parameter.v @@ -33,7 +33,7 @@ parameter TIMSTMP_FIFO_NUM=64; parameter [V-1 : 0] ESCAP_VC_MASK=1; parameter ROUTE_TYPE = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" || ROUTE_NAME == "TRANC")? "DETERMINISTIC" : - (ROUTE_NAME == "DUATO" || ROUTE_NAME == "TRANC_DUATO" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE"; + (ROUTE_NAME == "FULL_ADPT" || ROUTE_NAME == "TRANC_FULL_ADPT" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE"; parameter DEBUG_EN=0; parameter ROUTE_SUBFUNC= "NORTH_LAST"; parameter AVC_ATOMIC_EN= 0; diff --git a/mpsoc/src_verilator/simulator.cpp b/mpsoc/src_verilator/simulator.cpp index 15ef196..1be9cb2 100755 --- a/mpsoc/src_verilator/simulator.cpp +++ b/mpsoc/src_verilator/simulator.cpp @@ -24,7 +24,7 @@ int main(int argc, char** argv) { char change_injection_ratio=0; int i,j,x,y;//,report_delay_counter=0; - char deafult_out[] = {"result"}; + char default_out[] = {"result"}; NEw=Log2(NE); for(i=0;itask=task; new_endpt->next = *head; *head = new_endpt; @@ -75,210 +60,179 @@ void push(endpt_t ** head, task_t task) { int pop(endpt_t ** head) { // int retval = -1; endpt_t * next_endpt = NULL; - if (*head == NULL) { return -1; } - next_endpt = (*head)->next; //retval = (*head)->val; free(*head); *head = next_endpt; - return 1; + return 1; //return retval; } - int remove_by_index(endpt_t ** head, int n) { int i = 0; - // int retval = -1; + // int retval = -1; endpt_t * current = *head; endpt_t * temp_endpt = NULL; - if (n == 0) { return pop(head); } - for (i = 0; i < n-1; i++) { if (current->next == NULL) { return -1; } current = current->next; } - temp_endpt = current->next; //retval = temp_endpt->val; current->next = temp_endpt->next; free(temp_endpt); return 1; - } - int update_by_index(endpt_t * head,int loc, task_t task) { endpt_t * current = head; - int i; - for (i=0;inext; - - } - if(current == NULL) return 0; - current->task=task; + int i; + for (i=0;inext; + } + if(current == NULL) return 0; + current->task=task; return 1; - } - int read(endpt_t * head, int loc, task_t * task ) { endpt_t * current = head; - int i; - for (i=0;inext; - - } - if(current == NULL) return 0; - *task = current->task; + int i; + for (i=0;inext; + } + if(current == NULL) return 0; + *task = current->task; return 1; } - char* removewhiteSpacses (char * oldstr ) { - char *newstr = (char*) malloc(strlen(oldstr)+1); - char *np = newstr, *op = oldstr; - do { - if (*op != ' ' && *op != '\t') - *np++ = *op; - } while (*op++); - return newstr; + char *newstr = (char*) malloc(strlen(oldstr)+1); + char *np = newstr, *op = oldstr; + do { + if (*op != ' ' && *op != '\t') *np++ = *op; + } while (*op++); + return newstr; } - -int extract_traffic_data ( char * str, task_t* st) -{ - - unsigned int src; - unsigned int dst; // ID of the destination endpt (PE) - unsigned int bytes; - unsigned int initial_weight; - unsigned int min_pck_size; //in flit - unsigned int max_pck_size; //in flit - unsigned int burst; - float inject_rate; - int jnjct_var; - - int n; - n=sscanf( str, "%u,%u,%u,%u,%u,%u,%u,%f,%u",&src, &dst, &bytes, &initial_weight, &min_pck_size, &max_pck_size,&burst,&inject_rate,&jnjct_var); - - if (n<3) return 0; - - st->src = src; - st->dst=dst; - st->bytes=bytes; - st->initial_weight=(n>3 && initial_weight >0 )? initial_weight :DEAFULT_INIT_WEIGHT; - st->min_pck_size= (n>4 && min_pck_size>1 )? min_pck_size : DEAFULT_MIN_PCK_SIZE; - st->max_pck_size= (n>5 && max_pck_size >= st->min_pck_size )? max_pck_size : st->min_pck_size; - st->burst_size = (n>6 )? burst : SET_AUTO; - st->injection_rate= (n>7 )? inject_rate : SET_AUTO; - st->jnjct_var= (n>8 )? jnjct_var : 20; - // - st->avg_pck_size= (st->min_pck_size + st->max_pck_size)/2; - st->estimated_total_pck_num = (bytes*8) /(st->avg_pck_size*Fpay); - if(st->estimated_total_pck_num==0) st->estimated_total_pck_num= 1; - task_graph_total_pck_num=task_graph_total_pck_num+st->estimated_total_pck_num; - if(task_graph_min_pck_size > st->min_pck_size ) task_graph_min_pck_size= st->min_pck_size; - if(task_graph_max_pck_size < st->max_pck_size ) task_graph_max_pck_size= st->max_pck_size; - - st->pck_sent=0; - st->byte_sent=0; +int extract_traffic_data ( char * str, task_t* st) { + unsigned int src; + unsigned int dst; // ID of the destination endpt (PE) + unsigned int bytes; + unsigned int initial_weight; + unsigned int min_pck_size; //in flit + unsigned int max_pck_size; //in flit + unsigned int burst; + float inject_rate; + int jnjct_var; + + int n; + n=sscanf( str, "%u,%u,%u,%u,%u,%u,%u,%f,%u",&src, &dst, &bytes, &initial_weight, &min_pck_size, &max_pck_size,&burst,&inject_rate,&jnjct_var); + + if (n<3) return 0; + + st->src = src; + st->dst=dst; + st->bytes=bytes; + st->initial_weight=(n>3 && initial_weight >0 )? initial_weight :DEFAULT_INIT_WEIGHT; + st->min_pck_size= (n>4 && min_pck_size>1 )? min_pck_size : DEFAULT_MIN_PCK_SIZE; + st->max_pck_size= (n>5 && max_pck_size >= st->min_pck_size )? max_pck_size : st->min_pck_size; + st->burst_size = (n>6 )? burst : SET_AUTO; + st->injection_rate= (n>7 )? inject_rate : SET_AUTO; + st->jnjct_var= (n>8 )? jnjct_var : 20; + // + st->avg_pck_size= (st->min_pck_size + st->max_pck_size)/2; + st->estimated_total_pck_num = (bytes*8) /(st->avg_pck_size*Fpay); + if(st->estimated_total_pck_num==0) st->estimated_total_pck_num= 1; + task_graph_total_pck_num=task_graph_total_pck_num+st->estimated_total_pck_num; + if(task_graph_min_pck_size > st->min_pck_size ) task_graph_min_pck_size= st->min_pck_size; + if(task_graph_max_pck_size < st->max_pck_size ) task_graph_max_pck_size= st->max_pck_size; + + st->pck_sent=0; + st->byte_sent=0; st->burst_sent=0; - - return 1; + + return 1; } int calcualte_traffic_parameters(endpt_t * head[NE],index_t (* info)){ - int i,j; - task_t task; - - unsigned int max_bytes=0,accum[NE]; - unsigned int min_total[NE]; - - //find the maximum bytes that an IP sends - for(i=0;i task.estimated_total_pck_num) min_total[i] = task.estimated_total_pck_num; - j++; - } - info[i].total_index=j; - if(max_bytes < accum[i]) max_bytes=accum[i]; - } - - } - - - for(i=0;i task.estimated_total_pck_num) min_total[i] = task.estimated_total_pck_num; + j++; + } + info[i].total_index=j; + if(max_bytes < accum[i]) max_bytes=accum[i]; + } + } + + for(i=0;i=NE) continue;// the destination address must be smaller than NC - push(&head[st.src],st); - } - } - fclose(in); - calcualte_traffic_parameters(head,info); - for(i=0;i=NE) continue;// the destination address must be smaller than NC + push(&head[st.src],st); + } + } + fclose(in); + calcualte_traffic_parameters(head,info); + for(i=0;i Date: Wed, 15 Oct 2025 12:04:19 +0200 Subject: [PATCH 094/107] Clean openpiton wrapper file --- mpsoc/rtl/src_openpiton/wrapper.sv | 169 ++++++++++++++++++----------- 1 file changed, 105 insertions(+), 64 deletions(-) diff --git a/mpsoc/rtl/src_openpiton/wrapper.sv b/mpsoc/rtl/src_openpiton/wrapper.sv index 69c21fc..11adec7 100644 --- a/mpsoc/rtl/src_openpiton/wrapper.sv +++ b/mpsoc/rtl/src_openpiton/wrapper.sv @@ -1,19 +1,14 @@ -/**************************************************************************** - * wrapper.sv - ****************************************************************************/ - -/** - * Module: pronoc_to_piton_wrapper - * - * TODO: Add module documentation - */ -`timescale 1ns/1ps - +/************************************************************** + * File : wrapper.sv + * Description : Contains the necessary modules for adapting + * ProNoC with OpenPiton dynamic-node integration. + * + * Author : Alireza Monemi + * Date : 2025 + **************************************************************/ `include "define.tmp.h" `include "pronoc_def.v" - - module piton_to_pronoc_endp_addr_converter #( parameter CHIP_SET_PORT = 3 @@ -26,10 +21,8 @@ module piton_to_pronoc_endp_addr_converter pronoc_endp_addr_o, piton_end_addr_coded_o ); - import pronoc_pkg::*; - - localparam + localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH ), HEAD_DATw = (64-MSB_BE-1), ADDR_CODED = (HEAD_DATw - PRESERVED_DATw); @@ -94,7 +87,7 @@ module piton_to_pronoc_endp_addr_converter_diffrent_topology input [`NOC_CHIPID_WIDTH-1:0] piton_chipid_i; input [`NOC_X_WIDTH-1:0] piton_coreid_x_i; input [`NOC_Y_WIDTH-1:0] piton_coreid_y_i; - input [`MSG_SRC_FBITS_WIDTH-1:0] piton_fbits_i; + input [`MSG_SRC_FBITS_WIDTH-1:0] piton_fbits_i; output reg [EAw-1 : 0] pronoc_endp_addr_o; output reg [ADDR_CODED-1 : 0] piton_end_addr_coded_o; localparam [3:0] @@ -105,11 +98,11 @@ module piton_to_pronoc_endp_addr_converter_diffrent_topology FBIT_N = 4'b0101; localparam Xw = log2(NX), // number of node in x axis - Yw = log2(NY); // number of node in y axis + Yw = log2(NY); // number of node in y axis localparam PITON_TOPOLOGY = "FMESH", PITON_Xw = log2(`PITON_X_TILES), // number of node in x axis - PITON_Yw = log2(`PITON_Y_TILES), // number of node in y axis + PITON_Yw = log2(`PITON_Y_TILES), // number of node in y axis PITON_NE =(`PITON_X_TILES * `PITON_Y_TILES) + 2 * (`PITON_X_TILES+`PITON_Y_TILES), PITON_MAX_P = 5, PITON_NLw= log2(PITON_MAX_P), @@ -178,7 +171,6 @@ module piton_to_pronoc_endp_addr_converter_same_topology ); import pronoc_pkg::*; - localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH ), HEAD_DATw = (64-MSB_BE-1), @@ -193,12 +185,12 @@ module piton_to_pronoc_endp_addr_converter_same_topology output reg [ADDR_CODED-1 : 0] piton_end_addr_coded_o; localparam [3:0] - FBIT_NONE =4'b0000, + FBIT_NONE =4'b0000, FBIT_W =4'b0010, FBIT_S =4'b0011, FBIT_E =4'b0100, FBIT_N =4'b0101; - localparam + localparam Xw = log2(NX), // number of node in x axis Yw = log2(NY); // number of node in y axis @@ -210,7 +202,7 @@ module piton_to_pronoc_endp_addr_converter_same_topology (piton_fbits_i [3:0] == FBIT_E ) ? EAST: NORTH; //coded for FMESH topology - generate + generate if(TOPOLOGY == "FMESH") begin always_comb begin pronoc_endp_addr_o = {EAw{1'b0}}; @@ -226,7 +218,7 @@ module piton_to_pronoc_endp_addr_converter_same_topology end else begin //"mesh" always_comb begin pronoc_endp_addr_o = {EAw{1'b0}}; - pronoc_endp_addr_o [Yw+Xw-1 : 0] = {piton_coreid_y_i[Yw-1 : 0], piton_coreid_x_i[Xw-1 : 0]}; + pronoc_endp_addr_o [Yw+Xw-1 : 0] = {piton_coreid_y_i[Yw-1 : 0], piton_coreid_x_i[Xw-1 : 0]}; end end endgenerate @@ -237,8 +229,8 @@ module piton_to_pronoc_endp_addr_converter_same_topology if(piton_chipid_i == 8192 ) begin piton_end_addr_coded_o[ADDR_CODED-1]=1'b1; end// TODO need to know how chip id coded from zero to max or from 8192 to zero - end -endmodule + end +endmodule module pronoc_to_piton_endp_addr_converter ( @@ -258,10 +250,10 @@ module pronoc_to_piton_endp_addr_converter ( HEAD_DATw = (64-MSB_BE-1), ADDR_CODED = (HEAD_DATw - PRESERVED_DATw); -output [`NOC_CHIPID_WIDTH-1:0] piton_chipid_o; -output reg [`NOC_X_WIDTH-1:0] piton_coreid_x_o; -output reg [`NOC_Y_WIDTH-1:0] piton_coreid_y_o; -input [ADDR_CODED-1 : 0] piton_end_addr_coded_i; + output [`NOC_CHIPID_WIDTH-1:0] piton_chipid_o; + output reg [`NOC_X_WIDTH-1:0] piton_coreid_x_o; + output reg [`NOC_Y_WIDTH-1:0] piton_coreid_y_o; + input [ADDR_CODED-1 : 0] piton_end_addr_coded_i; always_comb begin piton_coreid_x_o = {`MSG_DST_X_WIDTH{1'b0}}; @@ -279,12 +271,12 @@ module piton_to_pronoc_wrapper #( parameter CHIP_SET_PORT = 3, parameter FLATID_WIDTH=8 )( - default_chipid, default_coreid_x, default_coreid_y, flat_tileid, + default_chipid, default_coreid_x, default_coreid_y, flat_tileid, reset, clk, dataIn, validIn, yummyIn, current_r_addr_i, chan_out -); +); import pronoc_pkg::*; localparam @@ -316,17 +308,17 @@ module piton_to_pronoc_wrapper #( wire [`MSG_OPTIONS_1_WIDTH-1 :0] option1 = dataIn [ `MSG_OPTIONS_1]; wire tail,head; - tail_hdr_detect #( + piton_tail_hdr_detect #( .FLIT_WIDTH(Fpay) )piton_hdr( .reset(reset), .clk(clk), - .flit_in(dataIn), + .length_in(dataIn[ `MSG_LENGTH ]), .valid(validIn), .ready(1'b1), .is_tail(tail), .is_header(head) - ); + ); wire [EAw-1 : 0] src_e_addr, dest_e_addr; wire [DSTPw-1 : 0] destport; @@ -340,11 +332,9 @@ module piton_to_pronoc_wrapper #( .piton_coreid_x_i (default_coreid_x), .piton_coreid_y_i (default_coreid_y), .piton_fbits_i (4'd0), - .pronoc_endp_addr_o (src_e_addr), .piton_end_addr_coded_o() - - ); + ); piton_to_pronoc_endp_addr_converter dst_conv ( .default_chipid_i (default_chipid), @@ -421,7 +411,7 @@ module piton_to_pronoc_wrapper #( $display("%t***Tile %d ***NoC %d************payload length =%d*************************",$time,TILE_NUM,NOC_ID,length); $display("%t*** src (c=%d,x=%d,y=%d) sends to dst (c=%d,x=%d,y=%d chan_out=%x)",$time, default_chipid, default_coreid_x, default_coreid_y, dest_chipid,dest_x,dest_y,chan_out); -//$finish; + //$finish; end end */ @@ -435,7 +425,7 @@ module piton_to_pronoc_wrapper #( (default_coreid_x != (TILE_NUM % `X_TILES ))) begin $display ("ERROR: Address missmatch! "); $finish; - end + end end //synthesis translate_on */ @@ -443,7 +433,7 @@ endmodule /******************************** - * pronoc_to_piton_wrapper + * pronoc_to_piton_wrapper * ***************************/ module pronoc_to_piton_wrapper #( parameter PORT_NUM=0, @@ -455,7 +445,7 @@ module pronoc_to_piton_wrapper #( dataOut, validOut, yummyOut, current_r_addr_o, chan_in -); +); import pronoc_pkg::*; localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH ), @@ -463,12 +453,12 @@ module pronoc_to_piton_wrapper #( ADDR_CODED = (HEAD_DATw - PRESERVED_DATw); //piton out input [`NOC_CHIPID_WIDTH-1:0] default_chipid; - input [`NOC_X_WIDTH-1:0] default_coreid_x; - input [`NOC_Y_WIDTH-1:0] default_coreid_y; + input [`NOC_X_WIDTH-1:0] default_coreid_x; + input [`NOC_Y_WIDTH-1:0] default_coreid_y; input [FLATID_WIDTH-1:0] flat_tileid; - output [Fpay-1:0] dataOut; - output validOut; - output yummyOut; + output [Fpay-1:0] dataOut; + output validOut; + output yummyOut; output [RAw-1 : 0] current_r_addr_o; //pronoc in input smartflit_chanel_t chan_in; @@ -476,7 +466,7 @@ module pronoc_to_piton_wrapper #( assign current_r_addr_o = chan_in.ctrl_chanel.router_addr; - localparam + localparam Xw = log2(NX), // number of node in x axis Yw = log2(NY); // number of node in y axis @@ -514,26 +504,18 @@ module pronoc_to_piton_wrapper #( wire [MAX_P-1:0] destport_one_hot; // FBITS coding localparam [3: 0] - FBITS_WEST = 4'b0010, + FBITS_WEST = 4'b0010, FBITS_SOUTH = 4'b0011, FBITS_EAST = 4'b0100, - FBITS_NORTH = 4'b0101, - FBITS_PROCESSOR = 4'b0000; - /* - ProNoC destination port order num - LOCAL = 0 - EAST = 1 - NORTH = 2 - WEST = 3 - SOUTH = 4 - */ + FBITS_NORTH = 4'b0101, + FBITS_PROCESSOR = 4'b0000; - //assign dest_fbits = (PORT_NUM==0) ? 4'b0000:4'b0010;//offchip + //assign dest_fbits = (PORT_NUM==0) ? 4'b0000:4'b0010;//offchip /* always @(posedge clk) begin if(validOut) begin - $display("********************************************destport_one_hot=%b; dest_fbits=%b",destport_one_hot,dest_fbits); + $display("Destport_one_hot=%b; dest_fbits=%b",destport_one_hot,dest_fbits); $finish; end end @@ -679,7 +661,6 @@ endmodule - module pronoc_noc #( parameter CHIP_SET_PORT=3, @@ -698,7 +679,7 @@ module pronoc_noc reset, clk ); - + import pronoc_pkg::*; input clk,reset; input [Fpay*NE-1:0] dataIn_flatten; @@ -724,7 +705,6 @@ module pronoc_noc genvar i; generate for (i=0;i= CHANEL_WORLD_NUM ) begin + flit_type_next = BODY; + remain_next = length_in - CHANEL_WORLD_NUM; + end + end //HEADER + BODY: begin + if(remain < CHANEL_WORLD_NUM) begin + flit_type_next = HEADER; + end else if (remain >= CHANEL_WORLD_NUM ) begin + remain_next = remain - CHANEL_WORLD_NUM; + end + end //BODY + endcase + end + end//always + + always @ (posedge clk) begin + if (reset) begin + remain <= {`MSG_LENGTH_WIDTH{1'b0}}; + flit_type <=HEADER; + end else begin + remain <= remain_next; + flit_type <= flit_type_next; + end + end + + assign is_tail = (flit_type == HEADER)? (length_in < CHANEL_WORLD_NUM) : (remain < CHANEL_WORLD_NUM); + assign is_header = (flit_type == HEADER); +endmodule \ No newline at end of file From 3663c37c4ae4abce619d11b9a6f62a6d8e1232b2 Mon Sep 17 00:00:00 2001 From: amonemi <71986417+amonemi@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:04:56 +0100 Subject: [PATCH 095/107] Ft/mesh 3d (#7) Merge: introduce 3D mesh topology support limited to DOR routing --- .github/workflows/main.yml | 2 +- .../FPGA-kc07/models/mesh_4x4_2cycle_xy_v1 | 2 +- .../FPGA-kc07/src/deafult_noc_param | 2 +- .../configurations/fmesh_8x8_2cycle_xy | 2 +- .../configurations/mesh_3d_4x3x2x2 | 10 + .../configurations/mesh_4x4x3_2cycle_xy | 2 +- .../configurations/mesh_4x4x3_vc_nonspec | 2 +- .../configurations/mesh_4x4x3_vc_spec1 | 2 +- .../configurations/mesh_4x4x3_vc_spec2 | 2 +- .../configurations/mesh_8x8_2cycle_xy | 2 +- .../Questa_lint/configurations/mesh_8x8_4vc | 2 +- .../configurations/mesh_8x8_4vc_4c | 2 +- .../configurations/mesh_8x8_4vc_hetero1 | 2 +- .../configurations/mesh_8x8_4vc_hetero2 | 2 +- .../Questa_lint/configurations/mesh_8x8_b2 | 2 +- .../configurations/ring_8x8_2cycle_xy | 2 +- .../configurations/torus_8x8_2cycle_xy | 2 +- .../VCS/Golden_ref/line4_smart3.log | 4 +- .../VCS/Golden_ref/mesh_3x3_v2_ssa.log | 16 +- .../Golden_ref/mesh_4x4_2cycle_mcast_f.log | 4 +- .../VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log | 16 +- .../Golden_ref/line4_smart3_vc_static.txt | 36 +- mpsoc/Integration_test/default_noc_param | 4 +- .../{mesh_4x4_smart3 => fmesh_4x4_smart3} | 0 .../conv_route/ring_8x8_2cycle_xy | 2 +- .../conv_route/torus_8x8_2cycle_xy | 2 +- .../{mesh_4x4_smart3 => fmesh_4x4_smart3} | 0 .../general/fmesh_8x8_2cycle_xy | 2 +- .../general/mesh_4x4x3_2cycle_xy | 2 +- .../configurations/general/mesh_8x8_2cycle_xy | 2 +- .../configurations/general/mesh_8x8_4vc_4c | 2 +- .../configurations/general/mesh_8x8_b2 | 2 +- .../general/torus_8x8_2cycle_xy | 2 +- .../configurations/line-ring/Line_3x2_v2 | 2 +- .../line-ring/line_4x3_2cycle_xy | 2 +- .../configurations/line-ring/line_8_2cycle_xy | 2 +- .../configurations/line-ring/line_8_b2 | 2 +- .../configurations/line-ring/linex8_4vc_4c | 2 +- .../line-ring/ring_8x8_2cycle_xy | 2 +- .../configurations/mesh_3d/mesh_3d_2x2x2 | 10 + .../configurations/mesh_3d/mesh_3d_4x3x2x2 | 10 + .../mesh_3d/mesh_3d_4x3x2x2_smart | 12 + .../mesh_3d/mesh_3d_4x3x2x2_ssa | 11 + .../configurations/tiny_topos/Line_3x2_v2 | 2 +- .../configurations/tiny_topos/mesh_3d_2x2x2 | 10 + .../configurations/tiny_topos/ring_3_2 | 2 +- .../vc_alloc/mesh_4x4x3_vc_nonspec | 2 +- .../vc_alloc/mesh_4x4x3_vc_spec1 | 2 +- .../vc_alloc/mesh_4x4x3_vc_spec2 | 2 +- .../configurations/vc_alloc/mesh_8x8_4vc | 2 +- .../vc_alloc/mesh_8x8_4vc_hetero1 | 2 +- .../vc_alloc/mesh_8x8_4vc_hetero2 | 2 +- .../synthetic_sim/golden_ref/conv_route | 14 +- .../synthetic_sim/golden_ref/general | 20 +- .../synthetic_sim/golden_ref/mesh_3d | 22 + .../configurations/fmesh_8x8_2cycle_xy | 2 +- .../configurations/mesh_4x4x3_2cycle_xy | 2 +- .../configurations/mesh_4x4x3_vc_nonspec | 2 +- .../configurations/mesh_4x4x3_vc_spec1 | 2 +- .../configurations/mesh_4x4x3_vc_spec2 | 2 +- .../configurations/mesh_8x8_2cycle_xy | 2 +- .../configurations/mesh_8x8_4vc | 2 +- .../configurations/mesh_8x8_4vc_4c | 2 +- .../configurations/mesh_8x8_4vc_hetero1 | 2 +- .../configurations/mesh_8x8_4vc_hetero2 | 2 +- .../verilator_lint/configurations/mesh_8x8_b2 | 2 +- .../configurations/ring_8x8_2cycle_xy | 2 +- .../configurations/torus_8x8_2cycle_xy | 2 +- mpsoc/perl_gui/lib/emulate/tt.EML | 2 +- mpsoc/perl_gui/lib/ip/NoC/ni_slave.IP | 2 +- mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC | 2 +- mpsoc/perl_gui/lib/multi_nocs/test.phy | 8 +- mpsoc/perl_gui/lib/multi_nocs/tt.phy | 6 +- mpsoc/perl_gui/lib/perl/diagram.pl | 104 +- mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl | 14 +- mpsoc/perl_gui/lib/perl/emulator.pl | 5 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 1237 ++++++----------- mpsoc/perl_gui/lib/perl/network_maker.pl | 8 +- mpsoc/perl_gui/lib/perl/simulator.pl | 6 +- mpsoc/perl_gui/lib/perl/topology.pl | 76 +- mpsoc/perl_gui/lib/perl/traffic_pattern.pl | 20 +- mpsoc/perl_gui/lib/soc/mor1k_tile.SOC | 2 +- mpsoc/rtl/arch/iport_reg_base.sv | 32 +- mpsoc/rtl/src_emulate/rtl/noc_emulator.vold | 6 +- mpsoc/rtl/src_modelsim/traffic_pattern.sv | 173 +-- mpsoc/rtl/src_noc/congestion_analyzer.sv | 387 ++---- mpsoc/rtl/src_noc/debug.sv | 113 +- mpsoc/rtl/src_noc/fattree_route.sv | 23 +- mpsoc/rtl/src_noc/flit_buffer.sv | 534 +++---- mpsoc/rtl/src_noc/fmesh.sv | 53 +- mpsoc/rtl/src_noc/header_flit.sv | 40 + mpsoc/rtl/src_noc/inout_ports.sv | 64 +- mpsoc/rtl/src_noc/input_ports.sv | 245 +--- mpsoc/rtl/src_noc/mesh_3d_top.sv | 151 ++ mpsoc/rtl/src_noc/mesh_torus.sv | 374 ++--- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 4 +- mpsoc/rtl/src_noc/mesh_torus_routting.sv | 521 +++---- mpsoc/rtl/src_noc/multicast.sv | 78 +- mpsoc/rtl/src_noc/noc_filelist.f | 1 + mpsoc/rtl/src_noc/noc_localparam.v | 4 +- mpsoc/rtl/src_noc/noc_top.sv | 10 +- mpsoc/rtl/src_noc/output_ports.sv | 1 - mpsoc/rtl/src_noc/pronoc_pkg.sv | 13 +- mpsoc/rtl/src_noc/router_bypass.sv | 73 +- mpsoc/rtl/src_noc/router_top.sv | 7 + mpsoc/rtl/src_noc/router_two_stage.sv | 11 +- mpsoc/rtl/src_noc/routing.sv | 96 +- mpsoc/rtl/src_noc/ss_allocator.sv | 43 +- mpsoc/rtl/src_noc/topology_localparam.v | 168 ++- mpsoc/rtl/src_noc/traffic_gen_top.sv | 34 +- mpsoc/rtl/src_noc/tree_route.sv | 21 +- mpsoc/rtl/src_openpiton/noc_localparam.v | 2 +- mpsoc/rtl/src_openpiton/piton_mesh.sv | 4 +- mpsoc/rtl/src_openpiton/wrapper.sv | 20 +- mpsoc/rtl/src_peripheral/ni/ni_master.sv | 8 +- mpsoc/rtl/src_peripheral/ni/ni_slave.v | 2 +- mpsoc/rtl/src_synfull/synfull_top.sv | 20 +- mpsoc/script/parameter.sh | 10 +- mpsoc/script/synfull/noc_localparam.v | 2 +- mpsoc/script/verilator_2D_mesh.sh | 14 +- mpsoc/smart-netrace/models/B4_V1_S0 | 2 +- mpsoc/smart-netrace/models/B4_V1_S2 | 2 +- mpsoc/smart-netrace/models/B4_V1_S4 | 2 +- mpsoc/smart-netrace/models/B4_V1_S7 | 2 +- mpsoc/smart-netrace/src/deafult_noc_param | 2 +- mpsoc/src_c/plot/parameter.v | 4 +- mpsoc/src_verilator/simulator.cpp | 49 +- mpsoc/src_verilator/topology/mesh.h | 695 ++++----- mpsoc/src_verilator/topology/topology_top.h | 8 +- mpsoc/src_verilator/traffic_synthetic.h | 402 +++--- 130 files changed, 2619 insertions(+), 3704 deletions(-) create mode 100644 mpsoc/Integration_test/Questa_lint/configurations/mesh_3d_4x3x2x2 rename mpsoc/Integration_test/synthetic_sim/configurations/conv_route/{mesh_4x4_smart3 => fmesh_4x4_smart3} (100%) rename mpsoc/Integration_test/synthetic_sim/configurations/general/{mesh_4x4_smart3 => fmesh_4x4_smart3} (100%) create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_2x2x2 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2 create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_smart create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_ssa create mode 100644 mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_3d_2x2x2 create mode 100644 mpsoc/Integration_test/synthetic_sim/golden_ref/mesh_3d create mode 100644 mpsoc/rtl/src_noc/mesh_3d_top.sv diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1f35a7e..5ae16aa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: image: verilator/verilator:4.104 strategy: matrix: - conf_name: [general, line-ring, multicast, vc_alloc, conv_route, tiny_topos] + conf_name: [general, line-ring, multicast, vc_alloc, conv_route, tiny_topos, mesh_3d] env: ROOT: ${{ github.workspace }}/mpsoc PRONOC_WORK: ${{ github.workspace }}/mpsoc_work diff --git a/mpsoc/Integration_test/FPGA-kc07/models/mesh_4x4_2cycle_xy_v1 b/mpsoc/Integration_test/FPGA-kc07/models/mesh_4x4_2cycle_xy_v1 index 68179c9..279821c 100644 --- a/mpsoc/Integration_test/FPGA-kc07/models/mesh_4x4_2cycle_xy_v1 +++ b/mpsoc/Integration_test/FPGA-kc07/models/mesh_4x4_2cycle_xy_v1 @@ -1,6 +1,6 @@ $model = bless( { 'compile' => "verilate_mesh.sh", 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param b/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param index d95b510..35fa420 100644 --- a/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param +++ b/mpsoc/Integration_test/FPGA-kc07/src/deafult_noc_param @@ -8,7 +8,7 @@ $model = bless( { "B" => "4", "LB" => "B", "Fpay" => "32", -"ROUTE_NAME" => "\"XY\"", +"ROUTE_NAME" => "\"DOR\"", "PCK_TYPE" => " \"MULTI_FLIT\"", "MIN_PCK_SIZE" => "2", "BYTE_EN" => "0", diff --git a/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy index ff79533..12a13c3 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy +++ b/mpsoc/Integration_test/Questa_lint/configurations/fmesh_8x8_2cycle_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"FMESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_3d_4x3x2x2 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_3d_4x3x2x2 new file mode 100644 index 0000000..5893919 --- /dev/null +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_3d_4x3x2x2 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => '"MESH_3D"', + "T1" => "4", + "T2" => "3", + "T3" => "2", + "T4" => "2", + "ROUTE_NAME" => '"DOR"', + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy index f0c8499..ee47bc2 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_2cycle_xy @@ -4,6 +4,6 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec index 719d562..6bb1a40 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_nonspec @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_NONSPEC\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 index 9d89499..1c5388c 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec1 @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_SPEC1\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 index aea90d2..ed2a7f9 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_4x4x3_vc_spec2 @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_SPEC2\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy index 4af7e61..7107201 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_2cycle_xy @@ -1,5 +1,5 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc index 248f91c..1914e8b 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ESCAP_VC_MASK" => "4'd1", "V" => 4, } diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c index d2f38c8..26296f7 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_4c @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "V" => 4, "C" => 4, "CLASS_SETTING" => "16'b1000010000100001", diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 index 5196912..89af385 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero1 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ESCAP_VC_MASK" => "4'd1", "V" => 4, "HETERO_VC"=> "1", diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 index 38c6d2b..bc13a6f 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_4vc_hetero2 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "V" => 4, "ESCAP_VC_MASK" => "4'd1", "HETERO_VC"=> "2", diff --git a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 index 8ad895e..166ee7c 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 +++ b/mpsoc/Integration_test/Questa_lint/configurations/mesh_8x8_b2 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "B"=> "2", "LB"=> 2 } diff --git a/mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy index f75ef5b..d47e3d9 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy +++ b/mpsoc/Integration_test/Questa_lint/configurations/ring_8x8_2cycle_xy @@ -3,6 +3,6 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"RING\"", "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy b/mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy index 5ade6a7..7d29733 100644 --- a/mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy +++ b/mpsoc/Integration_test/Questa_lint/configurations/torus_8x8_2cycle_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log b/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log index d8603c4..a7862c8 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/line4_smart3.log @@ -195,10 +195,10 @@ pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log index 45a5716..2733830 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_3x3_v2_ssa.log @@ -195,10 +195,10 @@ pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator @@ -1347,26 +1347,26 @@ mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./mesh_torus.sv, 336 -mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./mesh_torus.sv, 336 -mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./mesh_torus.sv, 336 -mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log index e9554f1..0fc7864 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_mcast_f.log @@ -195,10 +195,10 @@ pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log index 3a062f2..9dd7128 100644 --- a/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log +++ b/mpsoc/Integration_test/VCS/Golden_ref/mesh_4x4_2cycle_xy_v2.log @@ -195,10 +195,10 @@ pronoc_pkg, "(PCK_TYPE == "SINGLE_FLIT")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./topology_localparam.v, 143 -pronoc_pkg, "(ROUTE_NAME == "TRANC_XY")" +pronoc_pkg, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator @@ -1827,26 +1827,26 @@ mesh_torus_look_ahead_routing, "(TOPOLOGY == "TORUS")" Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./mesh_torus.sv, 336 -mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./mesh_torus.sv, 336 -mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator ./../../rtl/src_noc/./mesh_torus.sv, 336 -mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_XY")" +mesh_torus_mask_non_assignable_destport_no_self_loop, "(ROUTE_NAME == "TRANC_DOR")" A left 16-bit expression is compared to a right 64-bit expression. Comparing 'ROUTE_NAME' of type string - with '"TRANC_XY"' of type string. + with '"TRANC_DOR"' of type string. Lint-[ULCO] Unequal length in comparison operator diff --git a/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt index af4ca57..d48e414 100644 --- a/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt +++ b/mpsoc/Integration_test/VCST/Golden_ref/line4_smart3_vc_static.txt @@ -1430,9 +1430,9 @@ Module : mesh_torus_mask_non_assignable_destport_no_self_loop FileName : ./../../rtl/src_noc/./mesh_torus.sv LineNumber : 336 - Statement : if ( ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY") begin :xy + Statement : if ( ROUTE_NAME == "DOR" || ROUTE_NAME == "TRANC_DOR") begin :xy RTL_EXPRESSION : (Operators == and || used) - Node_Value : (Expr: ((ROUTE_NAME == "XY") || (ROUTE_NAME == "TRANC_XY"))) + Node_Value : (Expr: ((ROUTE_NAME == "DOR") || (ROUTE_NAME == "TRANC_DOR"))) ----------------------------------------------------------------------------- Tag : ExprParen Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] @@ -1727,9 +1727,9 @@ Module : FileName : ./../../rtl/src_noc/./topology_localparam.v LineNumber : 144 - Statement : (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : + Statement : (ROUTE_NAME == "DOR" || ROUTE_NAME == "TRANC_DOR" )? "DETERMINISTIC" : RTL_EXPRESSION : (Operators == and || used) - Node_Value : (Expr: ((ROUTE_NAME == "XY") || (ROUTE_NAME == "TRANC_XY"))) + Node_Value : (Expr: ((ROUTE_NAME == "DOR") || (ROUTE_NAME == "TRANC_DOR"))) ----------------------------------------------------------------------------- Tag : ExprParen Description : Use parenthesis in complex expression [RTL_EXPRESSION] [Node_Value] @@ -4622,7 +4622,7 @@ Module : mesh_torus_conventional_routing FileName : ./../../rtl/src_noc/./mesh_torus_routting.v LineNumber : 599 - Statement : parameter ROUTE_NAME = "XY", + Statement : parameter ROUTE_NAME = "DOR", CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -4642,7 +4642,7 @@ Module : mesh_torus_mask_non_assignable_destport FileName : ./../../rtl/src_noc/./mesh_torus.sv LineNumber : 225 - Statement : parameter ROUTE_NAME="XY", + Statement : parameter ROUTE_NAME="DOR", CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -4732,7 +4732,7 @@ Module : conventional_routing FileName : ./../../rtl/src_noc/./routing.v LineNumber : 33 - Statement : parameter ROUTE_NAME = "XY", + Statement : parameter ROUTE_NAME = "DOR", CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -4992,7 +4992,7 @@ Module : mesh_torus_deterministic_look_ahead_routing FileName : ./../../rtl/src_noc/./mesh_torus_routting.v LineNumber : 111 - Statement : parameter ROUTE_NAME="XY"// "XY", "TRANC_XY" + Statement : parameter ROUTE_NAME="DOR"// "DOR", "TRANC_DOR" CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -5212,7 +5212,7 @@ Module : mesh_torus_destp_generator FileName : ./../../rtl/src_noc/./mesh_torus.sv LineNumber : 1115 - Statement : parameter ROUTE_NAME = "XY", + Statement : parameter ROUTE_NAME = "DOR", CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -5252,7 +5252,7 @@ Module : look_ahead_routing FileName : ./../../rtl/src_noc/./routing.v LineNumber : 244 - Statement : parameter ROUTE_NAME="XY",// + Statement : parameter ROUTE_NAME="DOR",// CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -5312,7 +5312,7 @@ Module : mesh_torus_look_ahead_routing FileName : ./../../rtl/src_noc/./mesh_torus_routting.v LineNumber : 13 - Statement : parameter ROUTE_NAME = "XY",// + Statement : parameter ROUTE_NAME = "DOR",// CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -5422,7 +5422,7 @@ Module : destp_generator FileName : ./../../rtl/src_noc/./input_ports.sv LineNumber : 1091 - Statement : parameter ROUTE_NAME="XY", + Statement : parameter ROUTE_NAME="DOR", CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -5452,7 +5452,7 @@ Module : mesh_torus_mask_non_assignable_destport_no_self_loop FileName : ./../../rtl/src_noc/./mesh_torus.sv LineNumber : 282 - Statement : parameter ROUTE_NAME="XY", + Statement : parameter ROUTE_NAME="DOR", CValue : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ConstName @@ -5877,7 +5877,7 @@ Module : look_ahead_routing FileName : ./../../rtl/src_noc/./routing.v LineNumber : 244 - Statement : parameter ROUTE_NAME="XY",// + Statement : parameter ROUTE_NAME="DOR",// Param : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ParamName @@ -6067,7 +6067,7 @@ Module : destp_generator FileName : ./../../rtl/src_noc/./input_ports.sv LineNumber : 1091 - Statement : parameter ROUTE_NAME="XY", + Statement : parameter ROUTE_NAME="DOR", Param : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ParamName @@ -6377,7 +6377,7 @@ Module : mesh_torus_mask_non_assignable_destport_no_self_loop FileName : ./../../rtl/src_noc/./mesh_torus.sv LineNumber : 282 - Statement : parameter ROUTE_NAME="XY", + Statement : parameter ROUTE_NAME="DOR", Param : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ParamName @@ -6437,7 +6437,7 @@ Module : mesh_torus_mask_non_assignable_destport FileName : ./../../rtl/src_noc/./mesh_torus.sv LineNumber : 225 - Statement : parameter ROUTE_NAME="XY", + Statement : parameter ROUTE_NAME="DOR", Param : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ParamName @@ -6647,7 +6647,7 @@ Module : mesh_torus_conventional_routing FileName : ./../../rtl/src_noc/./mesh_torus_routting.v LineNumber : 599 - Statement : parameter ROUTE_NAME = "XY", + Statement : parameter ROUTE_NAME = "DOR", Param : ROUTE_NAME ----------------------------------------------------------------------------- Tag : ParamName diff --git a/mpsoc/Integration_test/default_noc_param b/mpsoc/Integration_test/default_noc_param index 0ec3ed9..b370372 100644 --- a/mpsoc/Integration_test/default_noc_param +++ b/mpsoc/Integration_test/default_noc_param @@ -5,11 +5,12 @@ $model = bless({ "T1" => "8", "T2" => "8", "T3" => "1", + "T4" => "1", "V" => "2", "B" => "4", "LB" => "B", "Fpay" => "32", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ROUTE_MODE" => "\"LOOKAHEAD\"", "PCK_TYPE" => " \"MULTI_FLIT\"", "MIN_PCK_SIZE" => "2", @@ -51,6 +52,7 @@ $model = bless({ 'T1', 'T2', 'T3', + 'T4', 'V', 'B', 'LB', diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/fmesh_4x4_smart3 similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/conv_route/mesh_4x4_smart3 rename to mpsoc/Integration_test/synthetic_sim/configurations/conv_route/fmesh_4x4_smart3 diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy index 35e24e5..ae75953 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/ring_8x8_2cycle_xy @@ -3,7 +3,7 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"RING\"", "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", "ROUTE_MODE" => "\"CONVENTIONAL\"", } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy index 58317ed..bb0e659 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/conv_route/torus_8x8_2cycle_xy @@ -1,7 +1,7 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", "ROUTE_MODE" => "\"CONVENTIONAL\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_4x4_smart3 similarity index 100% rename from mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4_smart3 rename to mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_4x4_smart3 diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_2cycle_xy index ff79533..12a13c3 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/fmesh_8x8_2cycle_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"FMESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4x3_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4x3_2cycle_xy index f0c8499..ee47bc2 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4x3_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_4x4x3_2cycle_xy @@ -4,6 +4,6 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_xy index 4af7e61..7107201 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_2cycle_xy @@ -1,5 +1,5 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_4vc_4c b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_4vc_4c index d2f38c8..26296f7 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_4vc_4c +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_4vc_4c @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "V" => 4, "C" => 4, "CLASS_SETTING" => "16'b1000010000100001", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_b2 b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_b2 index 8ad895e..166ee7c 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_b2 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/mesh_8x8_b2 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "B"=> "2", "LB"=> 2 } diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/general/torus_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/general/torus_8x8_2cycle_xy index 5ade6a7..7d29733 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/general/torus_8x8_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/general/torus_8x8_2cycle_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/Line_3x2_v2 b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/Line_3x2_v2 index af2aa51..07a06b4 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/Line_3x2_v2 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/Line_3x2_v2 @@ -8,6 +8,6 @@ $model = bless( { "B" => "4", "LB" => "4", "Fpay" => "32", - "ROUTE_NAME"=>"\"XY\"" + "ROUTE_NAME"=>"\"DOR\"" } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4x3_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4x3_2cycle_xy index 57133ba..15a1e84 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4x3_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_4x3_2cycle_xy @@ -4,6 +4,6 @@ $model = bless( { "T1" => "4", "T2" => "4", "T3" => "3", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_2cycle_xy index caa94b2..5a31cc4 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_2cycle_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"LINE\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_b2 b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_b2 index cdec6fb..8a39813 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_b2 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/line_8_b2 @@ -1,7 +1,7 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"LINE\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "B"=> "2", "LB"=> 2 } diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/linex8_4vc_4c b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/linex8_4vc_4c index 5e7b123..e204644 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/linex8_4vc_4c +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/linex8_4vc_4c @@ -1,7 +1,7 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"LINE\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "V" => 4, "C" => 4, "CLASS_SETTING" => "16'b1000010000100001", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/ring_8x8_2cycle_xy b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/ring_8x8_2cycle_xy index f75ef5b..d47e3d9 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/ring_8x8_2cycle_xy +++ b/mpsoc/Integration_test/synthetic_sim/configurations/line-ring/ring_8x8_2cycle_xy @@ -3,6 +3,6 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"RING\"", "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_2x2x2 b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_2x2x2 new file mode 100644 index 0000000..b65c45c --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_2x2x2 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => '"MESH_3D"', + "T1" => "2", + "T2" => "2", + "T3" => "2", + "T4" => "1", + "ROUTE_NAME" => '"DOR"', + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2 b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2 new file mode 100644 index 0000000..5893919 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => '"MESH_3D"', + "T1" => "4", + "T2" => "3", + "T3" => "2", + "T4" => "2", + "ROUTE_NAME" => '"DOR"', + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_smart b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_smart new file mode 100644 index 0000000..6c209c4 --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_smart @@ -0,0 +1,12 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => '"MESH_3D"', + "T1" => "4", + "T2" => "3", + "T3" => "2", + "T4" => "2", + "ROUTE_NAME" => '"DOR"', + "SSA_EN"=> "0", + "SMART_MAX" => "3", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_ssa b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_ssa new file mode 100644 index 0000000..29e38cc --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/mesh_3d/mesh_3d_4x3x2x2_ssa @@ -0,0 +1,11 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => '"MESH_3D"', + "T1" => "4", + "T2" => "3", + "T3" => "2", + "T4" => "2", + "ROUTE_NAME" => '"DOR"', + "SSA_EN"=> "1", + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 index 39a9863..191a894 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/Line_3x2_v2 @@ -8,6 +8,6 @@ $model = bless( { "B" => "4", "LB" => "4", "Fpay" => "32", - "ROUTE_NAME"=>"\"XY\"" + "ROUTE_NAME"=>"\"DOR\"" } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_3d_2x2x2 b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_3d_2x2x2 new file mode 100644 index 0000000..b65c45c --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/mesh_3d_2x2x2 @@ -0,0 +1,10 @@ +$model = bless( { + 'noc_param'=> { + "TOPOLOGY" => '"MESH_3D"', + "T1" => "2", + "T2" => "2", + "T3" => "2", + "T4" => "1", + "ROUTE_NAME" => '"DOR"', + } +}, 'ProNOC' ); diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/ring_3_2 b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/ring_3_2 index b1c5c90..0238d96 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/ring_3_2 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/tiny_topos/ring_3_2 @@ -2,7 +2,7 @@ $model = bless( { 'compile' => "verilate_mesh.sh", 'noc_param'=> { "TOPOLOGY"=>"\"RING\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", "T1" => "3", "T2" => "1", "T3" => "2", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_nonspec b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_nonspec index 719d562..6bb1a40 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_nonspec +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_nonspec @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_NONSPEC\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec1 b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec1 index 9d89499..1c5388c 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec1 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec1 @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_SPEC1\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec2 b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec2 index aea90d2..ed2a7f9 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec2 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_4x4x3_vc_spec2 @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_SPEC2\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc index 248f91c..1914e8b 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ESCAP_VC_MASK" => "4'd1", "V" => 4, } diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 index 5196912..89af385 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero1 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ESCAP_VC_MASK" => "4'd1", "V" => 4, "HETERO_VC"=> "1", diff --git a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 index 38c6d2b..bc13a6f 100644 --- a/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 +++ b/mpsoc/Integration_test/synthetic_sim/configurations/vc_alloc/mesh_8x8_4vc_hetero2 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "V" => 4, "ESCAP_VC_MASK" => "4'd1", "HETERO_VC"=> "2", diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route b/mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route index 013fab1..fe86e40 100644 --- a/mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/conv_route @@ -7,14 +7,14 @@ Verification Results: model is generated successfully. ****************************fmesh_2x2_openpiton : Compile *******************************: model is generated successfully. +****************************fmesh_4x4_smart3 : Compile *******************************: + model is generated successfully. ****************************mesh_3x3_v2_ssa : Compile *******************************: model is generated successfully. ****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: model is generated successfully. ****************************mesh_4x4_selflp_mcast_f : Compile *******************************: model is generated successfully. -****************************mesh_4x4_smart3 : Compile *******************************: - model is generated successfully. ****************************mesh_4x4x2_bcast_f : Compile *******************************: model is generated successfully. ****************************mesh_8x8_2cycle_adaptive : Compile *******************************: @@ -37,14 +37,14 @@ Verification Results: Passed: zero load (2,13.5991) saturation (62,98.8008) ****************************fmesh_2x2_openpiton : random traffic *******************************: Passed: zero load (2,8.27536) saturation (54,67.4686) +****************************fmesh_4x4_smart3 : random traffic *******************************: + Passed: zero load (2,10.1271) saturation (42,72.4117) ****************************mesh_3x3_v2_ssa : random traffic *******************************: Passed: zero load (2,9.86859) saturation (70,77.4433) ****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: Passed: zero load (2,14.4623) saturation (22,261.684) ****************************mesh_4x4_selflp_mcast_f : random traffic *******************************: Passed: zero load (2,14.366) saturation (22,257.065) -****************************mesh_4x4_smart3 : random traffic *******************************: - Passed: zero load (2,10.1271) saturation (42,72.4117) ****************************mesh_4x4x2_bcast_f : random traffic *******************************: Passed: zero load (2,20.5192) saturation (6,1071.58) ****************************mesh_8x8_2cycle_adaptive : random traffic *******************************: @@ -66,15 +66,15 @@ Verification Results: ****************************Fattree_k3_L3_st : transposed 1 traffic *******************************: Passed: zero load (26,13.4638) saturation (100,-) ****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,8.99642) saturation (54,71.4902) + Passed: zero load (2,8.44803) saturation (54,70.7567) +****************************fmesh_4x4_smart3 : transposed 1 traffic *******************************: + Passed: zero load (2,9.95941) saturation (26,73.9415) ****************************mesh_3x3_v2_ssa : transposed 1 traffic *******************************: Passed: zero load (6,9.72718) saturation (54,69.363) ****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: Passed: zero load (2,14.8953) saturation (26,146.747) ****************************mesh_4x4_selflp_mcast_f : transposed 1 traffic *******************************: Passed: zero load (2,14.6488) saturation (22,166.723) -****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: - Passed: zero load (2,10.5055) saturation (34,60.2796) ****************************mesh_4x4x2_bcast_f : transposed 1 traffic *******************************: Passed: zero load (2,21.0549) saturation (6,863.495) ****************************mesh_8x8_2cycle_adaptive : transposed 1 traffic *******************************: diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/general b/mpsoc/Integration_test/synthetic_sim/golden_ref/general index edfbf3e..e67bf42 100644 --- a/mpsoc/Integration_test/synthetic_sim/golden_ref/general +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/general @@ -9,6 +9,8 @@ Verification Results: model is generated successfully. ****************************fmesh_2x2_openpiton : Compile *******************************: model is generated successfully. +****************************fmesh_4x4_smart3 : Compile *******************************: + model is generated successfully. ****************************fmesh_8x8_2cycle_xy : Compile *******************************: model is generated successfully. ****************************fmesh_8x8_openpiton : Compile *******************************: @@ -19,8 +21,6 @@ Verification Results: model is generated successfully. ****************************mesh_4x4_2cycle_mcast_f : Compile *******************************: model is generated successfully. -****************************mesh_4x4_smart3 : Compile *******************************: - model is generated successfully. ****************************mesh_4x4_v1_B15 : Compile *******************************: model is generated successfully. ****************************mesh_4x4x3_2cycle_xy : Compile *******************************: @@ -55,6 +55,8 @@ Verification Results: Passed: zero load (2,6.28966) saturation (66,50.4578) ****************************fmesh_2x2_openpiton : random traffic *******************************: Passed: zero load (2,8.27536) saturation (54,67.4686) +****************************fmesh_4x4_smart3 : random traffic *******************************: + Passed: zero load (2,10.1271) saturation (42,72.4117) ****************************fmesh_8x8_2cycle_xy : random traffic *******************************: Passed: zero load (2,19.5638) saturation (18,137.798) ****************************fmesh_8x8_openpiton : random traffic *******************************: @@ -65,8 +67,6 @@ Verification Results: Passed: zero load (2,9.86859) saturation (70,77.4433) ****************************mesh_4x4_2cycle_mcast_f : random traffic *******************************: Passed: zero load (2,14.4623) saturation (22,261.684) -****************************mesh_4x4_smart3 : random traffic *******************************: - Passed: zero load (2,10.1271) saturation (42,72.4117) ****************************mesh_4x4_v1_B15 : random traffic *******************************: Passed: zero load (6,12.719) saturation (58,93.2747) ****************************mesh_4x4x3_2cycle_xy : random traffic *******************************: @@ -98,21 +98,21 @@ Verification Results: ****************************Fattree_k3_L3_st : transposed 1 traffic *******************************: Passed: zero load (26,13.4638) saturation (100,-) ****************************fmesh_1x1_openpiton : transposed 1 traffic *******************************: - Passed: zero load (58,6.52308) saturation (100,-) + Passed: zero load (50,6.03057) saturation (100,-) ****************************fmesh_2x2_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,8.99642) saturation (54,71.4902) + Passed: zero load (2,8.44803) saturation (54,70.7567) +****************************fmesh_4x4_smart3 : transposed 1 traffic *******************************: + Passed: zero load (2,9.95941) saturation (26,73.9415) ****************************fmesh_8x8_2cycle_xy : transposed 1 traffic *******************************: - Passed: zero load (2,21.6193) saturation (14,142.818) + Passed: zero load (2,21.0207) saturation (10,197.415) ****************************fmesh_8x8_openpiton : transposed 1 traffic *******************************: - Passed: zero load (2,15.916) saturation (26,118.048) + Passed: zero load (2,15.1688) saturation (14,111.335) ****************************mesh_2x2_openpiton : transposed 1 traffic *******************************: Passed: zero load (2,8.7482) saturation (100,-) ****************************mesh_3x3_v2_ssa : transposed 1 traffic *******************************: Passed: zero load (6,9.72718) saturation (54,69.363) ****************************mesh_4x4_2cycle_mcast_f : transposed 1 traffic *******************************: Passed: zero load (2,14.8953) saturation (26,146.747) -****************************mesh_4x4_smart3 : transposed 1 traffic *******************************: - Passed: zero load (2,10.5055) saturation (34,60.2796) ****************************mesh_4x4_v1_B15 : transposed 1 traffic *******************************: Passed: zero load (2,13.6902) saturation (38,106.686) ****************************mesh_4x4x3_2cycle_xy : transposed 1 traffic *******************************: diff --git a/mpsoc/Integration_test/synthetic_sim/golden_ref/mesh_3d b/mpsoc/Integration_test/synthetic_sim/golden_ref/mesh_3d new file mode 100644 index 0000000..bc7f3bc --- /dev/null +++ b/mpsoc/Integration_test/synthetic_sim/golden_ref/mesh_3d @@ -0,0 +1,22 @@ + +Verification Results: +****************************mesh_3d_2x2x2 : Compile *******************************: + model is generated successfully. +****************************mesh_3d_4x3x2x2 : Compile *******************************: + model is generated successfully. +****************************mesh_3d_4x3x2x2_smart : Compile *******************************: + model is generated successfully. +****************************mesh_3d_4x3x2x2_ssa : Compile *******************************: + model is generated successfully. +****************************mesh_3d_2x2x2 : random traffic *******************************: + Passed: zero load (6,10.8633) saturation (70,74.3971) +****************************mesh_3d_4x3x2x2 : random traffic *******************************: + Passed: zero load (2,12.8413) saturation (38,75.3519) +****************************mesh_3d_4x3x2x2_smart : random traffic *******************************: + Passed: zero load (2,11.3919) saturation (38,73.7525) +****************************mesh_3d_4x3x2x2_ssa : random traffic *******************************: + Passed: zero load (2,12.1337) saturation (38,85.3049) +****************************mesh_3d_2x2x2 : transposed 1 traffic *******************************: + Passed: zero load (2,9.82014) saturation (54,53.6323) +****************************mesh_3d_4x3x2x2 : transposed 1 traffic *******************************: + Passed: zero load (2,12.6931) saturation (14,165.269) diff --git a/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy index ff79533..12a13c3 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy +++ b/mpsoc/Integration_test/verilator_lint/configurations/fmesh_8x8_2cycle_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"FMESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy index f0c8499..ee47bc2 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_2cycle_xy @@ -4,6 +4,6 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec index 719d562..6bb1a40 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_nonspec @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_NONSPEC\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 index 9d89499..1c5388c 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec1 @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_SPEC1\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 index aea90d2..ed2a7f9 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_4x4x3_vc_spec2 @@ -4,7 +4,7 @@ $model = bless( { "T2" => "4", "T3" => "3", "TOPOLOGY" => "\"MESH\"", - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "COMBINATION_TYPE" => "\"COMB_SPEC2\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy index 4af7e61..7107201 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_2cycle_xy @@ -1,5 +1,5 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc index 248f91c..1914e8b 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ESCAP_VC_MASK" => "4'd1", "V" => 4, } diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c index d2f38c8..26296f7 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_4c @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "V" => 4, "C" => 4, "CLASS_SETTING" => "16'b1000010000100001", diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 index 5196912..89af385 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero1 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ESCAP_VC_MASK" => "4'd1", "V" => 4, "HETERO_VC"=> "1", diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 index 38c6d2b..bc13a6f 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_4vc_hetero2 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "V" => 4, "ESCAP_VC_MASK" => "4'd1", "HETERO_VC"=> "2", diff --git a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 index 8ad895e..166ee7c 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 +++ b/mpsoc/Integration_test/verilator_lint/configurations/mesh_8x8_b2 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "B"=> "2", "LB"=> 2 } diff --git a/mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy index f75ef5b..d47e3d9 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy +++ b/mpsoc/Integration_test/verilator_lint/configurations/ring_8x8_2cycle_xy @@ -3,6 +3,6 @@ $model = bless( { 'noc_param'=> { TOPOLOGY=>"\"RING\"", "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", } }, 'ProNOC' ); diff --git a/mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy b/mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy index 5ade6a7..7d29733 100644 --- a/mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy +++ b/mpsoc/Integration_test/verilator_lint/configurations/torus_8x8_2cycle_xy @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { "TOPOLOGY" => "\"TORUS\"", - "ROUTE_NAME" => "\"TRANC_XY\"", + "ROUTE_NAME" => "\"TRANC_DOR\"", } }, 'ProNOC' ); \ No newline at end of file diff --git a/mpsoc/perl_gui/lib/emulate/tt.EML b/mpsoc/perl_gui/lib/emulate/tt.EML index 2ae815a..8397dd3 100644 --- a/mpsoc/perl_gui/lib/emulate/tt.EML +++ b/mpsoc/perl_gui/lib/emulate/tt.EML @@ -42,7 +42,7 @@ $emulate = bless( { 'ADD_PIPREG_AFTER_CROSSBAR' => '1\'b0', 'FIRST_ARBITER_EXT_P_EN' => 1, 'MIN_PCK_SIZE' => '2', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'T1' => '2', 'CONGESTION_INDEX' => 3, 'SMART_MAX' => '0' diff --git a/mpsoc/perl_gui/lib/ip/NoC/ni_slave.IP b/mpsoc/perl_gui/lib/ip/NoC/ni_slave.IP index dd714c7..2a49a3e 100644 --- a/mpsoc/perl_gui/lib/ip/NoC/ni_slave.IP +++ b/mpsoc/perl_gui/lib/ip/NoC/ni_slave.IP @@ -101,7 +101,7 @@ The maximum data that can be sent via one packet will be 2 power of MAX_DMA_TRAN 'global_param' => 'Parameter', 'redefine_param' => 1, 'content' => '', - 'default' => '"XY" ' + 'default' => '"DOR" ' }, 'Fpay' => { 'default' => ' 32', diff --git a/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC b/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC index d1a97f0..2e36799 100644 --- a/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC +++ b/mpsoc/perl_gui/lib/mpsoc/mor1k_mpsoc.MPSOC @@ -598,7 +598,7 @@ $mpsoc = bless( { 'FIRST_ARBITER_EXT_P_EN' => 1, 'T3' => '1', 'TOPOLOGY' => '"MESH"', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'VC_REALLOCATION_TYPE' => '"NONATOMIC"', 'V' => '2', 'COMBINATION_TYPE' => '"COMB_NONSPEC"', diff --git a/mpsoc/perl_gui/lib/multi_nocs/test.phy b/mpsoc/perl_gui/lib/multi_nocs/test.phy index 1873cc8..7146d07 100644 --- a/mpsoc/perl_gui/lib/multi_nocs/test.phy +++ b/mpsoc/perl_gui/lib/multi_nocs/test.phy @@ -37,7 +37,7 @@ $phy = bless( { 'SWA_ARBITER_TYPE' => '"RRA"', 'T2' => '2', 'TOPOLOGY' => '"MESH"', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'BYTE_EN' => 0, 'DEBUG_EN' => '0' }, @@ -60,7 +60,7 @@ $phy = bless( { 'FIRST_ARBITER_EXT_P_EN' => 1, 'Fpay' => '32', 'SSA_EN' => '0', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'T2' => '3', 'TOPOLOGY' => '"MESH"', 'SWA_ARBITER_TYPE' => '"RRA"', @@ -246,7 +246,7 @@ $phy = bless( { 'TOPOLOGY' => '"MESH"', 'SWA_ARBITER_TYPE' => '"RRA"', 'T1' => '2', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'Fpay' => '32', 'SSA_EN' => '0', 'FIRST_ARBITER_EXT_P_EN' => 1, @@ -289,7 +289,7 @@ $phy = bless( { 'T1' => '2', 'T2' => '2', 'TOPOLOGY' => '"MESH"', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'CAST_TYPE' => '"UNICAST"', 'FIRST_ARBITER_EXT_P_EN' => 1, 'SSA_EN' => '0', diff --git a/mpsoc/perl_gui/lib/multi_nocs/tt.phy b/mpsoc/perl_gui/lib/multi_nocs/tt.phy index b6f0872..54885fe 100644 --- a/mpsoc/perl_gui/lib/multi_nocs/tt.phy +++ b/mpsoc/perl_gui/lib/multi_nocs/tt.phy @@ -36,7 +36,7 @@ $phy = bless( { 'VC_REALLOCATION_TYPE' => '"NONATOMIC"', 'AVC_ATOMIC_EN' => 0, 'B' => '4', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'ESCAP_VC_MASK' => '2\'b01', 'DEBUG_EN' => '0', 'SELF_LOOP_EN' => '0', @@ -202,7 +202,7 @@ $phy = bless( { 'WEIGHTw' => '4', 'DEBUG_EN' => '0', 'ESCAP_VC_MASK' => '2\'b01', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'B' => '4', 'AVC_ATOMIC_EN' => 0, 'VC_REALLOCATION_TYPE' => '"NONATOMIC"', @@ -237,7 +237,7 @@ $phy = bless( { 'SELF_LOOP_EN' => '0', 'AVC_ATOMIC_EN' => 0, 'VC_REALLOCATION_TYPE' => '"NONATOMIC"', - 'ROUTE_NAME' => '"XY"', + 'ROUTE_NAME' => '"DOR"', 'ESCAP_VC_MASK' => '2\'b01', 'B' => '4', 'SSA_EN' => '0', diff --git a/mpsoc/perl_gui/lib/perl/diagram.pl b/mpsoc/perl_gui/lib/perl/diagram.pl index 2236c55..d6194e6 100644 --- a/mpsoc/perl_gui/lib/perl/diagram.pl +++ b/mpsoc/perl_gui/lib/perl/diagram.pl @@ -1005,7 +1005,7 @@ sub generate_tree_dot_file{ my $hp= join("|",@hp); # my ($NE,$NR)=get_topology_info($self); my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($self); - #add endpoints + # add endpoints for(my $i=0; $i<$NE; $i++){ $dotfile=$dotfile."T$i\[ label = \"T$i\" @@ -1018,12 +1018,12 @@ sub generate_tree_dot_file{ ]; "; } - #add roots + # add roots my $label = "\{R0\}|\{$bp\}"; my $x=(($NE-1)/2); my $y= 1.5*($nl-1)+1; $dotfile.=get_router_dot_file("R0",$label,"$x,$y!",$gtype); - #add leaves + # add leaves my $t=1; for(my $l=$nl-1; $l>0; $l--){ my $NL = powi($k,$l); @@ -1036,7 +1036,7 @@ sub generate_tree_dot_file{ $dotfile.=get_router_dot_file("R$r",$label,"$x,$y!",$gtype); } } - #add leave connections + # add leave connections for(my $l=$nl-1; $l>0; $l--){ my $NL = powi($k,$l); for(my $pos=0; $pos<$NL; $pos++){ @@ -1045,7 +1045,7 @@ sub generate_tree_dot_file{ $dotfile=$dotfile.node_connection('R',$id1,undef,$k,'R',$id2,undef,$pos % $k,$gtype); } } - #add endpoints connection + # add endpoints connection for(my $i=0; $i<$NE; $i++){ my $r= sum_powi($k,$nl-1)+int($i/$k); $dotfile=$dotfile.node_connection('T',$i,undef,undef,'R',$r,undef,$i%($k),$gtype); @@ -1054,6 +1054,99 @@ sub generate_tree_dot_file{ return $dotfile; } +sub generate_3d_mesh_dot_file { + my $self=shift; + my $x_dim=$self->object_get_attribute('noc_param','T1'); + my $y_dim=$self->object_get_attribute('noc_param','T2'); + my $z_dim=$self->object_get_attribute('noc_param','T3'); + my $l_num=$self->object_get_attribute('noc_param','T4'); + # print "Generating 3D mesh dot file with dimensions: ${x_dim}x${y_dim}x${z_dim}, L_num=$l_num\n"; + my $dotfile.="digraph G {\n"; + $dotfile.=" graph [ layout = neato, rankdir = LR , splines = true, overlap = false];\n"; + $dotfile.=" node [shape=parallelogram, style=filled, color=orange, fillcolor=skyblue];\n"; + $dotfile.=" graph [splines=line, overlap=true];\n\n"; + my $node_size="width=1, height=.5, fixedsize=true"; + my $x_shift_per_layer = 0; # shift each layer slightly right + my $x_shift_per_row = .5; # shift each row slightly right + my $x_gap_mulply = 1.3; # increase the gap between two adjacent nodes in x dir + my $y_gap_mulply = 1.1; # increase the gap between two adjacent nodes in y dir + # Generate nodes with pos attributes + my $v=$z_dim*$y_dim*$x_dim; + for my $zz (0..$z_dim-1) { + for my $yy (0..$y_dim-1) { + for my $xx (0..$x_dim-1) { + my $x = $xx; + my $y = $y_dim-$yy-1; + my $z = $z_dim-$zz-1; + my $node_name = "N_${xx}_${yy}_${zz}"; + # X shifted by layer index, Y shifted by row + layer offset + my $x_pos = $x*$x_gap_mulply + $z * $x_shift_per_layer - $y * $x_shift_per_row; + my $y_pos = $y*$y_gap_mulply + $z * ($y_dim*$y_gap_mulply +.25); # space between layers + my $len = length("$v"); + my $Rnum=$xx + ($yy*$x_dim) + ($zz * $x_dim * $y_dim); + my $Rlable = sprintf("R%-${len}d", $Rnum); + $dotfile.= " $node_name [label=\"$Rlable\", pos=\"$x_pos,$y_pos!\" $node_size];\n"; + for my $ll (0..$l_num-1){ + my $Tx_pos =($ll==0 || $ll==2)? $x_pos-0.4 : $x_pos+0.3; + my $Ty_pos =($ll==0 || $ll==1)? $y_pos-0.3 : $y_pos+0.3; + my $Tnum = $ll+($Rnum*$l_num); + my $endp_name = "T_${xx}_${yy}_${zz}_$ll"; + $dotfile.= +" $endp_name [ + label=\"T$Tnum\", + pos=\"$Tx_pos,$Ty_pos!\", + shape=box, + style=filled, + fillcolor=orange, + width=0, // 0 means auto + height=0, // 0 means auto + fixedsize=false, + margin=0.01 // small margin around text +]; +"; + } + } + } + } + $dotfile.= "\n"; + # Connect nodes in X, Y, Z directions + for my $z (0..$z_dim-1) { + for my $y (0..$y_dim-1) { + for my $x (0..$x_dim-1) { + my $node = "N_${x}_${y}_${z}"; + # X direction + if ($x < $x_dim-1) { + my $neighbor = "N_" . ($x+1) . "_$y\_$z"; + $dotfile.= " $node -> $neighbor [dir=none];\n"; + } + # Y direction + if ($y < $y_dim-1) { + my $neighbor = "N_${x}_" . ($y+1) . "_$z"; + $dotfile.= " $node -> $neighbor [dir=none];\n"; + } + # Z direction + if ($z < $z_dim-1) { + my $neighbor = "N_${x}_${y}_" . ($z+1); + $dotfile.= " $node -> $neighbor [dir=none, style=dashed, constraint=false];\n"; + } + } + } + } + $dotfile.= "\n"; + # Invisible edges for column alignment + for my $z (0..$z_dim-1) { + for my $x (0..$x_dim-1) { + for my $y (0..$y_dim-2) { + my $from = "N_${x}_${y}_${z}"; + my $to = "N_${x}_" . ($y+1) . "_$z"; + $dotfile.= " $from -> $to [style=invis];\n"; + } + } + } + $dotfile.= "}\n"; + return $dotfile; +} + sub get_topology_dot_file{ my $self=shift; @@ -1062,6 +1155,7 @@ sub get_topology_dot_file{ return generate_fattree_dot_file ($self) if($topology eq '"FATTREE"'); return generate_tree_dot_file($self) if($topology eq '"TREE"'); return generate_star_dot_file($self) if($topology eq '"STAR"'); + return generate_3d_mesh_dot_file($self) if($topology eq '"MESH_3D"'); } diff --git a/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl b/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl index b574571..c00195b 100755 --- a/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl +++ b/mpsoc/perl_gui/lib/perl/emulate_ram_gen.pl @@ -97,8 +97,7 @@ sub synthetic_destination{ sub gen_synthetic_traffic_ram_line{ my ($emulate, $endp, $sample,$ratio ,$line_num,$rnd)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_sample_topology_info ($emulate,$sample); my $traffic=$emulate->object_get_attribute($sample,"traffic"); my $pck_num_to_send=$emulate->object_get_attribute($sample,"PCK_NUM_LIMIT"); my $pck_size=$emulate->object_get_attribute($sample,"PCK_SIZE"); @@ -127,8 +126,7 @@ sub gen_synthetic_traffic_ram_line{ sub get_synthetic_traffic_pattern{ my ($self, $sample)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_sample_topology_info ($self,$sample); my $rnd=random_dest_gen_no_shuffle($NE); my $traffic=$self->object_get_attribute($sample,"traffic"); my @traffics=("tornado", "transposed 1", "transposed 2", "bit reverse", "bit complement","random", "hot spot", "shuffle", "neighbor", "bit rotation" ); @@ -184,8 +182,7 @@ sub print_32_bit { sub generate_emulator_ram { my ($emulate, $sample,$ratio_in,$info)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_sample_topology_info ($emulate,$sample); my $rnd=random_dest_gen($NE); # generate a matrix of sudo random number my $traffic=$emulate->object_get_attribute($sample,"traffic"); my @traffics=("tornado", "transposed 1", "transposed 2", "bit reverse", "bit complement","random", "hot spot", "shuffle", "neighbor", "bit rotation" ); @@ -324,8 +321,7 @@ sub read_statistic_mem_fast { sub read_pack_gen{ my ($emulate,$sample,$info,$jtag_intfc,$ratio_in)= @_; my $ref=$emulate->object_get_attribute($sample,"noc_info"); - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_sample_topology_info ($emulate,$sample); #wait for done add_info($info, "wait for done\n"); my $done=0; @@ -395,4 +391,4 @@ sub read_pack_gen{ update_result ($emulate,$sample,"exe_time_result",$ratio_in,$clk_counter); return 1; } -1; \ No newline at end of file +1; diff --git a/mpsoc/perl_gui/lib/perl/emulator.pl b/mpsoc/perl_gui/lib/perl/emulator.pl index 7338905..31c6e95 100755 --- a/mpsoc/perl_gui/lib/perl/emulator.pl +++ b/mpsoc/perl_gui/lib/perl/emulator.pl @@ -279,7 +279,7 @@ sub gen_emulation_column { my $temp = __PACKAGE__->new(); my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my ($topology, $T1, $T2, $T3, $T4, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); my $ref=$emulate->object_get_attribute($sample,"noc_info"); if (defined $ref){ my %noc_info= %$ref; @@ -293,10 +293,11 @@ sub gen_emulation_column { $traffic-> signal_connect("clicked" => sub{ my $st = ($mode eq "simulate" )? check_sim_sample($emulate,$sample,$info) : check_sample($emulate,$sample,$info); return if $st==0; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); + my ($topology, $T1, $T2, $T3, $T4, $V, $Fpay) = get_sample_emulation_param($emulate,$sample); $emulate->object_add_attribute('noc_param','T1',$T1); $emulate->object_add_attribute('noc_param','T2',$T2); $emulate->object_add_attribute('noc_param','T3',$T3); + $emulate->object_add_attribute('noc_param','T4',$T4); $emulate->object_add_attribute('noc_param','TOPOLOGY',$topology); my $pattern=""; my $traffictype=$emulate->object_get_attribute($sample,"TRAFFIC_TYPE"); diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index cb4217c..aa9704a 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -51,19 +51,18 @@ sub initial_default_param{ ############# # get_soc_lists ############ - sub get_soc_list { my ($mpsoc,$info)=@_; - my $path=$mpsoc->object_get_attribute('setting','soc_path'); + my $path=$mpsoc->object_get_attribute('setting','soc_path'); $path =~ s/ /\\ /g; my @socs; my @files = glob "$path/*.SOC"; for my $p (@files){ - my ($soc,$r,$err) = regen_object($p); - # Read - if ($r){ + my ($soc,$r,$err) = regen_object($p); + # Read + if ($r){ add_info($info,"**Error reading $p file: $err\n"); - next; + next; } my $top=$soc->soc_get_top(); if (defined $top){ @@ -79,12 +78,10 @@ sub get_soc_list { copy_back_custom_soc_param($top,$old_top) if(defined $old_top); $mpsoc->mpsoc_add_soc($name,$top); #print" $name\n"; - } + } } - } }# files - # initial default soc parameter initial_default_param($mpsoc); return $mpsoc->mpsoc_get_soc_list; @@ -97,8 +94,7 @@ sub copy_back_custom_soc_param{ my %l =$old->top_get_custom_soc_param($tile); $new->top_add_custom_soc_param (\%l,$tile); } - -} +} sub get_NI_instance_list { my $top=shift; @@ -108,7 +104,7 @@ sub get_NI_instance_list { #check if the soc has ni port foreach my $instanc(@instance_list){ my $category=$top->top_get_def_of_instance($instanc,'category'); - push(@nis,$instanc) if($category eq 'NoC') ; + push(@nis,$instanc) if($category eq 'NoC') ; } return @nis; } @@ -116,29 +112,21 @@ sub get_NI_instance_list { #################### # get_conflict_decision ########################### - - sub get_conflict_decision{ my ($mpsoc,$name,$inserted,$conflicts,$msg)=@_; $msg="\tThe inserted tile number(s) have been mapped previously to \n\t\t\"$msg\".\n\tDo you want to remove the conflicted tiles number(s) in newly \n\tinserted range or remove them from the previous ones? "; - my $wind=def_popwin_size(10,30,"warning",'percent'); my $label= gen_label_in_left($msg); my $table=def_table(2,6,FALSE); $table->attach_defaults ($label , 0, 6, 0,1); $wind->add($table); - my $b1= def_button("Remove Previous"); my $b2= def_button("Remove Current"); my $b3= def_button("Cancel"); - $table->attach ($b1 , 0, 1, 1,2,'fill','fill',2,2); $table->attach ($b2 , 3, 4, 1,2,'fill','fill',2,2); $table->attach ($b3 , 5, 6, 1,2,'fill','fill',2,2); - - $wind->show_all(); - $b1->signal_connect( "clicked"=> sub{ #Remove Previous my @socs=$mpsoc->mpsoc_get_soc_list(); foreach my $p (@socs){ @@ -153,9 +141,7 @@ sub get_conflict_decision{ #set_gui_status($mpsoc,"ref",1); $wind->destroy(); get_soc_parameter_setting($mpsoc,$name, $inserted)if(defined $inserted ); - }); - $b2->signal_connect( "clicked"=> sub{#Remove Current my @new= get_diff_array($inserted,$conflicts); $mpsoc->mpsoc_add_soc_tiles_num($name,\@new) if(scalar @new ); @@ -163,9 +149,7 @@ sub get_conflict_decision{ #set_gui_status($mpsoc,"ref",1); $wind->destroy(); get_soc_parameter_setting($mpsoc,$name, \@new) if(scalar @new ); - }); - $b3->signal_connect( "clicked"=> sub{ $wind->destroy(); @@ -180,7 +164,6 @@ sub check_inserted_ip_nums{ my ($mpsoc,$name,$str)=@_; my @all_num=(); $str= remove_all_white_spaces ($str); - if($str !~ /^[0-9.:,]+$/){ message_dialog ("The Ip numbers contains invalid character" ); return; } my @chunks=split(/\s*,\s*/,$str); foreach my $p (@chunks){ @@ -195,16 +178,12 @@ sub check_inserted_ip_nums{ for (my $i=$min; $i<=$max; $i++){ if ( grep( /^$i$/, @all_num ) ) { message_dialog ("Multiple definition for IP number $i in $p" ); return; } push(@all_num,$i); - } - }else{message_dialog ("invalid range: [$p]" ); return; } - } #check if range does not exceed the tile numbers my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); my $max_tile_num=$NE; - my @f=sort { $a <=> $b } @all_num; my @l; foreach my $num (@f){ @@ -212,12 +191,9 @@ sub check_inserted_ip_nums{ } @all_num=@l; - #check if any ip number exists in the rest my $conflicts_msg; my @conflicts; - - my @socs=$mpsoc->mpsoc_get_soc_list(); foreach my $p (@socs){ if($p ne $name){ @@ -231,9 +207,7 @@ sub check_inserted_ip_nums{ }#if } if (defined $conflicts_msg) { - get_conflict_decision($mpsoc,$name,\@all_num,\@conflicts,$conflicts_msg); - - + get_conflict_decision($mpsoc,$name,\@all_num,\@conflicts,$conflicts_msg); }else { #save the entered ips if( scalar @all_num>0){ @@ -253,10 +227,6 @@ sub check_inserted_ip_nums{ ################# # get_soc_parameter_setting ################ - - - - sub get_soc_parameter_setting{ my ($mpsoc,$soc_name,$tiles_ref)=@_; my @tiles = @{$tiles_ref} if defined ($tiles_ref); @@ -272,18 +242,15 @@ sub get_soc_parameter_setting_table{ my ($mpsoc,$soc_name,$window,$tiles_ref)=@_; my @tiles; @tiles = @{$tiles_ref} if defined ($tiles_ref); - # my $window = def_popwin_size(40,40,"Parameter setting for $soc_name mapped to tile(@tiles) ",'percent'); + # my $window = def_popwin_size(40,40,"Parameter setting for $soc_name mapped to tile(@tiles) ",'percent'); my $table = def_table(10, 7, FALSE); - my $scrolled_win = add_widget_to_scrolled_win($table); my $row=0; my $column=0; my $top=$mpsoc->mpsoc_get_soc($soc_name); - #read soc parameters my %param_value=(scalar @tiles ==1 ) ? $top->top_get_custom_soc_param($tiles[0]) : $top->top_get_default_soc_param(); $mpsoc->object_add_attribute('current_tile_param',undef,\%param_value); - my @insts=$top->top_get_all_instances(); my @exceptions=get_NI_instance_list($top); @insts=get_diff_array(\@insts,\@exceptions); @@ -295,82 +262,68 @@ sub get_soc_parameter_setting_table{ $default= $param_value{$p} if(defined $param_value{$p}); ($row,$column)=add_param_widget($mpsoc,$p,$p, $default,$type,$content,$info, $table,$row,$column,$show,'current_tile_param',undef,undef,'vertical'); } - - - # if ($type eq "Entry"){ - # my $entry=gen_entry($param_value{$p}); - # $table->attach_defaults ($entry, 3, 6, $row, $row+1); - # $entry-> signal_connect("changed" => sub{$param_value{$p}=$entry->get_text();}); - # } - # elsif ($type eq "Combo-box"){ - # my @combo_list=split(/\s*,\s*/,$content); - # my $pos=get_item_pos($param_value{$p}, @combo_list) if(defined $param_value{$p}); - # my $combo=gen_combo(\@combo_list, $pos); - # $table->attach_defaults ($combo, 3, 6, $row, $row+1); - # $combo-> signal_connect("changed" => sub{$param_value{$p}=$combo->get_active_text();}); - # - # } - # elsif ($type eq "Spin-button"){ - # my ($min,$max,$step)=split(/\s*,\s*/,$content); - # $param_value{$p}=~ s/\D//g; - # $min=~ s/\D//g; - # $max=~ s/\D//g; - # $step=~ s/\D//g; - # my $spin=gen_spin($min,$max,$step); - # $spin->set_value($param_value{$p}); - # $table->attach_defaults ($spin, 3, 4, $row, $row+1); - # $spin-> signal_connect("value_changed" => sub{$param_value{$p}=$spin->get_value_as_int();}); - # - # # $box=def_label_spin_help_box ($param,$info, $value,$min,$max,$step, 2); - # } - # my $label =gen_label_in_center($p); - # $table->attach_defaults ($label, 0, 3, $row, $row+1); - # if (defined $info){ - # my $info_button=def_image_button('icons/help.png'); - # $table->attach_defaults ($info_button, 6, 7, $row, $row+1); - # $info_button->signal_connect('clicked'=>sub{ - # message_dialog($info); - # - # }); - # - # } - # $row++; - # - # - # } + # if ($type eq "Entry"){ + # my $entry=gen_entry($param_value{$p}); + # $table->attach_defaults ($entry, 3, 6, $row, $row+1); + # $entry-> signal_connect("changed" => sub{$param_value{$p}=$entry->get_text();}); + # } + # elsif ($type eq "Combo-box"){ + # my @combo_list=split(/\s*,\s*/,$content); + # my $pos=get_item_pos($param_value{$p}, @combo_list) if(defined $param_value{$p}); + # my $combo=gen_combo(\@combo_list, $pos); + # $table->attach_defaults ($combo, 3, 6, $row, $row+1); + # $combo-> signal_connect("changed" => sub{$param_value{$p}=$combo->get_active_text();}); + # + # } + # elsif ($type eq "Spin-button"){ + # my ($min,$max,$step)=split(/\s*,\s*/,$content); + # $param_value{$p}=~ s/\D//g; + # $min=~ s/\D//g; + # $max=~ s/\D//g; + # $step=~ s/\D//g; + # my $spin=gen_spin($min,$max,$step); + # $spin->set_value($param_value{$p}); + # $table->attach_defaults ($spin, 3, 4, $row, $row+1); + # $spin-> signal_connect("value_changed" => sub{$param_value{$p}=$spin->get_value_as_int();}); + # + # # $box=def_label_spin_help_box ($param,$info, $value,$min,$max,$step, 2); + # } + # my $label =gen_label_in_center($p); + # $table->attach_defaults ($label, 0, 3, $row, $row+1); + # if (defined $info){ + # my $info_button=def_image_button('icons/help.png'); + # $table->attach_defaults ($info_button, 6, 7, $row, $row+1); + # $info_button->signal_connect('clicked'=>sub{ + # message_dialog($info); + # + # }); + # } + # $row++; + # } } my $ok = def_image_button('icons/select.png','OK'); my $okbox=def_hbox(TRUE,0); $okbox->pack_start($ok, FALSE, FALSE,0); - - my $mtable = def_table(10, 1, TRUE); - $mtable->attach_defaults($scrolled_win,0,1,0,9); $mtable->attach_defaults($okbox,0,1,9,10); - - - $ok-> signal_connect("clicked" => sub{ $window->destroy if(defined $window); #save new values my $ref=$mpsoc->object_get_attribute('current_tile_param'); %param_value=%{$ref}; - - # if(!defined $tile ) { + # if(!defined $tile ) { # $top->top_add_default_soc_param(\%param_value); # $mpsoc->object_add_attribute('soc_param',"default",\%param_value); - # } - # else { - foreach my $tile (@tiles){ + # } + # else { + foreach my $tile (@tiles){ $top->top_add_custom_soc_param(\%param_value,$tile); $mpsoc->object_add_attribute('soc_param',"custom_${soc_name}",\%param_value); } $mpsoc->object_add_attribute('current_tile_param',undef,undef); set_gui_status($mpsoc,"refresh_soc",1); - - }); $mtable->show_all(); return $mtable; @@ -379,7 +332,6 @@ sub get_soc_parameter_setting_table{ ################ # tile_set_widget ################ - sub tile_set_widget{ my ($mpsoc,$soc_name,$num,$table,$show,$row)=@_; #my $label=gen_label_in_left($soc); @@ -391,11 +343,9 @@ sub tile_set_widget{ my $set= def_image_button('icons/right.png'); my $remove= def_image_button('icons/cancel.png'); #my $setting= def_image_button('icons/setting.png','setting'); - - my $button = def_colored_button($soc_name,$num); $button->signal_connect("clicked"=> sub{ - # get_soc_parameter_setting($mpsoc,$soc_name,undef); + # get_soc_parameter_setting($mpsoc,$soc_name,undef); }); $set->signal_connect("clicked"=> sub{ @@ -406,39 +356,25 @@ sub tile_set_widget{ get_soc_parameter_setting($mpsoc,$soc_name,\@all_num); } }); - $remove->signal_connect("clicked"=> sub{ $mpsoc->mpsoc_remove_soc($soc_name); set_gui_status($mpsoc,"ref",1); }); - - -if($show){ - $table->attach ( $button, 0, 1, $row,$row+1,'fill','fill',2,2); - $table->attach ( $remove, 1, 2, $row,$row+1,'fill','shrink',2,2); - $table->attach ( $entry , 2, 3, $row,$row+1,'fill','shrink',2,2); - $table->attach ( $set, 3, 4, $row,$row+1,'fill','shrink',2,2); - - - - $row++; -} - + if($show){ + $table->attach ( $button, 0, 1, $row,$row+1,'fill','fill',2,2); + $table->attach ( $remove, 1, 2, $row,$row+1,'fill','shrink',2,2); + $table->attach ( $entry , 2, 3, $row,$row+1,'fill','shrink',2,2); + $table->attach ( $set, 3, 4, $row,$row+1,'fill','shrink',2,2); + $row++; + } return $row; - - -} - - - +} ################## # defualt_tilles_setting ################### - sub defualt_tilles_setting { my ($mpsoc,$table,$show,$row,$info)=@_; - #title my $separator1 = gen_Hsep(); my $separator2 = gen_Hsep(); @@ -448,15 +384,11 @@ sub defualt_tilles_setting { $box1->pack_start( $title2, FALSE, FALSE, 3); $box1->pack_start( $separator2, FALSE, FALSE, 3); if($show){$table->attach_defaults ($box1 ,0,4, $row,$row+1);$row++;} - - my $label = gen_label_in_left("Tiles path:"); my $entry = gen_entry(); my $browse= def_image_button("icons/browse.png"); my $file= $mpsoc->object_get_attribute('setting','soc_path'); if(defined $file){$entry->set_text($file);} - - $browse->signal_connect("clicked"=> sub{ my $entry_ref=$_[1]; my $file; @@ -468,13 +400,10 @@ sub defualt_tilles_setting { $mpsoc->mpsoc_remove_all_soc(); set_gui_status($mpsoc,"ref",1); #check_input_file($file,$socgen,$info); - #print "file = $file\n"; + #print "file = $file\n"; } $dialog->destroy; - } , \$entry); - - $entry->signal_connect("activate"=>sub{ my $file_name=$entry->get_text(); $mpsoc->object_add_attribute('setting','soc_path',$file_name); @@ -482,9 +411,6 @@ sub defualt_tilles_setting { set_gui_status($mpsoc,"ref",1); #check_input_file($file_name,$socgen,$info); }); - - - if($show){ my $tmp=gen_label_in_left(" "); $table->attach ($label, 0, 1 , $row,$row+1,'fill','shrink',2,2); @@ -493,20 +419,12 @@ sub defualt_tilles_setting { $table->attach ($browse, 3, 4, $row,$row+1,'fill','shrink',2,2); $row++; } - - - my @socs=$mpsoc->mpsoc_get_soc_list(); - if( scalar @socs == 0){ + if( scalar @socs == 0){ @socs=get_soc_list($mpsoc,$info); - } @socs=$mpsoc->mpsoc_get_soc_list(); - - - my $lab1=gen_label_in_center(' Tile name'); - my $lab2=gen_label_help('Define the tile numbers that each IP is mapped to. you can add individual numbers or ranges as follow e.g. individual numbers: 5,6,7,8,9,10 @@ -516,25 +434,18 @@ sub defualt_tilles_setting { $table->attach_defaults ($lab1 ,0,1, $row,$row+1); $table->attach_defaults ($lab2 ,2,3, $row,$row+1);$row++; } - my $soc_num=0; - foreach my $soc_name (@socs){ + foreach my $soc_name (@socs){ $row=tile_set_widget ($mpsoc,$soc_name,$soc_num,$table,$show,$row); - $soc_num++; - - } + $soc_num++; + } return $row; - } - - ####################### # noc_config ###################### - - sub noc_topology_setting_gui { my ($mpsoc,$table,$txview,$row,$show_noc,$noc_id)=@_; my $noc_param="noc_param$noc_id"; @@ -543,15 +454,13 @@ sub noc_topology_setting_gui { my $label='Topology'; my $param='TOPOLOGY'; my $default='"MESH"'; - my $content='"MESH","FMESH","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM"'; + my $content='"MESH","FMESH","MESH_3D","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM"'; my $type='Combo-box'; my $info="Specifies the NoC topology. Options include $content"; $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); - my $topology=$mpsoc->object_get_attribute($noc_param,'TOPOLOGY'); - if($topology ne '"CUSTOM"' ){ #topology T1 parameter $label= @@ -560,80 +469,83 @@ sub noc_topology_setting_gui { $param= 'T1'; $default= '2'; $content= - ($topology eq '"MESH"' || $topology eq '"TORUS"') ? '2,16,1': + ($topology eq '"MESH"' || $topology eq '"TORUS"' || $topology eq '"MESH_3D"') ? '2,16,1': ($topology eq '"FMESH"')? '1,16,1': ($topology eq '"FATTREE"' || $topology eq '"TREE"' )? '2,6,1':'2,64,1'; $info= ($topology eq '"FATTREE"' || $topology eq '"TREE"' )? 'number of last level individual router`s endpoints.' :'Number of NoC routers in row (X dimension)'; $type= 'Spin-button'; - $noc_param_comment{$param}="$info"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); - #Topology T2 parameter - if($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"TORUS"' || $topology eq '"FATTREE"' || $topology eq '"TREE"' ) { + if($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"TORUS"' || $topology eq '"FATTREE"' || $topology eq '"TREE"' || $topology eq '"MESH_3D"') { $label= ($topology eq '"FATTREE"' || $topology eq '"TREE"')? 'L' :'Routers per column'; $param= 'T2'; $default='2'; $content= ($topology eq '"FMESH"')? '1,16,1': '2,16,1'; $info= ($topology eq '"FATTREE"' || $topology eq '"TREE"')? 'Fattree layer number (The height of FT)':'Number of NoC routers in column (Y dimension)'; $type= 'Spin-button'; - $noc_param_comment{$param}="$info"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); } else { - $mpsoc->object_add_attribute($noc_param,'T2',1); + $mpsoc->object_add_attribute($noc_param,'T2',1); } #Topology T3 parameter - if($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"TORUS"' || $topology eq '"RING"' || $topology eq '"LINE"') { - $label="Router's endpoint number"; + if($topology eq '"MESH_3D"') { + $label= 'Routers per layer'; $param= 'T3'; $default='1'; + $content= '1,16,1'; + $info= 'Number of NoC layers (Z dimension)'; + $type= 'Spin-button'; + $noc_param_comment{$param}="$info"; + ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); + } else { + $mpsoc->object_add_attribute($noc_param,'T4',1); + $mpsoc->object_add_attribute_order($noc_param,"T4"); + } + #Topology T3/T4 parameter + if($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"TORUS"' || $topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"MESH_3D"') { + $label="Router's endpoint number"; + $param= $topology eq '"MESH_3D"' ? 'T4' : 'T3'; + $default='1'; $content='1,4,1'; $info= "Number of endpoints per router. In $topology topology, each router can have up to 4 endpoint processing tile."; $type= 'Spin-button'; - $noc_param_comment{$param}="$info"; + $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); } - - }else{#its a custom Topology ($row,$coltmp)=config_custom_topology_gui($mpsoc,$table,$txview,$row,$noc_id); } return ($row,$coltmp); - } - sub noc_config{ my ($mpsoc,$table,$txview,$noc_id)=@_; $noc_id = "" if(!defined $noc_id); my $noc_param="noc_param$noc_id"; my $noc_type="noc_type$noc_id"; - #title my $row=0; my $title=gen_label_in_center("NoC Configuration"); $table->attach ($title , 0, 4, $row, $row+1,'expand','shrink',2,2); $row++; add_Hsep_to_table ($table,0,4,$row); $row++; - my $label; my $param; my $default; my $type; my $content; my $info; - - - #parameter start my $b1; my $show_noc=$mpsoc->object_get_attribute('setting','show_noc_setting'); if(!defined $show_noc){ $show_noc=1; $mpsoc->object_add_attribute('setting','show_noc_setting',$show_noc); - } if($show_noc == 0){ $b1= def_image_button("icons/down.png","NoC Parameters"); @@ -642,9 +554,7 @@ sub noc_config{ $table->attach ( $b1 , 0, 2, $row,$row+1,'fill','shrink',2,2); $row++; } - my $coltmp=0; - #NoC_ID $label='NoC ID'; $param='NOC_ID'; @@ -654,7 +564,6 @@ sub noc_config{ $info="Unique identifier for the NoC. Will be modified by phy_noc_gen.pl script."; $noc_param_comment{'NOC_ID'}="Unique identifier for the NoC. Will be modified by phy_noc_gen.pl script"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param,1); - #Router type $label='Router Type'; $param='ROUTER_TYPE'; @@ -665,11 +574,8 @@ sub noc_config{ VC-based routers offer higher performance, fully adaptive routing and traffic isolation for different packet classes."; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_type,1); my $router_type=$mpsoc->object_get_attribute($noc_type,"ROUTER_TYPE"); - - ($row,$coltmp) =noc_topology_setting_gui($mpsoc,$table,$txview,$row,$show_noc,$noc_id); my $topology=$mpsoc->object_get_attribute($noc_param,'TOPOLOGY'); - #VC number per port if($router_type eq '"VC_BASED"'){ my $v=$mpsoc->object_get_attribute($noc_param,'V'); @@ -697,8 +603,6 @@ sub noc_config{ $info=($router_type eq '"VC_BASED"')? 'Buffer queue size per VC in flits' : 'Buffer queue size in flits'; $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,undef); - - #Local port buffer width per VC $label=($router_type eq '"VC_BASED"')? 'Local port Buffer flits per VC': "Local Port Buffer flits"; $param='LB'; @@ -715,7 +619,6 @@ sub noc_config{ }else{ $mpsoc->object_add_attribute($noc_param,'LB','B'); } - #packet payload width $label='Payload width'; $param='Fpay'; @@ -725,42 +628,46 @@ sub noc_config{ $info="The packet payload width in bits"; $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info,$table,$row,undef,$show_noc,$noc_param,undef); - -if($topology ne '"CUSTOM"' ){ - #routing algorithm - $label='Routing Algorithm'; - $param="ROUTE_NAME"; - $type="Combo-box"; - if($router_type eq '"VC_BASED"'){ - $content=($topology eq '"MESH"' || $topology eq '"FMESH"')? '"XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN","FULL_ADPT"' : - ($topology eq '"TORUS"')? '"TRANC_XY","TRANC_WEST_FIRST","TRANC_NORTH_LAST","TRANC_NEGETIVE_FIRST","TRANC_FULL_ADPT"': - ($topology eq '"RING"')? '"TRANC_XY"' : - ($topology eq '"LINE"')? '"XY"': - ($topology eq '"FATTREE"')? '"NCA_RND_UP","NCA_STRAIGHT_UP","NCA_DST_UP"': - ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; - }else{ - $content=($topology eq '"MESH"' || $topology eq '"FMESH"')? '"XY","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN"' : - ($topology eq '"TORUS"')? '"TRANC_XY","TRANC_WEST_FIRST","TRANC_NORTH_LAST","TRANC_NEGETIVE_FIRST"': - ($topology eq '"RING"')? '"TRANC_XY"' : - ($topology eq '"LINE"')? '"XY"': - ($topology eq '"FATTREE"')? '"NCA_RND_UP","NCA_STRAIGHT_UP","NCA_DST_UP"' : - ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; - } - $default=($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"LINE"' )? '"XY"': - ($topology eq '"TORUS"'|| $topology eq '"RING"')? '"TRANC_XY"' : - ($topology eq '"FATTREE"')? '"NCA_STRAIGHT_UP"' : - ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; - + + if($topology ne '"CUSTOM"' ){ + #routing algorithm + $label='Routing Algorithm'; + $param="ROUTE_NAME"; + $type="Combo-box"; + if($router_type eq '"VC_BASED"'){ + $content= + ($topology eq '"MESH_3D"') ? '"DOR"' : + ($topology eq '"MESH"' || $topology eq '"FMESH"')? '"DOR","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN","FULL_ADPT"' : + ($topology eq '"TORUS"')? '"TRANC_DOR","TRANC_WEST_FIRST","TRANC_NORTH_LAST","TRANC_NEGETIVE_FIRST","TRANC_FULL_ADPT"': + ($topology eq '"RING"')? '"TRANC_DOR"' : + ($topology eq '"LINE"')? '"DOR"': + ($topology eq '"FATTREE"')? '"NCA_RND_UP","NCA_STRAIGHT_UP","NCA_DST_UP"': + ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; + }else{ + $content= + ($topology eq '"MESH_3D"') ? '"DOR"' : + ($topology eq '"MESH"' || $topology eq '"FMESH"')? '"DOR","WEST_FIRST","NORTH_LAST","NEGETIVE_FIRST","ODD_EVEN"' : + ($topology eq '"TORUS"')? '"TRANC_DOR","TRANC_WEST_FIRST","TRANC_NORTH_LAST","TRANC_NEGETIVE_FIRST"': + ($topology eq '"RING"')? '"TRANC_DOR"' : + ($topology eq '"LINE"')? '"DOR"': + ($topology eq '"FATTREE"')? '"NCA_RND_UP","NCA_STRAIGHT_UP","NCA_DST_UP"' : + ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; + } + $default= + ($topology eq '"MESH"' || $topology eq '"FMESH"' || $topology eq '"LINE"'|| $topology eq '"MESH_3D"' )? '"DOR"': + ($topology eq '"TORUS"'|| $topology eq '"RING"')? '"TRANC_DOR"' : + ($topology eq '"FATTREE"')? '"NCA_STRAIGHT_UP"' : + ($topology eq '"TREE"')? '"NCA"' : '"UNKNOWN"'; my $info_mesh="Select the routing algorithm. Options are: - - XY: Deterministic routing (Dimension-Order Routing, DoR). + - DOR: Dimension-Order Deterministic routing (XY). - WEST_FIRST, NORTH_LAST, NEGATIVE_FIRST, ODD_EVEN: Partially adaptive routing algorithms based on turn model restrictions. - FULL_ADPT: Fully adaptive routing based on Duato's algorithm; requires at least two virtual channels (VCs) per port."; my $info_fat="Nearest common ancestor (NCA) where the up port is selected randomly (RND), based on destination endpoint address (DST) or it is the top port that is located in front of the port which has received the packet (STRAIGHT) "; - - $info=($topology eq '"FATTREE"')? $info_fat : - ($topology eq '"TREE"') ? "Nearest common ancestor": $info_mesh; + $info= + ($topology eq '"FATTREE"')? $info_fat : + ($topology eq '"TREE"') ? "Nearest common ancestor": $info_mesh; $noc_param_comment{$param}="$info options are $content"; my $show_routing =($topology eq '"STAR"' )? 0 : $show_noc; @@ -781,7 +688,6 @@ sub noc_config{ $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,1,$noc_param,1); } - #PCK_TYPE $label='Packet type'; $param='PCK_TYPE'; @@ -795,13 +701,9 @@ sub noc_config{ b) Two-flit: Separate header and tail flits. c) Multi-flit: Header, one or more body flits, and a tail flit."; $noc_param_comment{$param}="$info"; - ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); - my $pck_type=$mpsoc->object_get_attribute($noc_param,'PCK_TYPE'); - if($pck_type eq '"MULTI_FLIT"'){ - #MIN_PCK_SIZE # 2 //minimum packet size in flits. The minimum value is 1. $label='Minimum packet size'; @@ -818,7 +720,6 @@ sub noc_config{ }else{ $mpsoc->object_add_attribute($noc_param,'MIN_PCK_SIZE',1); } - # BYTE_EN $label='Byte Enable'; $param='BYTE_EN'; @@ -831,7 +732,6 @@ sub noc_config{ $type="Combo-box"; $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param); - #CAST_TYPE $label='Casting Type'; $param='CAST_TYPE'; @@ -925,7 +825,7 @@ sub noc_config{ from neighboring routers. Please refer to the usere manual for more information"; $noc_param_comment{$param}="$info"; $default=3; - if($topology ne '"CUSTOM"' && $route ne '"XY"' && $route ne '"TRANC_XY"' ){ + if($topology ne '"CUSTOM"' && $route ne '"DOR"' && $route ne '"TRANC_DOR"' ){ ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); } else { ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param,undef); @@ -933,7 +833,7 @@ sub noc_config{ #Fully adaptive routing setting my $v=$mpsoc->object_get_attribute($noc_param,"V"); - $label="Select Escap VC"; + $label="Select Escap VC"; $param="ESCAP_VC_MASK"; $type="Check-box"; $content=$v; @@ -960,8 +860,6 @@ sub noc_config{ $type='Combo-box'; $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,undef); - - #vc/sw allocator type $label = 'VC/SW combination type'; $param='COMBINATION_TYPE'; @@ -998,8 +896,6 @@ sub noc_config{ $content='0,16,1'; $type='Spin-button'; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,5); - - my $class=$mpsoc->object_get_attribute($noc_param,"C"); my $v=$mpsoc->object_get_attribute($noc_param,"V"); $default= "$v\'b"; @@ -1016,9 +912,7 @@ sub noc_config{ $info="Select the permitted VCs which the message class $i can be sent via them."; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,'class_param',undef); } - }#($router_type eq '"VC_BASED"') - #simulation debuge enable $label='Debug enable'; $param='DEBUG_EN'; @@ -1075,9 +969,6 @@ sub noc_config{ $noc_param_comment{$param}="$info"; $type= 'Spin-button'; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$wrra_show,$noc_param,undef); - - - $label='Self loop enable'; $param='SELF_LOOP_EN'; $default='0'; @@ -1113,8 +1004,7 @@ sub noc_config{ $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$adv_set,$noc_param,1); $noc_param_comment{$param}="$info"; - - + #VC_CONFIG_TABLE my $hetero_en=$mpsoc->object_get_attribute($noc_param,'HETERO_VC'); $label='Heterogeneous VC setting'; @@ -1146,12 +1036,9 @@ sub noc_config{ $mpsoc->object_add_attribute($noc_param,"MAX_PORT",$MAX_P); $row=hetero_vc_widget($mpsoc,$row,$NR,$MAX_P,$label,$info,$table,$noc_id,$param,$v); } - - $mpsoc->object_add_attribute_order($noc_param,"MAX_ROUTER"); $mpsoc->object_add_attribute_order($noc_param,"MAX_PORT"); $mpsoc->object_add_attribute_order($noc_param,$param); - if($show_noc == 1){ $b1= def_image_button("icons/up.png","NoC Parameters"); $table->attach ( $b1 , 0, 2, $row,$row+1,'fill','shrink',2,2); @@ -1162,10 +1049,7 @@ sub noc_config{ $mpsoc->object_add_attribute('setting','show_noc_setting',$show_noc); set_gui_status($mpsoc,"ref",1); }); - - #other fixed parameters - # AVC_ATOMIC_EN $label='AVC_ATOMIC_EN'; $param='AVC_ATOMIC_EN'; @@ -1175,10 +1059,7 @@ sub noc_config{ $type="Combo-box"; $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,0,$noc_param); - - $mpsoc->object_add_attribute('noc_param_comments',undef,\%noc_param_comment); - return $row; } @@ -1206,7 +1087,6 @@ sub set_hetero_vc_list{ my $row=0; my $col=0; my $init = $mpsoc->object_get_attribute($noc_param,$param); - my $label = "$param="; my ($Ebox,$entry) = def_h_labeled_entry ($label); $entry->set_sensitive (FALSE); @@ -1225,7 +1105,6 @@ sub set_hetero_vc_list{ for(my $r=0;$r<$nr;$r++){ my $label= gen_label_in_center("R$r"); $table->attach ($label , $col, $col+4, $row,$row+1,'fill','shrink',2,2);$col+=4; - for(my $p=0;$p<$np;$p++){ my $w; ($row,$col,$w)=add_param_widget ($mpsoc,undef,"R$r-P$p", $v,"Combo-box",$content,undef, $table,$row,$col,1,$vc_param,undef,undef,"horizental"); @@ -1281,27 +1160,20 @@ sub set_multicast_list{ my $init = $mpsoc->object_get_attribute($noc_param,"MCAST_ENDP_LIST"); $init =~ s/'h//g; my @arr= reverse split (//, $init); - - my $label = "Multicast Node list (hex fromat)"; my ($Ebox,$entry) = def_h_labeled_entry ($label); $entry->set_sensitive (FALSE); - my @sel_options= ("Select","All","None","2n","3n","4n","2n+1","3n+1","3n+2","4n+1","4n+2","4n+3"); my $combo= gen_combo(\@sel_options, 0); $table->attach ($combo , 0, 1, $row,$row+1,'fill','shrink',2,2); #get the number of endpoints my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc,$noc_id); my @check; - - - my $sel_val="Init"; for (my $i=0; $i<$NE; $i++){ if($i%10 == 0){ $row++;$col=0;} my $box; my $l=$NE -$i-1; - my $char = $arr[$l/4]; $char=0 if (!defined $char); my $hex = hex($char); @@ -1309,21 +1181,17 @@ sub set_multicast_list{ ($box,$check[$l])=def_h_labeled_checkbutton("$l"); $table->attach ($box , $col, $col+1, $row,$row+1,'fill','shrink',2,2); $col++; - if($bit==1){ $check[$l]->set_active(TRUE); } - $check[$l]-> signal_connect("toggled" => sub{ get_multicast_val ($mpsoc,$entry,$NE,@check)if($sel_val eq "Select"); }); } $row++; $col=0; - $sel_val="Select"; get_multicast_val ($mpsoc,$entry,$NE,@check); - $combo-> signal_connect("changed" => sub{ $sel_val=$combo->get_active_text(); my $n=1; @@ -1341,25 +1209,17 @@ sub set_multicast_list{ $r=0; $n=1 if(!defined $n); } - for (my $i=0; $i<$NE; $i++){ if($i % $n == $r){ $check[$i]->set_active(TRUE);} } $combo->set_active(0); get_multicast_val ($mpsoc,$entry,$NE,@check); - }); - - - $table->attach ($Ebox , 0, 10, $row,$row+1,'fill','shrink',2,2);$row++; - my $main_table=def_table(10,10,FALSE); - my $ok = def_image_button('icons/select.png','OK'); $main_table->attach_defaults ($table , 0, 12, 0,11); $main_table->attach ($ok,5, 6, 11,12,'shrink','shrink',0,0); - $ok->signal_connect('clicked', sub { my $s=get_multicast_val ($mpsoc,$entry,$NE,@check); my $n=$entry->get_text( ); @@ -1368,10 +1228,6 @@ sub set_multicast_list{ set_gui_status($mpsoc,"ref",1); $window->destroy; }); - - - - my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_multicast'); add_widget_to_scrolled_win($main_table,$scrolled_win); $window->add($scrolled_win); @@ -1391,17 +1247,14 @@ sub get_multicast_val { $h=0; } } - $n="$h".$n if($NE%4!=0); $n="'h".$n; $entry->set_text("$n"); return $s; - } ############# # config_custom_topology_gui ############ - sub config_custom_topology_gui{ my($mpsoc,$table,$txview,$row,$noc_id)=@_; my $noc_param="noc_param$noc_id"; @@ -1411,19 +1264,17 @@ sub config_custom_topology_gui{ my $file="$dir/param.obj"; unless (-f $file){ add_colored_info($txview,"No Custom topology find in $dir. You can define a Custom Topology using ProNoC Topology maker.\n",'red'); - return; - } + return; + } - my %param; + my %param; my ($pp,$r,$err) = regen_object($file ); - if ($r){ + if ($r){ add_colored_info($txview,"Error: cannot open $file file: $err\n",'red'); return; - } - + } %param=%{$pp}; my @topologies=sort keys %param; - my $label='Topology_name'; my $param='CUSTOM_TOPOLOGY_NAME'; my $default=$topologies[0]; @@ -1431,59 +1282,40 @@ sub config_custom_topology_gui{ my $type='Combo-box'; my $info="Custom topology name"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,1,$noc_param,1); - - my $topology_name=$mpsoc->object_get_attribute($noc_param,'CUSTOM_TOPOLOGY_NAME'); - - + my $topology_name=$mpsoc->object_get_attribute($noc_param,'CUSTOM_TOPOLOGY_NAME'); $label='Routing Algorithm'; $param="ROUTE_NAME"; $type="Combo-box"; - $content=$param{$topology_name}{'ROUTE_NAME'}; + $content=$param{$topology_name}{'ROUTE_NAME'}; my @rr=split(/\s*,\s*/,$content); $default=$rr[0]; $info="Select the routing algorithm"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,1,$noc_param,1); - - $mpsoc->object_add_attribute($noc_param,'T1',$param{$topology_name}{'T1'}); - $mpsoc->object_add_attribute($noc_param,'T2',$param{$topology_name}{'T2'}); - $mpsoc->object_add_attribute($noc_param,'T3',$param{$topology_name}{'T3'}); - $mpsoc->object_add_attribute('noc_connection','er_addr',$param{$topology_name}{'er_addr'}); - - + $mpsoc->object_add_attribute($noc_param,'T1',$param{$topology_name}{'T1'}); + $mpsoc->object_add_attribute($noc_param,'T2',$param{$topology_name}{'T2'}); + $mpsoc->object_add_attribute($noc_param,'T3',$param{$topology_name}{'T3'}); + $mpsoc->object_add_attribute($noc_param,'T4',$param{$topology_name}{'T4'}); + $mpsoc->object_add_attribute('noc_connection','er_addr',$param{$topology_name}{'er_addr'}); return ($row,$coltmp); - } - - - ####################### # get_config ###################### - sub get_config{ my ($mpsoc,$info)=@_; my $table=def_table(20,10,FALSE);# my ($row,$col,$homogeneous)=@_; - - #noc_setting my $row=noc_config ($mpsoc,$table,$info); - - #tiles setting my $tile_set; my $show=$mpsoc->object_get_attribute('setting','show_tile_setting'); - if($show == 0){ $tile_set= def_image_button("icons/down.png","Tiles setting"); $table->attach ( $tile_set , 0, 2, $row,$row+1,'fill','shrink',2,2); $row++; - } - $row=defualt_tilles_setting($mpsoc,$table,$show,$row,$info); - - #end tile setting if($show == 1){ $tile_set= def_image_button("icons/up.png","Tiles setting"); @@ -1494,10 +1326,7 @@ sub get_config{ $show=($show==1)?0:1; $mpsoc->object_add_attribute('setting','show_tile_setting',$show); set_gui_status($mpsoc,"ref",1); - - }); - my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'get_config_adj'); add_widget_to_scrolled_win($table,$scrolled_win); return $scrolled_win; @@ -1507,28 +1336,24 @@ sub get_config{ ############# # gen_all_tiles ########### - sub gen_all_tiles{ my ($mpsoc,$info, $hw_dir,$sw_dir)=@_; - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); + my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); - my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; + my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; my @generated_tiles; for (my $tile_num=0;$tile_num<$NE;$tile_num++){ #print "$tile_num\n"; my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($tile_num); next if(!defined $soc_name); - - - my $path=$mpsoc->object_get_attribute('setting','soc_path'); + my $path=$mpsoc->object_get_attribute('setting','soc_path'); $path=~ s/ /\\ /g; my $p = "$path/$soc_name.SOC"; my ($soc,$r,$err) = regen_object($p); - if ($r){ + if ($r){ show_info($info,"**Error reading $p file: $err\n"); next; } - #update core id $soc->object_add_attribute('global_param','CORE_ID',$tile_num); #update NoC param @@ -1540,13 +1365,11 @@ sub gen_all_tiles{ my %z; foreach my $p (sort keys %{$nocparam}){ $z{$p}="Parameter"; - } + } $soc->soc_add_instance_param_type($nis[0] ,\%z); #foreach my $p ( sort keys %nocparam ) { - - # print "$p = $nocparam{$p} \n"; + # print "$p = $nocparam{$p} \n"; #} - my $sw_path = "$sw_dir/tile$tile_num"; #print "$sw_path\n"; if( grep (/^$soc_name$/,@generated_tiles)){ # This soc is generated before only create the software file @@ -1555,24 +1378,19 @@ sub gen_all_tiles{ generate_soc($soc,$info,$target_dir,$hw_dir,$sw_path,0,1,"merge",1); move ("$hw_dir/$soc_name.sv","$hw_dir/tiles/"); my @tmp= ("$hw_dir/tiles/$soc_name.sv"); - add_to_project_file_list(\@tmp,"$hw_dir/tiles",$hw_dir); - - } + add_to_project_file_list(\@tmp,"$hw_dir/tiles",$hw_dir); + } }#$tile_num - - } ################ # generate_soc ################# - sub generate_soc_files{ my ($mpsoc,$soc,$info)=@_; my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); my $soc_name=$soc->object_get_attribute('soc_name'); - # copy all files in project work directory my $dir = Cwd::getcwd(); my $project_dir = abs_path("$dir/../../"); @@ -1581,95 +1399,73 @@ sub generate_soc_files{ mkpath("$target_dir/src_verilog/lib/",1,0755); mkpath("$target_dir/src_verilog/tiles/",1,0755); mkpath("$target_dir/sw",1,0755); - my ($file_v,$tmp)=soc_generate_verilog($soc,"$target_dir/sw",$info); - # Write object file open(FILE, ">lib/soc/$soc_name.SOC") || die "Can not open: $!"; print FILE perl_file_header("$soc_name.SOC"); print FILE Data::Dumper->Dump([\%$soc],['soc']); close(FILE) || die "Error closing file: $!"; - # Write verilog file open(FILE, ">lib/verilog/$soc_name.sv") || die "Can not open: $!"; print FILE $file_v; close(FILE) || die "Error closing file: $!"; - - - #copy hdl codes in src_verilog my ($hdl_ref,$warnings)= get_all_files_list($soc,"hdl_files"); my ($sim_ref,$warnings2)= get_all_files_list($soc,"hdl_files_ticked"); #hdl_ref-sim_ref my @n= get_diff_array($hdl_ref,$sim_ref); $hdl_ref=\@n; - - foreach my $f(@{$hdl_ref}){ + foreach my $f(@{$hdl_ref}){ my $n="$project_dir$f"; - if (-f "$n") { - copy ("$n","$target_dir/src_verilog/lib"); - }elsif(-f "$f" ){ - copy ("$f","$target_dir/src_verilog/lib"); - } + if (-f "$n") { + copy ("$n","$target_dir/src_verilog/lib"); + }elsif(-f "$f" ){ + copy ("$f","$target_dir/src_verilog/lib"); + } } - show_colored_info($info,$warnings,'green') if(defined $warnings); - - - - foreach my $f(@{$sim_ref}){ - my $n="$project_dir$f"; - if (-f "$n") { - copy ("$n","$target_dir/src_sim"); - }elsif(-f "$f" ){ - copy ("$f","$target_dir/src_sim"); - } - } - show_colored_info($info,$warnings2,'green') if(defined $warnings2); - - + show_colored_info($info,$warnings,'green') if(defined $warnings); + foreach my $f(@{$sim_ref}){ + my $n="$project_dir$f"; + if (-f "$n") { + copy ("$n","$target_dir/src_sim"); + }elsif(-f "$f" ){ + copy ("$f","$target_dir/src_sim"); + } + } + show_colored_info($info,$warnings2,'green') if(defined $warnings2); #save project hdl file/folder list my @new_file_ref; foreach my $f(@{$hdl_ref}){ - my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); - push(@new_file_ref,"$target_dir/src_verilog/lib/$name$suffix"); + my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); + push(@new_file_ref,"$target_dir/src_verilog/lib/$name$suffix"); } foreach my $f(@{$sim_ref}){ - my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); - push(@new_file_ref,"$target_dir/src_sim/$name$suffix"); + my ($name,$path,$suffix) = fileparse("$f",qr"\..[^.]*$"); + push(@new_file_ref,"$target_dir/src_sim/$name$suffix"); } open(FILE, ">$target_dir/src_verilog/file_list") || die "Can not open: $!"; print FILE Data::Dumper->Dump([\@new_file_ref],['files']); close(FILE) || die "Error closing file: $!"; - - - - move ("$dir/lib/verilog/$soc_name.sv","$target_dir/src_verilog/tiles/"); copy_noc_files($project_dir,"$target_dir/src_verilog/lib"); - - # Write header file generate_header_file($soc,$project_dir,$target_dir,$target_dir,$dir); #use File::Copy::Recursive qw(dircopy); #dircopy("$dir/../src_processor/aeMB/compiler","$target_dir/sw/") or die("$!\n"); my $msg="SoC \"$soc_name\" has been created successfully at $target_dir/ "; - return $msg; -} - + return $msg; +} sub generate_mpsoc_lib_file { my ($mpsoc,$info) = @_; my $tmp = $mpsoc; my $name=$mpsoc->object_get_attribute('mpsoc_name'); - open(FILE, ">lib/mpsoc/$name.MPSOC") || die "Can not open: $!"; print FILE perl_file_header("$name.MPSOC"); print FILE Data::Dumper->Dump([\%$tmp],['mpsoc']); close(FILE) || die "Error closing file: $!"; - #get_soc_list($mpsoc,$info); - -} +} sub check_mpsoc_name { my ($name,$info,$label)= @_; @@ -1686,63 +1482,53 @@ sub check_mpsoc_name { message_dialog("Please define the $label filed!"); return 1; } - return 0; + return 0; } ################ # generate_mpsoc ################# - sub generate_mpsoc{ my ($mpsoc,$info,$show_sucess_msg)=@_; my $name=$mpsoc->object_get_attribute('mpsoc_name'); return 0 if (check_mpsoc_name($name,$info)); - # make target dir my $dir = Cwd::getcwd(); my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$name"; my $hw_dir = "$target_dir/src_verilog"; my $sw_dir = "$target_dir/sw"; - # rmtree ($hw_dir); mkpath("$hw_dir",1,01777); mkpath("$hw_dir/lib/",1,0755); mkpath("$hw_dir/tiles",1,0755); mkpath("$sw_dir",1,0755); - #remove old rtl files that were copied by ProNoC my ($old_file_ref,$r,$err) = regen_object("$hw_dir/file_list"); if (defined $old_file_ref){ remove_file_and_folders($old_file_ref,$target_dir); } unlink "$hw_dir/file_list"; - #generate/copy all tiles HDL/SW codes gen_all_tiles($mpsoc,$info, $hw_dir,$sw_dir ); - #copy clk setting hdl codes in src_verilog my $project_dir = abs_path("$dir/../../"); my $sc_soc =get_source_set_top($mpsoc,'mpsoc'); - my ($file_ref,$warnings)= get_all_files_list($sc_soc,"hdl_files"); - my ($sim_ref,$warnings2)= get_all_files_list($sc_soc,"hdl_files_ticked"); + my ($file_ref,$warnings)= get_all_files_list($sc_soc,"hdl_files"); + my ($sim_ref,$warnings2)= get_all_files_list($sc_soc,"hdl_files_ticked"); #file_ref-sim_ref my @n= get_diff_array($file_ref,$sim_ref); $file_ref=\@n; - copy_file_and_folders($file_ref,$project_dir,"$hw_dir/lib"); show_colored_info($info,$warnings,'green') if(defined $warnings); add_to_project_file_list($file_ref,"$hw_dir/lib/",$hw_dir); - + copy_file_and_folders($sim_ref,$project_dir,"$hw_dir/../src_sim"); show_colored_info($info,$warnings2,'green') if(defined $warnings2); add_to_project_file_list($sim_ref,"$hw_dir/../src_sim",$hw_dir); - - #generate header file containig the tiles physical addresses gen_tiles_physical_addrsses_header_file($mpsoc,"$sw_dir/phy_addr.h"); - #copy all NoC HDL files #my @files = glob( "$dir/../rtl/src_noc/*.v" ); #copy_file_and_folders(\@files,$project_dir,"$hw_dir/lib/"); @@ -1764,19 +1550,17 @@ sub generate_mpsoc{ @files = File::Find::Rule->file() ->name( '*.v','*.V') ->in( "$dir2" ); - copy_file_and_folders (\@files,$project_dir,"$hw_dir/lib/"); } - - + # Write object file generate_mpsoc_lib_file($mpsoc,$info); - + # Write verilog file open(FILE, ">$target_dir/src_verilog/$name.sv") || die "Can not open: $!"; print FILE $file_v; close(FILE) || die "Error closing file: $!"; - + my $l=autogen_warning().get_license_header("${name}_top.v"); open(FILE, ">$target_dir/src_verilog/${name}_top.v") || die "Can not open: $!"; print FILE "$l\n$top_v"; @@ -1784,16 +1568,10 @@ sub generate_mpsoc{ gen_noc_localparam_v_file($mpsoc,"$target_dir/src_verilog/lib/src_noc"); - - - - - - # $l=autogen_warning().get_license_header("${name}_mp.v"); - # open(FILE, ">$target_dir/src_verilog/${name}_mp.v") || die "Can not open: $!"; - # print FILE "$l\n$mp_v"; - # close(FILE) || die "Error closing file: $!"; - + # $l=autogen_warning().get_license_header("${name}_mp.v"); + # open(FILE, ">$target_dir/src_verilog/${name}_mp.v") || die "Can not open: $!"; + # print FILE "$l\n$mp_v"; + # close(FILE) || die "Error closing file: $!"; #generate makefile open(FILE, ">$sw_dir/Makefile") || die "Can not open: $!"; @@ -1806,7 +1584,7 @@ sub generate_mpsoc{ open(FILE, ">$sw_dir/program.sh") || die "Can not open: $!"; print FILE mpsoc_mem_prog($m_chain); close(FILE) || die "Error closing file: $!"; - + my @ff= ("$target_dir/src_verilog/$name.sv","$target_dir/src_verilog/${name}_top.v"); add_to_project_file_list(\@ff,"$hw_dir/lib/",$hw_dir); @@ -1818,14 +1596,13 @@ sub generate_mpsoc{ #regenerate linker var file create_linker_var_file($mpsoc); - - + message_dialog("MPSoC \"$name\" has been created successfully at $target_dir/ " ) if($show_sucess_msg); return 1; -} +} sub mpsoc_sw_make { - my $make="TOPTARGETS := all clean + my $make="TOPTARGETS := all clean SUBDIRS := \$(wildcard */.) \$(TOPTARGETS): \$(SUBDIRS) \$(SUBDIRS): @@ -1839,9 +1616,7 @@ sub mpsoc_sw_make { sub mpsoc_mem_prog { my $chain=shift; - - my $string="#!/bin/bash - + my $string="#!/bin/bash #JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/JTAG_INTFC\" source ./jtag_intfc.sh @@ -1871,7 +1646,7 @@ sub mpsoc_mem_prog { bash write_memory.sh cd .. done - + #Enable the cpu \$JTAG_INTFC -t $chain -n 127 -d \"I:1,D:2:0,I:0\" # I:1 set jtag_enable in active mode @@ -1927,9 +1702,8 @@ sub get_tile{ } $button->signal_connect("clicked" => sub{ - get_tile_setting ($mpsoc,$tile); - }); - + get_tile_setting ($mpsoc,$tile); + }); #$button->show_all; return $button; } @@ -1940,26 +1714,21 @@ sub define_empty_param_setting { my $okbox=def_hbox(TRUE,0); $okbox->pack_start($ok, FALSE, FALSE,0); $ok-> signal_connect("clicked" => sub{ - set_gui_status($mpsoc,"refresh_soc",1); - $window->destroy; - - }); - my $param_table = def_table(1, 1, TRUE); - $param_table->attach_defaults($okbox,0,1,3,4); - return $param_table; - - + set_gui_status($mpsoc,"refresh_soc",1); + $window->destroy; + }); + my $param_table = def_table(1, 1, TRUE); + $param_table->attach_defaults($okbox,0,1,3,4); + return $param_table; } sub get_tile_setting { my($mpsoc,$tile)=@_; my $window = def_popwin_size(50,40,"Parameter setting for Tile $tile ",'percent'); my $table = def_table(6, 2, FALSE); - my $scrolled_win = add_widget_to_scrolled_win($table); my $row=0; my ($soc_name,$g,$t)=$mpsoc->mpsoc_get_tile_soc_name($tile); - my @socs=$mpsoc->mpsoc_get_soc_list(); my @list=(' ',@socs); my $pos=(defined $soc_name)? get_scolar_pos($soc_name,@list): 0; @@ -1969,13 +1738,11 @@ sub get_tile_setting { $table->attach($combo,2,3,$row,$row+1,'shrink','shrink',2,2);$row++; add_Hsep_to_table($table,0,3,$row);$row++; $soc_name = ' ' if (!defined $soc_name); - my $param_table = ($soc_name eq ' ')? define_empty_param_setting($mpsoc,$window) : - get_soc_parameter_setting_table($mpsoc,$soc_name,$window,[$tile]); - - $table->attach_defaults($param_table,0,3,2,3); - - - $combo->signal_connect('changed'=>sub{ + my $param_table = ($soc_name eq ' ')? + define_empty_param_setting($mpsoc,$window) : + get_soc_parameter_setting_table($mpsoc,$soc_name,$window,[$tile]); + $table->attach_defaults($param_table,0,3,2,3); + $combo->signal_connect('changed'=>sub{ my $new_soc=$combo->get_active_text(); if ($new_soc eq ' '){ #unconnect tile @@ -1996,7 +1763,6 @@ sub get_tile_setting { $window->show_all; } - ########## # gen_tiles ######### @@ -2005,15 +1771,14 @@ sub gen_tiles{ my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($mpsoc); my $table; my $dim_y = floor(sqrt($NE)); - $table=def_table($NE%8,$NE/8,FALSE);# my ($row,$col,$homogeneous)=@_; - for (my $i=0; $i<$NE;$i++){ - my $tile=get_tile($mpsoc,$i); - my $y= int($i/$dim_y); - my $x= $i % $dim_y; + $table=def_table($NE%8,$NE/8,FALSE);# my ($row,$col,$homogeneous)=@_; + for (my $i=0; $i<$NE;$i++){ + my $tile=get_tile($mpsoc,$i); + my $y= int($i/$dim_y); + my $x= $i % $dim_y; $table->attach_defaults ($tile, $x, $x+1 , $y, $y+1); - } - - my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_tiles_adj'); + } + my $scrolled_win = gen_scr_win_with_adjst($mpsoc,'gen_tiles_adj'); add_widget_to_scrolled_win($table,$scrolled_win); return $scrolled_win; } @@ -2024,22 +1789,20 @@ sub get_elf_file_addr_range { #my $command= "size -A $file"; my $command= "nm $file"; #add_info($tview,"$command\n"); - my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); + my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command); if(length $stderr>1){ add_colored_info($tview,"$stderr\n",'red'); add_colored_info($tview,"$command was not run successfully!\n",'red'); return ("Err","Err"); - } + } if($exit){ add_colored_info($tview,"$stdout\n",'red'); add_colored_info($tview,"$command was not run successfully!\n",'red'); return ("Err","Err"); } - my @lines = split ("\n" ,$stdout); my $max_addr=0; my $sec_name; - foreach my $p (@lines ){ $p =~ s/\s+/ /g; # remove extra spaces $p =~ s/^\s+//; #ltrim @@ -2062,7 +1825,7 @@ sub show_reqired_brams{ my $table= def_table(10,10,FALSE); add_widget_to_scrolled_win($table,$sc_win); my $row=0; - my $col=0; + my $col=0; my @clmns =('Tile#', 'Section located in Upper Bound Address (UBA) ','UBA in Bytes','UBA in Words','Minimum Memory Address Width'); my $target_dir; @@ -2070,11 +1833,8 @@ sub show_reqired_brams{ my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); if(defined $mpsoc_name){#it is an soc - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; - for (my $tile_num=0;$tile_num<$NE;$tile_num++){ my $ram_file = "$target_dir/sw/tile$tile_num/image"; my ($size,$sec) = get_elf_file_addr_range($ram_file,$tview); @@ -2086,8 +1846,7 @@ sub show_reqired_brams{ $clmn{3}="$w"; $clmn{4}=ceil(log($w)/log(2)); push(@data,\%clmn); - - }#$tile_num + }#$tile_num } else { @@ -2105,27 +1864,26 @@ sub show_reqired_brams{ push(@data,\%clmn); } - my @clmn_type = (#'Glib::Boolean', # => G_TYPE_BOOLEAN - #'Glib::Uint', # => G_TYPE_UINT - 'Glib::String', # => G_TYPE_STRING - 'Glib::String', - 'Glib::String', - 'Glib::String', - 'Glib::String'); # you get the idea + my @clmn_type = ( + #'Glib::Boolean', # => G_TYPE_BOOLEAN + #'Glib::Uint', # => G_TYPE_UINT + 'Glib::String', # => G_TYPE_STRING + 'Glib::String', + 'Glib::String', + 'Glib::String', + 'Glib::String' + ); my $list= gen_list_store (\@data,\@clmn_type,\@clmns); $table-> attach ($list, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $row++; - $win->add($sc_win); $win->show_all(); } sub check_conflict { my ($self,$tile_num,$label)=@_; - my $r1 =$self->object_get_attribute("ROM$tile_num",'end'); my $r2 =$self->object_get_attribute("RAM$tile_num",'start'); - if(defined $r1 && defined $r2){ if(hex($r1)> hex($r2)){ $label->set_markup("RAM-ROM range Conflict"); @@ -2145,7 +1903,6 @@ sub update_ram_rom_size { my ($self,$tile_num,$name,$label,$start,$end,$conflict)=@_; my $s = $start->get_value(); my $e = $end->get_value(); - $self->object_add_attribute($name.$tile_num,'start',$start->get_value()); $self->object_add_attribute($name.$tile_num,'end',$end->get_value()); if($e <= $s){ @@ -2154,13 +1911,8 @@ sub update_ram_rom_size { }else { $label->set_label( metric_conversion($e - $s) . "B"); - } - check_conflict($self,$tile_num,$conflict); - - - } sub get_tile_peripheral_patameter { @@ -2184,8 +1936,7 @@ sub get_tile_peripheral_patameter { } } } - return undef; - + return undef; } sub get_soc_peripheral_parameter { @@ -2199,7 +1950,6 @@ sub get_soc_peripheral_parameter { return undef; } - sub linker_initial_setting { my ($self,$tview)=@_; my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); @@ -2208,32 +1958,23 @@ sub linker_initial_setting { if(defined $mpsoc_name){#it is an mpsoc my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; for (my $tile_num=0;$tile_num<$NE;$tile_num++){ - my $v=get_tile_peripheral_patameter($self,$tile_num,"_ram","Aw"); $v = 13 if (!defined $v); $self->object_add_attribute('MEM'.$tile_num,'width',$v); $self->object_add_attribute('MEM'.$tile_num,'percent',75); - my $s =(1 << ($v+2)) ; my $p = 75; - my $rom_start = 0; my $rom_end= int ( ($s*$p)/100); my $ram_start= int (($s*$p)/100); my $ram_end= $s; - $self->object_add_attribute('ROM'.$tile_num,'start',$rom_start); $self->object_add_attribute('ROM'.$tile_num,'end',$rom_end); $self->object_add_attribute('RAM'.$tile_num,'start',$ram_start); $self->object_add_attribute('RAM'.$tile_num,'end',$ram_end); - - } - - } else { @@ -2243,66 +1984,47 @@ sub linker_initial_setting { $self->object_add_attribute('MEM0','percent',75); my $s =(1 << ($v+2)) ; my $p = 75; - my $rom_start = 0; my $rom_end= int ( ($s*$p)/100); my $ram_start= int (($s*$p)/100); my $ram_end= $s; - $self->object_add_attribute('ROM0','start',$rom_start); $self->object_add_attribute('ROM0','end',$rom_end); $self->object_add_attribute('RAM0','start',$ram_start); $self->object_add_attribute('RAM0','end',$ram_end); } - - } - - sub linker_setting{ my ($self,$tview)=@_; my $win=def_popwin_size (80,50,"BRAM info", 'percent'); my $sc_win = gen_scr_win_with_adjst($self,'liststore'); my $table= def_table(10,10,FALSE); - - my $row=0; my $col=0; - $table-> attach (gen_label_in_center("Tile"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; $table-> attach (gen_label_in_center("Memory Addr"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; $table-> attach (gen_label_in_center("ROM/(ROM+RAM)"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; - $table-> attach (gen_label_in_center("ROM index addr (hex)"), $col, $col+2, $row, $row+1,'shrink','shrink',2,2); $col+=3; $table-> attach (gen_label_in_center("RAM index addr (hex)"), $col, $col+2, $row, $row+1,'shrink','shrink',2,2); $col+=3; - - $col=0;$row++; $table-> attach (gen_label_in_center("#"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; $table-> attach (gen_label_in_center("Width"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; $table-> attach (gen_label_in_center("(%)"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_center("Beginning"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; $table-> attach (gen_label_in_center("End"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; $table-> attach (gen_label_in_center("Size"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - $table-> attach (gen_label_in_center("Beginning"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col+=1; $table-> attach (gen_label_in_center("End"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; $table-> attach (gen_label_in_center("Size"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - $col=0;$row++; - my $target_dir; my @data; - my $mpsoc_name=$self->object_get_attribute('mpsoc_name'); my $tnum; if(defined $mpsoc_name){#it is an mpsoc - my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - $tnum=$NE; + $tnum=$NE; $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; } else @@ -2311,121 +2033,82 @@ sub linker_setting{ $target_dir = "$ENV{'PRONOC_WORK'}/SOC/$soc_name"; $tnum=1; } - for (my $j=0;$j<$tnum;$j++){ - my $tile_num=$j; - my $conflict =gen_label_in_center(" ") ; - - $table-> attach (gen_label_in_center("$tile_num"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col++; - my $ram_width = gen_spin(2,64,1); - my $width = $self->object_get_attribute('MEM'.$tile_num,'width'); - if(!defined $width){ - linker_initial_setting ($self,$tview); - $width = $self->object_get_attribute('MEM'.$tile_num,'width'); - } - $ram_width->set_value($width); - my $size =gen_label_in_center(metric_conversion(1 << 15). "B") ; - - - $table-> attach (def_pack_hbox('FALSE',0,$ram_width,$size), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - - my $percent = gen_spin_float(6.25,93.75,6.25,2); - my $p=$self->object_get_attribute('MEM'.$tile_num,'percent'); - $percent->set_value($p); - - my $enter= def_image_button("icons/enter.png"); - $table-> attach (def_pack_hbox('FALSE',0,$percent,$enter), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - my $rom_start_v =$self->object_get_attribute('ROM'.$tile_num,'start'); - my $rom_end_v = $self->object_get_attribute('ROM'.$tile_num,'end'); - my $ram_start_v = $self->object_get_attribute('RAM'.$tile_num,'start'); - my $ram_end_v = $self->object_get_attribute('RAM'.$tile_num,'end'); - - - - my $rom_start = HexSpin->new ( $rom_start_v, 0, 0xffffffff ,4); - $rom_start->set_digits(8); - $table-> attach ($rom_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - my $rom_end = HexSpin->new ( $rom_end_v, 0, 0xffffffff ,4); - $rom_end->set_digits(8); - $table-> attach ($rom_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - my $rom_size =gen_label_in_center(" ") ; - $table-> attach ($rom_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + for (my $j=0;$j<$tnum;$j++){ + my $tile_num=$j; + my $conflict =gen_label_in_center(" ") ; + $table-> attach (gen_label_in_center("$tile_num"), $col, $col+1, $row, $row+1,'shrink','shrink',2,2);$col++; + my $ram_width = gen_spin(2,64,1); + my $width = $self->object_get_attribute('MEM'.$tile_num,'width'); + if(!defined $width){ + linker_initial_setting ($self,$tview); + $width = $self->object_get_attribute('MEM'.$tile_num,'width'); + } + $ram_width->set_value($width); + my $size =gen_label_in_center(metric_conversion(1 << 15). "B") ; + $table-> attach (def_pack_hbox('FALSE',0,$ram_width,$size), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + my $percent = gen_spin_float(6.25,93.75,6.25,2); + my $p=$self->object_get_attribute('MEM'.$tile_num,'percent'); + $percent->set_value($p); + my $enter= def_image_button("icons/enter.png"); + $table-> attach (def_pack_hbox('FALSE',0,$percent,$enter), $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + my $rom_start_v =$self->object_get_attribute('ROM'.$tile_num,'start'); + my $rom_end_v = $self->object_get_attribute('ROM'.$tile_num,'end'); + my $ram_start_v = $self->object_get_attribute('RAM'.$tile_num,'start'); + my $ram_end_v = $self->object_get_attribute('RAM'.$tile_num,'end'); + my $rom_start = HexSpin->new ( $rom_start_v, 0, 0xffffffff ,4); + $rom_start->set_digits(8); + $table-> attach ($rom_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + my $rom_end = HexSpin->new ( $rom_end_v, 0, 0xffffffff ,4); + $rom_end->set_digits(8); + $table-> attach ($rom_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + my $rom_size =gen_label_in_center(" ") ; + $table-> attach ($rom_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict); + $rom_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); + $rom_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); + my $ram_start = HexSpin->new ( $ram_start_v, 0, 0xffffffff ,4); + $ram_start->set_digits(8); + $table-> attach ($ram_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + my $ram_end = HexSpin->new ( $ram_end_v, 0, 0xffffffff ,4); + $ram_end->set_digits(8); + $table-> attach ($ram_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + my $ram_size =gen_label_in_center(" ") ; + $table-> attach ($ram_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict); + $ram_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); + $ram_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); + $ram_width->signal_connect("value_changed" => sub{ + my $w=$ram_width->get_value(); + $self->object_add_attribute('MEM'.$tile_num,'width',$w); + $size->set_label (metric_conversion(1 << ($w+2)). "B") ; + $size->show_all; + $enter->clicked; + }); + $percent->signal_connect("value_changed" => sub{ + $self->object_add_attribute('MEM'.$tile_num,'percent',$percent->get_value()); + }); + $table-> attach ($conflict, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; + $enter-> signal_connect ( 'clicked' , sub { + my $w=$ram_width->get_value(); + my $s =(1 << ($w+2)); + my $p = $percent->get_value(); + my $rom_start_v = 0; + my $rom_end_v= int ( ($s*$p)/100); + my $ram_start_v= int (($s*$p)/100); + my $ram_end_v= $s; + $rom_start->set_value($rom_start_v); + $rom_end->set_value($rom_end_v); + $ram_start->set_value($ram_start_v); + $ram_end->set_value($ram_end_v); update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict); - $rom_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); - $rom_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict);}); - - my $ram_start = HexSpin->new ( $ram_start_v, 0, 0xffffffff ,4); - $ram_start->set_digits(8); - $table-> attach ($ram_start, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - my $ram_end = HexSpin->new ( $ram_end_v, 0, 0xffffffff ,4); - $ram_end->set_digits(8); - $table-> attach ($ram_end, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - my $ram_size =gen_label_in_center(" ") ; - $table-> attach ($ram_size, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict); - - $ram_start->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); - $ram_end->signal_connect ( 'changed', sub {update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict);}); - - $ram_width->signal_connect("value_changed" => sub{ - my $w=$ram_width->get_value(); - $self->object_add_attribute('MEM'.$tile_num,'width',$w); - $size->set_label (metric_conversion(1 << ($w+2)). "B") ; - $size->show_all; - $enter->clicked; - }); - $percent->signal_connect("value_changed" => sub{ - $self->object_add_attribute('MEM'.$tile_num,'percent',$percent->get_value()); - }); - - $table-> attach ($conflict, $col, $col+1, $row, $row+1,'shrink','shrink',2,2); $col++; - - - - - $enter-> signal_connect ( 'clicked' , sub { - my $w=$ram_width->get_value(); - my $s =(1 << ($w+2)); - my $p = $percent->get_value(); - - my $rom_start_v = 0; - my $rom_end_v= int ( ($s*$p)/100); - my $ram_start_v= int (($s*$p)/100); - my $ram_end_v= $s; - - $rom_start->set_value($rom_start_v); - $rom_end->set_value($rom_end_v); - $ram_start->set_value($ram_start_v); - $ram_end->set_value($ram_end_v); - update_ram_rom_size($self,$tile_num,'ROM',$rom_size,$rom_start,$rom_end,$conflict); - update_ram_rom_size($self,$tile_num,'RAM',$ram_size,$ram_start,$ram_end,$conflict); - - }); - - $col=0; $row++; - + }); + $col=0; $row++; }#$tile_num - my $main_table=def_table(10,10,FALSE); - my $ok = def_image_button('icons/select.png','OK'); $main_table->attach_defaults ($table , 0, 12, 0,11); $main_table->attach ($ok,5, 6, 11,12,'shrink','shrink',0,0); - $ok->signal_connect('clicked', sub { for (my $t=0;$t<$tnum;$t++){ my $r0 =$self->object_get_attribute("ROM$t",'start'); @@ -2433,31 +2116,20 @@ sub linker_setting{ my $r2 =$self->object_get_attribute("RAM$t",'start'); my $r3 =$self->object_get_attribute("RAM$t",'end'); if(hex($r1) hex($r2) ){ - message_dialog("Please fix tile $t conflict range !"); - return ; - + message_dialog("Please fix tile $t conflict range !"); + return ; } - - - } create_linker_var_file($self); $win->destroy(); - - }); - - add_widget_to_scrolled_win($main_table,$sc_win); $win->add($sc_win); $win->show_all(); - } @@ -2473,20 +2145,17 @@ sub create_linker_var_file{ if(defined $mpsoc_name){#it is an mpsoc my ($NE, $NR, $RAw, $EAw, $Fw)=get_topology_info($self); - $tnum=$NE; + $tnum=$NE; } else { - $tnum=1; } - for (my $t=0;$t<$tnum;$t++){ my $r0 =$self->object_get_attribute("ROM$t",'start'); my $r1 =$self->object_get_attribute("ROM$t",'end'); my $r2 =$self->object_get_attribute("RAM$t",'start'); my $r3 =$self->object_get_attribute("RAM$t",'end'); - my $file=sprintf(" MEMORY @@ -2539,9 +2208,7 @@ sub software_edit_mpsoc { $ram -> signal_connect("clicked" => sub{ show_reqired_brams($self,$tview); }); - - my $load; - + my $load; $make -> signal_connect("clicked" => sub{ $load->destroy if(defined $load); $load= show_gif("icons/load.gif"); @@ -2556,27 +2223,23 @@ sub software_edit_mpsoc { $load->show_all; return; }; - unless (run_make_file($sw,$tview)){ - $load->destroy; - $load=def_icon("icons/cancel.png"); - $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); - $load->show_all; - return; - } + unless (run_make_file($sw,$tview)){ + $load->destroy; + $load=def_icon("icons/cancel.png"); + $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); + $load->show_all; + return; + } $load->destroy; $load=def_icon("icons/button_ok.png"); $table->attach ($load,7, 8, 1,2,'shrink','shrink',0,0); $load->show_all; - - }); - #Programe the board $prog-> signal_connect("clicked" => sub{ my $error = 0; my $bash_file="$sw/program.sh"; my $jtag_intfc="$sw/jtag_intfc.sh"; - add_info($tview,"Program the board using quartus_pgm and $bash_file file\n"); #check if the programming file exists unless (-f $bash_file) { @@ -2588,7 +2251,6 @@ sub software_edit_mpsoc { add_colored_info($tview,"\tThe $jtag_intfc does not exists!. Press the compile button and select your FPGA board first to generate $jtag_intfc file\n", 'red'); $error=1; } - return if($error); my $command = "cd $sw; bash program.sh"; add_info($tview,"$command\n"); @@ -2597,32 +2259,22 @@ sub software_edit_mpsoc { add_colored_info($tview,"$stderr\n",'red'); add_colored_info($tview,"Memory was not programmed successfully!\n",'red'); }else { - if($exit){ add_colored_info($tview,"$stdout\n",'red'); add_colored_info($tview,"Memory was not programmed successfully!\n",'red'); }else{ add_info($tview,"$stdout\n"); add_colored_info($tview,"Memory is programmed successfully!\n",'blue'); - } - } }); - - $linker -> signal_connect("clicked" => sub{ linker_setting($self,$tview); }); - } - - - ############# # load_mpsoc ############# - sub load_mpsoc{ my ($mpsoc,$info)=@_; my $file; @@ -2641,13 +2293,10 @@ sub load_mpsoc{ $dialog->destroy; return; } - - clone_obj($mpsoc,$pp); #read save mpsoc socs my @oldsocs=$mpsoc->mpsoc_get_soc_list(); #add existing SoCs and add them to mpsoc - my $error; #print "old: @oldsocs\n new @newsocs \n"; foreach my $p (@oldsocs) { @@ -2655,67 +2304,50 @@ sub load_mpsoc{ my @num= $mpsoc->mpsoc_get_soc_tiles_num($p); if (scalar @num && ( grep (/^$p$/,@newsocs)==0)){ my $m="Processing tile $p that has been used for ties @num but is not located in library anymore\n"; - $error = (defined $error ) ? "$error $m" : $m; + $error = (defined $error ) ? "$error $m" : $m; } $mpsoc->mpsoc_remove_soc ($p) if (grep (/^$p$/,@newsocs)==0); - - } @newsocs=get_soc_list($mpsoc,$info); # add all existing socs add_info($info,"**Error: \n $error\n") if(defined $error); - set_gui_status($mpsoc,"load_file",0); - - } - } - $dialog->destroy; + } + } + $dialog->destroy; } ####### # CLK setting ####### - sub clk_setting_win1{ my ($self,$info,$type)=@_; - my $window = def_popwin_size(80,80,"CLK setting",'percent'); - my $next=def_image_button('icons/right.png','Next'); my $mtable = def_table(10, 1, FALSE); #get the list of all tiles clk sources - my @sources=('clk','reset'); - my $table = def_table(10, 7, FALSE); my $notebook = gen_notebook(); $notebook->set_scrollable(TRUE); #$notebook->can_focus(FALSE); $notebook->set_tab_pos ('left'); - - - my($row,$column)=(0,0); - my %all = ($type eq 'mpsoc') ? get_all_tiles_clk_sources_list($self): get_soc_clk_source_list($self) ; foreach my $s (@sources){ - my $spin; - ($row,$column,$spin)= add_param_widget($self,"$s number","${s}_number", 1,'Spin-button',"1,1024,1","Define total number of ${s} input ports mpsoc", $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); - - my $w=get_source_assignment_win($self,$s,$all{$s},$type); - my $box=def_hbox(FALSE,0); - $box->pack_start($w, TRUE, TRUE, 0); - $notebook->append_page ($box,gen_label_in_center ($s)); - $spin->signal_connect("value_changed" => sub{ - $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",1); - $w->destroy; - $w=get_source_assignment_win($self,$s,$all{$s},$type); - $box->pack_start($w, TRUE, TRUE, 0); - $box->show_all; - + my $spin; + ($row,$column,$spin)= add_param_widget($self,"$s number","${s}_number", 1,'Spin-button',"1,1024,1","Define total number of ${s} input ports mpsoc", $table,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); + my $w=get_source_assignment_win($self,$s,$all{$s},$type); + my $box=def_hbox(FALSE,0); + $box->pack_start($w, TRUE, TRUE, 0); + $notebook->append_page ($box,gen_label_in_center ($s)); + $spin->signal_connect("value_changed" => sub{ + $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",1); + $w->destroy; + $w=get_source_assignment_win($self,$s,$all{$s},$type); + $box->pack_start($w, TRUE, TRUE, 0); + $box->show_all; }); - } - $mtable->attach_defaults($table,0,1,0,1); $mtable->attach_defaults( $notebook,0,1,1,20); $mtable->attach($next,0,1,20,21,'expand','fill',2,2); @@ -2724,9 +2356,7 @@ sub clk_setting_win1{ $next-> signal_connect("clicked" => sub{ clk_setting_win2($self,$info,$type); $window->destroy; - }); - } @@ -2767,10 +2397,8 @@ sub get_source_assignment_win{ my $enter= def_image_button("icons/enter.png"); my $box=def_hbox(FALSE,0); $box->pack_start( $enter, FALSE, FALSE, 0); - ($row,$column,$entry)= add_param_widget($mpsoc,"$n-","${s}_${n}_name", "${s}$n",'Entry',undef,undef, $table1,$row,$column,1,'SOURCE_SET',undef,undef,'horizontal'); $table1->attach ($box,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column++; - $enter->signal_connect ("clicked" => sub{ $mpsoc->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",1); $win2->destroy; @@ -2778,24 +2406,18 @@ sub get_source_assignment_win{ $v2-> pack2($win2, TRUE, TRUE); $v2->show_all; }); - - if($s eq 'clk'){ ($column,$row)=get_clk_constrain_widget($mpsoc,$table1,$column,$row, $s,$n); } - - - - # if((($n+1) % 4)==0){ - $column=0; - $row++; - #} - } - - #source assigmnmet + # if((($n+1) % 4)==0){ + $column=0; + $row++; + #} + } + #source assigmnmet $win2= get_source_assignment_win2($mpsoc,$s,$ports_ref,$type); - $v2=gen_vpaned($win1,.2,$win2); - return $v2; + $v2=gen_vpaned($win1,.2,$win2); + return $v2; } @@ -2820,11 +2442,11 @@ sub get_clk_constrain_widget { $table->attach ($f_lab,$column,$column+1,$row,$row+1,'fill','shrink',2,2);$column+=1; update_wave_form($period,$rise,$fall,$r_lab,$f_lab); $frequency-> signal_connect("value_changed" => sub{ - my $fr =$frequency->get_value(); + my $fr =$frequency->get_value(); my $p = 1000/$fr; - $period->set_value($p); - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); - }); + $period->set_value($p); + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + }); $period-> signal_connect("value_changed" => sub{ my $p =$period->get_value(); my $fr = 1000/$p; @@ -2832,27 +2454,25 @@ sub get_clk_constrain_widget { update_wave_form($period,$rise,$fall,$r_lab,$f_lab); }); $rise-> signal_connect("value_changed" => sub{ - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); }); $fall-> signal_connect("value_changed" => sub{ - update_wave_form($period,$rise,$fall,$r_lab,$f_lab); - }); + update_wave_form($period,$rise,$fall,$r_lab,$f_lab); + }); return ($column,$row); } - sub get_source_assignment_win2{ my ($mpsoc,$s,$ports_ref,$type)=@_; my $num = $mpsoc->object_get_attribute('SOURCE_SET',"${s}_number"); my $table2 = def_table(10, 7, FALSE); - my $win2=add_widget_to_scrolled_win($table2); - my %ports = %{$ports_ref} if(defined $ports_ref); - + my $win2=add_widget_to_scrolled_win($table2); + my %ports = %{$ports_ref} if(defined $ports_ref); my $contents; for(my $n=0;$n<$num; $n++ ){ - my $m=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); - $contents=(defined $contents)? "$contents,$m":$m; + my $m=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); + $contents=(defined $contents)? "$contents,$m":$m; } my $default=$mpsoc->object_get_attribute('SOURCE_SET',"${s}_0_name"); my $n=0; @@ -2861,18 +2481,16 @@ sub get_source_assignment_win2{ add_param_widget($mpsoc," NoC $s","NoC_${s}", $default,'Combo-box',$contents,undef, $table2,$row,$column,1,'SOURCE_SET_CONNECT',undef,undef,'horizontal'); ($row,$column)=(1,0); } - foreach my $p (sort keys %ports){ - my @array=@{$ports{$p}}; - foreach my $q (@array){ - my $param="${p}_$q"; - my $label=" ${p}_$q"; - ($row,$column)= add_param_widget($mpsoc,$label,$param, $default,'Combo-box',$contents,undef, $table2,$row,$column,1,'SOURCE_SET_CONNECT',undef,undef,'horizontal'); - if((($n+1) % 4)==0){$column=0;$row++;}$n++; - } + my @array=@{$ports{$p}}; + foreach my $q (@array){ + my $param="${p}_$q"; + my $label=" ${p}_$q"; + ($row,$column)= add_param_widget($mpsoc,$label,$param, $default,'Combo-box',$contents,undef, $table2,$row,$column,1,'SOURCE_SET_CONNECT',undef,undef,'horizontal'); + if((($n+1) % 4)==0){$column=0;$row++;}$n++; + } } return $win2; - } @@ -2885,9 +2503,7 @@ sub get_all_tiles_clk_sources_list{ next if(!defined $soc_name); my $top=$mpsoc->mpsoc_get_soc($soc_name); my @intfcs=$top->top_get_intfc_list(); - my @sources=('clk','reset'); - foreach my $intfc (@intfcs){ my($type,$name,$num)= split("[:\[ \\]]", $intfc); foreach my $s (@sources){ @@ -2896,17 +2512,13 @@ sub get_all_tiles_clk_sources_list{ $all_sources{$s}{"T$tile_num"}=\@ports; } } - } } - return %all_sources; + return %all_sources; } - - sub clk_setting_win2{ my ($self,$info,$type)=@_; - my $window = def_popwin_size(70,70,"CLK setting",'percent'); my $table = def_table(10, 7, FALSE); my $scrolled_win=add_widget_to_scrolled_win($table); @@ -2916,79 +2528,61 @@ sub clk_setting_win2{ my $ip = ip->lib_new (); #print "get_top_ip(\$self,$type);\n"; my $mpsoc_ip=get_top_ip($self,$type); - $ip->add_ip($mpsoc_ip); my $soc =get_source_set_top($self,$type); my $infc = interface->interface_new(); - - set_gui_status($soc,"ideal",0); # A tree view for holding a library my %tree_text; my @categories= ('Source'); foreach my $p (@categories) { - my @modules= $ip->get_modules($p); - $tree_text{$p}=\@modules; + my @modules= $ip->get_modules($p); + $tree_text{$p}=\@modules; } - my $tree_box = create_tree ($soc,'IP list', $info,\%tree_text,\&tmp,\&add_module_to_mpsoc); my $device_win=show_active_dev($soc,$ip,$infc,$info); my $h1=gen_hpaned($tree_box,.15,$device_win); $table->attach_defaults ($h1,0, 10, 0, 10); - my $event =Event->timer (after => 1, interval => 1, cb => sub { - -my ($state,$timeout)= get_gui_status($soc); - - - if ($timeout>0){ - $timeout--; - set_gui_status($soc,$state,$timeout); + my ($state,$timeout)= get_gui_status($soc); + if ($timeout>0){ + $timeout--; + set_gui_status($soc,$state,$timeout); + } + elsif( $state ne "ideal" ){ + #check if top is removed add it + my @instances=$soc->soc_get_all_instances(); + my $redefine =1; + foreach my $inst (@instances){ + $redefine = 0 if ($inst eq 'TOP'); } - elsif( $state ne "ideal" ){ - - #check if top is removed add it - my @instances=$soc->soc_get_all_instances(); - my $redefine =1; - foreach my $inst (@instances){ - $redefine = 0 if ($inst eq 'TOP'); - } - if($redefine == 1){ - my $ip = ip->lib_new (); - #print "get_top_ip(\$self,$type);\n"; - my $mpsoc_ip=get_top_ip($self,$type); - - $ip->add_ip($mpsoc_ip); - $soc ->object_add_attribute('SOURCE_SET',"IP",$mpsoc_ip); - $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",0); - add_mpsoc_to_device($soc,$ip); - $self->object_add_attribute('SOURCE_SET',"SOC",$soc); - } - - $device_win->destroy; - - $device_win=show_active_dev($soc,$ip,$infc,$info); - $h1 -> pack2($device_win, TRUE, TRUE); - $h1 -> show_all; - $table->show_all(); - $device_win->show_all(); - - $self->object_add_attribute('SOURCE_SET',"SOC",$soc); - set_gui_status($soc,"ideal",0); - - } - return TRUE; - - - }); - - my $mtable = def_table(10, 5, FALSE); + if($redefine == 1){ + my $ip = ip->lib_new (); + #print "get_top_ip(\$self,$type);\n"; + my $mpsoc_ip=get_top_ip($self,$type); + $ip->add_ip($mpsoc_ip); + $soc ->object_add_attribute('SOURCE_SET',"IP",$mpsoc_ip); + $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",0); + add_mpsoc_to_device($soc,$ip); + $self->object_add_attribute('SOURCE_SET',"SOC",$soc); + } + $device_win->destroy; + $device_win=show_active_dev($soc,$ip,$infc,$info); + $h1 -> pack2($device_win, TRUE, TRUE); + $h1 -> show_all; + $table->show_all(); + $device_win->show_all(); + $self->object_add_attribute('SOURCE_SET',"SOC",$soc); + set_gui_status($soc,"ideal",0); + } + return TRUE; + }); + my $mtable = def_table(10, 5, FALSE); $mtable->attach_defaults($scrolled_win,0,5,0,9); $mtable->attach($back,0,1,9,10,'expand','fill',2,2) if($type ne 'soc'); $mtable->attach($diagram,2,4,9,10,'expand','fill',2,2); $mtable->attach($ok,4,5,9,10,'expand','fill',2,2); - $window->add ($mtable); $window->show_all(); $self->object_add_attribute('SOURCE_SET',"SOC",$soc); @@ -2996,9 +2590,8 @@ sub clk_setting_win2{ $self->object_add_attribute('SOURCE_SET',"SOC",$soc); clk_setting_win1($self,$info,$type); $window->destroy; - $event->cancel; - }); - + $event->cancel; + }); $diagram-> signal_connect("clicked" => sub{ show_tile_diagram ($soc); }); @@ -3007,13 +2600,7 @@ sub clk_setting_win2{ set_gui_status($self,"ref",1); $window->destroy; $event->cancel; - }); - - - - - - + }); } sub tmp{ @@ -3023,12 +2610,9 @@ sub tmp{ sub add_module_to_mpsoc{ my ($soc,$category,$module,$info)=@_; my $ip = ip->lib_new (); - my ($instance_id,$id)= get_instance_id($soc,$category,$module); - - #add module instance + # add module instance my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); - if($result == 0){ my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; show_info($info,$info_text); @@ -3042,7 +2626,6 @@ sub add_module_to_mpsoc{ $soc->object_add_attribute($instance_id,"version",$v); # Read default parameter from lib and add them to soc my %param_default= $ip->get_param_default($category,$module); - my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); if($rr == 0){ my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist."; @@ -3051,19 +2634,14 @@ sub add_module_to_mpsoc{ } my @r=$ip->ip_get_param_order($category,$module); $soc->soc_add_instance_param_order($instance_id,\@r); - get_module_parameter($soc,$ip,$instance_id); undef $ip; set_gui_status($soc,"refresh_soc",0); } - - - #$mpsoc,$top_ip,$sw_dir,$soc_name,$id,$soc_num,$txview sub get_top_ip{ my ($self,$type)=@_; - my $mpsoc_ip=ip_gen->ip_gen_new(); $mpsoc_ip->ipgen_add("module_name",'TOP'); $mpsoc_ip->ipgen_add("ip_name",'TOP'); @@ -3076,11 +2654,9 @@ sub get_top_ip{ $num=1 if(!defined $num); $mpsoc_ip->ipgen_add_plug("$s",'num',$num); for (my $n=0; $n<$num; $n++ ){ - my $name=$self->object_get_attribute('SOURCE_SET',"${s}_${n}_name"); $mpsoc_ip->ipgen_set_plug_name($s,$n,$name); $mpsoc_ip->ipgen_add_port($name,undef,'input',"plug:${s}\[$n\]","${s}_i"); - } } # add_mpsoc_ip_other_interfaces($mpsoc,$mpsoc_ip); @@ -3099,44 +2675,33 @@ sub get_top_ip{ } } } - return $mpsoc_ip; + return $mpsoc_ip; } sub add_mpsoc_ip_other_interfaces{ my ($mpsoc,$mpsoc_ip)=@_; -my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); + my ($NE, $NR, $RAw, $EAw, $Fw)= get_topology_info ($mpsoc); my $processors_en=0; my %intfc_num; my @parameters_order; for (my $tile_num=0;$tile_num<$NE;$tile_num++){ my ($soc_name,$n,$soc_num)=$mpsoc->mpsoc_get_tile_soc_name($tile_num); - - my $top=$mpsoc->mpsoc_get_soc($soc_name); my @nis=get_NI_instance_list($top); my @noc_param=$top->top_get_parameter_list($nis[0]); my $inst_name=$top->top_get_def_of_instance($nis[0],'instance'); - #other parameters my %params=$top->top_get_default_soc_param(); - my @intfcs=$top->top_get_intfc_list(); - my $i=0; - my $dir = Cwd::getcwd(); my $mpsoc_name=$mpsoc->object_get_attribute('mpsoc_name'); my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name"; my $soc_file="$target_dir/src_verilog/tiles/$soc_name.sv"; - my $vdb =read_verilog_file($soc_file); - my %soc_localparam = $vdb->get_modules_parameters($soc_name); - - foreach my $intfc (@intfcs){ - # Auto connected/not connected interface if( $intfc eq 'socket:ni[0]' || ($intfc =~ /plug:clk\[/) || ( $intfc =~ /plug:reset\[/)|| ($intfc =~ /socket:RxD_sim\[/ ) || $intfc =~ /plug:enable\[/){ #do nothing @@ -3146,12 +2711,8 @@ sub add_mpsoc_ip_other_interfaces{ foreach my $p (@ports){ my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); $mpsoc_ip->ipgen_add_port($io_port,$new_range,$type,'IO','IO'); - - } - } - else { #other interface my($if_type,$if_name,$if_num)= split("[:\[ \\]]", $intfc); @@ -3160,31 +2721,25 @@ sub add_mpsoc_ip_other_interfaces{ $intfc_num{"$if_type:$if_name"}=$num; $mpsoc_ip->ipgen_add_plug("$if_name",'num',$num) if ($if_type eq 'plug'); $mpsoc_ip->ipgen_add_soket("$if_name",'num',$num) if ($if_type eq 'socket'); - my @ports=$top->top_get_intfc_ports_list($intfc); foreach my $p (@ports){ my ($io_port,$type,$new_range,$intfc_name,$intfc_port)= get_top_port_io_info($top,$p,$tile_num,\%params,\%soc_localparam); $mpsoc_ip->ipgen_add_port($io_port,$new_range,$type,"$if_type:$if_name\[$num\]",$intfc_port); - } } } - - my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile_num); #if ($setting eq 'Custom'){ - %params= $top->top_get_custom_soc_param($tile_num); + %params= $top->top_get_custom_soc_param($tile_num); #}else{ # %params=$top->top_get_default_soc_param(); #} - foreach my $p (sort keys %params){ $params{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$params{$p}); $params{$p}=add_instantc_name_to_parameters(\%soc_localparam,"T$tile_num",$params{$p}); my $pname="T${tile_num}_$p"; $mpsoc_ip-> ipgen_add_parameter ($pname,$params{$p},'Fixed',undef,undef,'Localparam',1); push (@parameters_order,$pname); - } foreach my $p (sort keys %soc_localparam){ $soc_localparam{$p}=add_instantc_name_to_parameters(\%params,"T$tile_num",$soc_localparam{$p}); @@ -3194,13 +2749,9 @@ sub add_mpsoc_ip_other_interfaces{ push (@parameters_order,$pname); } - - - } #TODO get parameter order $mpsoc_ip->ipgen_add("parameters_order",\@parameters_order); - } sub get_source_set_top{ @@ -3217,7 +2768,6 @@ sub get_source_set_top{ my $ip = ip->lib_new (); #print "get_top_ip(\$self,$type);\n"; my $mpsoc_ip=get_top_ip($self,$type); - $ip->add_ip($mpsoc_ip); $soc ->object_add_attribute('SOURCE_SET',"IP",$mpsoc_ip); $self->object_add_attribute('SOURCE_SET',"REDEFINE_TOP",0); @@ -3233,14 +2783,10 @@ sub add_mpsoc_to_device{ my $category='TOP'; my $module='TOP'; my ($instance_id,$id) =('TOP',1); - #my ($instance_id,$id)= get_instance_id($soc,$category,$module); - remove_instance_from_soc($soc,$instance_id); - - #add module instanance + # add module instanance my $result=$soc->soc_add_instance($instance_id,$category,$module,$ip); - if($result == 0){ my $info_text= "Failed to add \"$instance_id\" to SoC. $instance_id is already exist."; # show_info($info,$info_text); @@ -3254,7 +2800,6 @@ sub add_mpsoc_to_device{ $soc->object_add_attribute($instance_id,"version",$v); # Read default parameter from lib and add them to soc my %param_default= $ip->get_param_default($category,$module); - my $rr=$soc->soc_add_instance_param($instance_id,\%param_default); if($rr == 0){ my $info_text= "Failed to add default parameter to \"$instance_id\". $instance_id does not exist."; @@ -3344,7 +2889,7 @@ sub ctrl_box{ }); $clk-> signal_connect("clicked" => sub{ - clk_setting_win1($mpsoc,$info,'mpsoc'); + clk_setting_win1($mpsoc,$info,'mpsoc'); }); return $table; } @@ -3373,7 +2918,7 @@ sub gen_save_load_widget { $entrybox->pack_start( $save, FALSE, FALSE, 0); $entrybox->pack_start( $load, FALSE, FALSE, 0); $entrybox->pack_start( $open_dir , FALSE, FALSE, 0) if (defined $target_dir); - $open_dir-> signal_connect("clicked" => sub{ + $open_dir-> signal_connect("clicked" => sub{ my $name=$self->object_get_attribute($param_name); $name="" if (!defined $name); if (length($name)==0){ diff --git a/mpsoc/perl_gui/lib/perl/network_maker.pl b/mpsoc/perl_gui/lib/perl/network_maker.pl index 8c556a0..cddfe6f 100644 --- a/mpsoc/perl_gui/lib/perl/network_maker.pl +++ b/mpsoc/perl_gui/lib/perl/network_maker.pl @@ -217,7 +217,7 @@ sub generate_custom_topology_dot_file{ graph [layout = twopi, rankdir = RL , splines = true, overlap = false]; node[shape=record]; "; - #Add endpoints + # Add endpoints my @nodes=get_list_of_all_endpoints($self); my $i=0; foreach my $p (@nodes){ @@ -226,7 +226,7 @@ sub generate_custom_topology_dot_file{ $dotfile.= ($gtype eq 'simple')? endp_node_dot_sim($p,$instance) : endp_node_dot_comp($p,$instance); $i++; } - #add routers + # add routers @nodes=get_list_of_all_routers($self); $i=0; foreach my $p (@nodes){ @@ -236,7 +236,7 @@ sub generate_custom_topology_dot_file{ $dotfile.=($gtype eq 'simple')? router_node_dot_sim($pnum,$p,$instance): router_node_dot_comp($pnum,$p,$instance); $i++; } - #add connections + # add connections my @all_nodes=get_list_of_all_nodes($self); my @draw; foreach my $p (@all_nodes){ @@ -2448,4 +2448,4 @@ sub build_network_maker_gui { } ); return $sc_win; } -1; \ No newline at end of file +1; diff --git a/mpsoc/perl_gui/lib/perl/simulator.pl b/mpsoc/perl_gui/lib/perl/simulator.pl index 4142cbe..0549fe5 100755 --- a/mpsoc/perl_gui/lib/perl/simulator.pl +++ b/mpsoc/perl_gui/lib/perl/simulator.pl @@ -445,8 +445,7 @@ sub get_simulator_noc_configuration{ if ($st==0){ $NE=100; }else{ - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NEe, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($NEe, $NR, $RAw, $EAw, $Fw) = get_sample_topology_info($self,$sample); $NE=$NEe; } if ($traffic eq 'custom'){ @@ -749,8 +748,7 @@ sub run_synthetic_simulation { my $dst = $simulate->object_get_attribute($sample,"DST_$i"); $custom.=($i==0)? "-H \"$src,$dst" : ",$src,$dst"; } - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($simulate,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_sample_topology_info ($simulate,$sample); for (my $i=0;$i<$NE; $i++){ my ($src,$dst) = custom_traffic_dest ($simulate,$sample,$i); $custom_sv.="\tassign custom_traffic_t[$src]=$dst;\n"; diff --git a/mpsoc/perl_gui/lib/perl/topology.pl b/mpsoc/perl_gui/lib/perl/topology.pl index 7024415..0ae06f0 100644 --- a/mpsoc/perl_gui/lib/perl/topology.pl +++ b/mpsoc/perl_gui/lib/perl/topology.pl @@ -17,9 +17,10 @@ sub get_topology_info { 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 $T4=$self->object_get_attribute($noc_param,'T4'); 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); + return get_topology_info_sub($topology, $T1, $T2, $T3, $T4, $V, $Fpay); } sub get_topology_info_from_parameters { @@ -30,13 +31,14 @@ sub get_topology_info_from_parameters { my $T1 =$param{'T1'}; my $T2 =$param{'T2'}; my $T3 =$param{'T3'}; + my $T4 =$param{'T4'}; my $V =$param{'V'}; - my $Fpay=$param{'Fpay'}; - return get_topology_info_sub($topology, $T1, $T2, $T3,$V, $Fpay); + my $Fpay=$param{'Fpay'}; + return get_topology_info_sub($topology, $T1, $T2, $T3, $T4,$V, $Fpay); } sub get_topology_info_sub { - my ($topology, $T1, $T2, $T3,$V, $Fpay)=@_; + my ($topology, $T1, $T2, $T3, $T4, $V, $Fpay)=@_; my $NE; # Total number of end points (local ports) in the NoC my $NR; # Total number of routers in NoC my $RAw; # Routers address width @@ -89,6 +91,20 @@ sub get_topology_info_sub { $RAw = $Xw + $Yw; $EAw = ($NL==1) ? $RAw : $RAw + $Lw; $MAX_P = 4 + $NL; + }elsif ($topology eq '"MESH_3D"' ) { + my $NX=$T1; + my $NY=$T2; + my $NZ=$T3; + my $NL=$T4; + $NE = $NX*$NY*$NL*$NZ; + $NR = $NX*$NY*$NZ; + my $Xw=log2($NX); + my $Yw=log2($NY); + my $Lw=log2($NL); + my $Zw=log2($NZ); + $RAw = $Xw + $Yw + $Zw; + $EAw = ($NL==1) ? $RAw : $RAw + $Lw; + $MAX_P = 6 + $NL; }elsif ($topology eq '"FMESH"'){ my $NX=$T1; my $NY=$T2; @@ -415,9 +431,10 @@ sub get_noc_verilator_top_modules_info { 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 $T4=$self->object_get_attribute('noc_param','T4'); + 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"' || $topology eq '"MESH_3D"')? $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 @@ -432,8 +449,8 @@ sub get_noc_verilator_top_modules_info { my $custom_include=""; if($topology eq '"FATTREE"') { my $K = $T1; - my $L = $T2; - my $p2 = 2*$K; + my $L = $T2; + my $p2 = 2*$K; $router_p=2; my $NRL= $ne/$K; #number of router in each layer $nr_p{1}=$NRL; @@ -449,8 +466,8 @@ sub get_noc_verilator_top_modules_info { ); }elsif ($topology eq '"TREE"'){ my $K = $T1; - my $L = $T2; - my $p2 = $K+1; + 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; @@ -484,7 +501,18 @@ sub get_noc_verilator_top_modules_info { "Vrouter1" => "--top-module router_top_v -GP=${ports} ", # "Vnoc" => " --top-module noc_connection", ); - }elsif ($topology eq '"STAR"') { + } elsif ($topology eq '"MESH_3D"') { + $router_p=1; + $nr_p{1}=$nr; + my $ports= 7+$T4-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; @@ -496,15 +524,15 @@ sub get_noc_verilator_top_modules_info { ); }else {#custom my $dir =get_project_dir()."/mpsoc/rtl/src_topology"; - my $file="$dir/param.obj"; + my $file="$dir/param.obj"; my %param; if(-f $file){ my ($pp,$r,$err) = regen_object($file ); - if ($r){ + if ($r){ print "**Error: cannot open $file file: $err\n"; return; } - %param=%{$pp}; + %param=%{$pp}; }else { print "**Error: cannot find $file \n"; return; @@ -523,8 +551,8 @@ sub get_noc_verilator_top_modules_info { $tops{"Vrouter$i"}= "--top-module router_top_v -GP=${p} ", $i++; - } - $router_p=$i-1; + } + $router_p=$i-1; ${topology_name} =~ s/\"+//g; $custom_include="#define IS_${topology_name}_noc\n"; }#else @@ -709,7 +737,7 @@ sub get_noc_verilator_top_modules_info { # } #} #$includ_h.="\n}\n"; - return ($nr,$ne,$router_p,\%tops,$includ_h); + return ($nr,$ne,$router_p,\%tops,$includ_h); } sub connect_sim_nodes{ @@ -760,7 +788,7 @@ sub gen_tiles_physical_addrsses_header_file{ $txt=$txt."\t#define PHY_ADDR_ENDP_$id $hex\n"; } $txt=$txt."#endif\n"; - save_file($file,$txt); + save_file($file,$txt); } sub get_endpoints_mah_distance { @@ -775,7 +803,7 @@ sub get_endpoints_mah_distance { }elsif ($topology eq '"STAR"'){ return 1; }else { #custom - return undef; + return undef; } } @@ -803,13 +831,13 @@ sub fattree_mah_distance { $pow=1; for (my $i = 0; $i <$l; $i=$i+1 ) { $tmp1=int($router1/$pow); - $tmp2=int($router2/$pow); + $tmp2=int($router2/$pow); $tmp1=$tmp1 % $k; - $tmp2=$tmp2 % $k; - $pow=$pow * $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; + return $distance; } 1 diff --git a/mpsoc/perl_gui/lib/perl/traffic_pattern.pl b/mpsoc/perl_gui/lib/perl/traffic_pattern.pl index ec017d8..b440818 100644 --- a/mpsoc/perl_gui/lib/perl/traffic_pattern.pl +++ b/mpsoc/perl_gui/lib/perl/traffic_pattern.pl @@ -14,9 +14,17 @@ sub get_sample_emulation_param { my $T1=$noc_info{'T1'}; my $T2=$noc_info{'T2'}; my $T3=$noc_info{'T3'}; + my $T4=$noc_info{'T4'}; my $V =$noc_info{'V'}; my $Fpay = $noc_info{'Fpay'}; - return ($topology, $T1, $T2, $T3, $V, $Fpay); + return ($topology, $T1, $T2, $T3, $T4, $V, $Fpay); +} + +sub get_sample_topology_info{ + my ($self,$sample)= @_; + my ($topology, $T1, $T2, $T3, $T4, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $T4, $V, $Fpay); + return ($NE, $NR, $RAw, $EAw, $Fw); } sub getBit{ @@ -38,8 +46,8 @@ sub setBit{ sub pck_dst_gen_2D { my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($topology, $T1, $T2, $T3, $T4, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $T4, $V, $Fpay); my $NEw=log2($NE); #for mesh-tori my ($current_l,$current_x, $current_y); @@ -127,8 +135,8 @@ sub pck_dst_gen_2D { sub pck_dst_gen_1D { my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); - my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $V, $Fpay); + my ($topology, $T1, $T2, $T3, $T4, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info_sub ($topology, $T1, $T2, $T3, $T4, $V, $Fpay); my $NEw=log2($NE); if( $traffic eq "random") { my @randoms=@{$rnd}; @@ -186,7 +194,7 @@ sub pck_dst_gen_1D { sub pck_dst_gen{ my ($self,$sample,$traffic,$core_num,$line_num,$rnd)=@_; - my ($topology, $T1, $T2, $T3, $V, $Fpay) = get_sample_emulation_param($self,$sample); + my ($topology, $T1, $T2, $T3, $T4, $V, $Fpay) = get_sample_emulation_param($self,$sample); return pck_dst_gen_2D ($self,$sample,$traffic,$core_num,$line_num,$rnd) if(( $topology eq '"MESH"') ||( $topology eq '"TORUS"')); return pck_dst_gen_1D ($self,$sample,$traffic,$core_num,$line_num,$rnd); } diff --git a/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC b/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC index ae99c39..d758604 100644 --- a/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC +++ b/mpsoc/perl_gui/lib/soc/mor1k_tile.SOC @@ -1517,7 +1517,7 @@ For XILINX FPGAs define it as "XILINX_JTAG_WB". In this case, the UART uses BSCA 'value' => '4' }, 'ROUTE_NAME' => { - 'value' => '"XY"' + 'value' => '"DOR"' }, 'SELF_LOOP_EN' => { 'value' => '0' diff --git a/mpsoc/rtl/arch/iport_reg_base.sv b/mpsoc/rtl/arch/iport_reg_base.sv index 38ad74f..fdfa09f 100644 --- a/mpsoc/rtl/arch/iport_reg_base.sv +++ b/mpsoc/rtl/arch/iport_reg_base.sv @@ -52,7 +52,7 @@ module iport_reg_base #( parameter VC_REALLOCATION_TYPE = "ATOMIC", parameter COMBINATION_TYPE= "BASELINE",// "BASELINE", "COMB_SPEC1", "COMB_SPEC2", "COMB_NONSPEC" parameter TOPOLOGY = "MESH",//"MESH","TORUS" - parameter ROUTE_NAME="XY",// "XY", "TRANC_XY" + parameter ROUTE_NAME="DOR",// "DOR", "TRANC_DOR" parameter ROUTE_TYPE="DETERMINISTIC",// "DETERMINISTIC", "FULL_ADAPTIVE", "PAR_ADAPTIVE" parameter DEBUG_EN =1, parameter AVC_ATOMIC_EN= 0, @@ -315,10 +315,7 @@ generate .wr_en (flit_wr[i]), // Write enable .rd_en (ivc_num_getting_sw_grant[i]), // Read the next word .dout (flit_is_tail[i]), // Data out - .full ( ), - .nearly_full ( ), - .recieve_more_than_0 ( ), - .recieve_more_than_1 ( ), + .status_o(), .reset (reset), .clk (clk) ); @@ -335,10 +332,7 @@ generate .wr_en (hdr_flit_wr[i]), // Write enable .rd_en (class_rd_fifo[i]), // Read the next word .dout (class_out[i]), // Data out - .full ( ), - .nearly_full ( ), - .recieve_more_than_0 ( ), - .recieve_more_than_1 ( ), + .status_o(), .reset (reset), .clk (clk) @@ -358,10 +352,7 @@ generate .wr_en (hdr_flit_wr_delayed [i]), // Write enable .rd_en (lk_dst_rd_fifo [i]), // Read the next word .dout (lk_destination_encoded [(i+1)*DSTPw-1 : i*DSTPw]), // Data out - .full (), - .nearly_full (), - .recieve_more_than_0 (), - .recieve_more_than_1 (), + .status_o(), .reset (reset), .clk (clk) @@ -381,10 +372,7 @@ generate .wr_en(hdr_flit_wr[i]), // Write enable .rd_en(dst_rd_fifo[i]), // Read the next word .dout(dest_port_encoded[(i+1)*DSTPw-1 : i*DSTPw]), // Data out - .full(), - .nearly_full(), - .recieve_more_than_0(), - .recieve_more_than_1(), + .status_o(), .reset(reset), .clk(clk) ); @@ -401,10 +389,7 @@ generate .wr_en(hdr_flit_wr[i]), // Write enable .rd_en(dst_rd_fifo[i]), // Read the next word .dout(dest_port_encoded[(i+1)*DSTPw-1 : i*DSTPw]), // Data out - .full(), - .nearly_full(), - .recieve_more_than_0(), - .recieve_more_than_1(), + .status_o(), .reset(reset), .clk(clk), .clear(destport_clear[(i+1)*DSTPw-1 : i*DSTPw]) // clear other destination ports once one of them is selected @@ -455,10 +440,7 @@ generate .wr_en(hdr_flit_wr[i]), // Write enable .rd_en(dst_rd_fifo[i]), // Read the next word .dout(endp_localp_num[(i+1)*ELw-1 : i*ELw]), // Data out - .full( ), - .nearly_full( ), - .recieve_more_than_0(), - .recieve_more_than_1(), + .status_o(), .reset(reset), .clk(clk) ); diff --git a/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold b/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold index 2a67880..b23be17 100755 --- a/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold +++ b/mpsoc/rtl/src_emulate/rtl/noc_emulator.vold @@ -15,7 +15,7 @@ module noc_emulator #( parameter T2 = 4, parameter T3 = 1, parameter TOPOLOGY = "MESH", - parameter ROUTE_NAME = "XY", + parameter ROUTE_NAME = "DOR", parameter C = 4, parameter Fpay = 32, parameter MUX_TYPE = "BINARY", @@ -215,7 +215,7 @@ module Jtag_traffic_gen #( parameter Fpay = 32, parameter VC_REALLOCATION_TYPE = "NONATOMIC",// "ATOMIC" , "NONATOMIC" parameter TOPOLOGY = "MESH", - parameter ROUTE_NAME = "XY", + parameter ROUTE_NAME = "DOR", parameter C = 4 , // number of flit class parameter MIN_PCK_SIZE = 2, parameter BYTE_EN=0, @@ -475,7 +475,7 @@ module traffic_gen_ram #( parameter Fpay = 32, parameter VC_REALLOCATION_TYPE = "NONATOMIC",// "ATOMIC" , "NONATOMIC" parameter TOPOLOGY = "MESH", - parameter ROUTE_NAME = "XY", + parameter ROUTE_NAME = "DOR", parameter C = 4, // number of flit class parameter RAM_Aw=7, parameter STATISTIC_NUM=8, // the last 8 rows of RAM is reserved for collecting statistic values; diff --git a/mpsoc/rtl/src_modelsim/traffic_pattern.sv b/mpsoc/rtl/src_modelsim/traffic_pattern.sv index 2da7650..6c6c530 100755 --- a/mpsoc/rtl/src_modelsim/traffic_pattern.sv +++ b/mpsoc/rtl/src_modelsim/traffic_pattern.sv @@ -270,11 +270,11 @@ module pck_dst_gen_unicast input custom_traffic_en; input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; generate - if ( ADDR_DIMENSION == 2) begin :two_dim - two_dimension_pck_dst_gen #( + if ( IS_2D_TOPO | IS_3D_TOPO) begin : MD_ + multi_dimension_pck_dst_gen #( .TRAFFIC(TRAFFIC), .HOTSPOT_NODE_NUM(HOTSPOT_NODE_NUM) - ) the_two_dimension_pck_dst_gen ( + ) the_multi_dim_pck_dst_gen ( .reset(reset), .clk(clk), .en(en), @@ -309,9 +309,9 @@ module pck_dst_gen_unicast endmodule /********************************** -* two_dimension_pck_dst_gen +* multi_dimension_pck_dst_gen **********************************/ -module two_dimension_pck_dst_gen +module multi_dimension_pck_dst_gen #( parameter TRAFFIC = "RANDOM", parameter HOTSPOT_NODE_NUM = 4 @@ -332,51 +332,37 @@ module two_dimension_pck_dst_gen localparam PCK_CNTw = log2(MAX_PCK_NUM+1), HOTSPOT_NUM= (TRAFFIC=="HOTSPOT")? HOTSPOT_NODE_NUM : 1; - input reset,clk,en; input [NEw-1 : 0] core_num; input [PCK_CNTw-1 : 0] pck_number; input [EAw-1 : 0] current_e_addr; - output [EAw-1 : 0] dest_e_addr; + output logic [EAw-1 : 0] dest_e_addr; output valid_dst; input hotspot_t hotspot_info [HOTSPOT_NUM-1 : 0]; input [NEw-1 : 0] custom_traffic_t; input custom_traffic_en; - wire [NXw-1 : 0] current_x; - wire [NYw-1 : 0] current_y; - wire [NLw-1 : 0] current_l; - wire [NXw-1 : 0] dest_x; - wire [NYw-1 : 0] dest_y; - wire [NLw-1 : 0] dest_l; + regular_topo_endp_addr_t current_addr, dest_addr; + always_comb begin + current_addr = regular_topo_endp_addr_t'(current_e_addr); + //for 2d we need to re-extact the l + current_addr.l=current_e_addr[EAw-1: EAw-NLw]; + end - regular_topo_endp_addr_decode src_addr_decode ( - .e_addr(current_e_addr), - .ex(current_x), - .ey(current_y), - .el(current_l), - .valid( ) - ); wire off_flag; - wire [NEw-1 : 0] dest_ip_num; + wire [NEw-1 : 0] dest_ip_num; genvar i; - generate if (TRAFFIC == "RANDOM") begin logic [6 : 0] rnd_reg; always @(posedge clk ) begin if(en | `pronoc_reset) begin rnd_reg = $urandom_range(NE-1,0); - if(SELF_LOOP_EN == 0) while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core - + if(SELF_LOOP_EN == 0) while(rnd_reg==core_num) rnd_reg = $urandom_range(NE-1,0);// get a random IP core, make sure its not same as sender core end end assign dest_ip_num = rnd_reg; - endp_addr_encoder addr_encoder ( - .id_in(dest_ip_num), - .code_out(dest_e_addr) - ); - + endp_addr_encoder addr_encoder (.id_in(dest_ip_num), .code_out(dest_e_addr)); end else if (TRAFFIC == "HOTSPOT") begin hot_spot_dest_gen #( .HOTSPOT_NUM(HOTSPOT_NUM), @@ -391,110 +377,87 @@ module two_dimension_pck_dst_gen .core_num(core_num), .off_flag(off_flag) ); - endp_addr_encoder addr_encoder ( - .id_in(dest_ip_num), - .code_out(dest_e_addr) - ); + endp_addr_encoder addr_encoder (.id_in(dest_ip_num), .code_out(dest_e_addr)); + end else if( TRAFFIC == "BIT_REVERSE") begin :bitreverse + for(i=0; i<(EAw); i=i+1'b1) begin :lp //reverse the address + assign dest_e_addr[i] = current_e_addr [((EAw)-1)-i]; + end + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); + end else if( TRAFFIC == "BIT_COMPLEMENT") begin :bitcomp + assign dest_e_addr = ~ current_e_addr; + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); end else if( TRAFFIC == "TRANSPOSE1") begin - assign dest_x = NX-current_y-1; - assign dest_y = NY-current_x-1; - assign dest_l = NL-current_l-1; - assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - - endp_addr_decoder enc - ( - .code_in(dest_e_addr), - .id_out(dest_ip_num) - ); - + assign dest_addr.x = (NZ==1 && NY==1)? NX-current_addr.x-1 : NY-current_addr.y-1 ; + assign dest_addr.y = (NZ==1)? NX-current_addr.x-1 : NZ-current_addr.z-1 ; + assign dest_addr.z = NX-current_addr.x-1; + assign dest_addr.l = NL-current_addr.l-1; + always @(*) begin + dest_e_addr = EAw'(dest_addr); + if(NL>1) dest_e_addr[EAw-1: EAw-NLw]=dest_addr.l; + end + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); end else if( TRAFFIC == "TRANSPOSE2") begin :transpose2 - assign dest_x = current_y; - assign dest_y = current_x; - assign dest_l = current_l; - assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - endp_addr_decoder enc ( - .code_in(dest_e_addr), - .id_out(dest_ip_num) - ); - end else if( TRAFFIC == "BIT_REVERSE") begin :bitreverse - - for(i=0; i<(EAw); i=i+1'b1) begin :lp//reverse the address - assign dest_ip_num[i] = current_e_addr [((EAw)-1)-i]; + assign dest_addr.x = (NZ==1 && NY==1)? NX-current_addr.x-1 : current_addr.y; + assign dest_addr.y = ( NZ==1)? current_addr.x : current_addr.z; + assign dest_addr.z = current_addr.x; + assign dest_addr.l = current_addr.l; + always @(*) begin + dest_e_addr = EAw'(dest_addr); + if(NL>1) dest_e_addr[EAw-1: EAw-NLw]=dest_addr.l; end - - endp_addr_encoder addr_encoder( - .id_in(dest_ip_num), - .code_out(dest_e_addr) - ); - - end else if( TRAFFIC == "BIT_COMPLEMENT") begin :bitcomp - assign dest_x = ~current_x; - assign dest_y = ~current_y; - assign dest_l = ~dest_l; - assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - endp_addr_decoder enc ( - .code_in(dest_e_addr), - .id_out(dest_ip_num) - ); + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); end else if( TRAFFIC == "TORNADO" ) begin :tornado //[(x+(k/2-1)) mod k, (y+(k/2-1)) mod k], - assign dest_x = (current_x> ((NX+1)/2))? current_x- ((NX+1)/2) -1 : (NX/2)+current_x-1; // = ((current_x + ((NX/2)-1))%NX); - assign dest_y = (current_y> ((NY+1)/2))? current_y- ((NY+1)/2) -1 : (NY/2)+current_y-1; // = ((current_y + ((NY/2)-1))%NY); - assign dest_l = current_l; - assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - - endp_addr_decoder enc ( - .code_in(dest_e_addr), - .id_out(dest_ip_num) - ); + assign dest_addr.x = (current_addr.x> ((NX+1)/2))? current_addr.x- ((NX+1)/2) -1 : (NX/2)+current_addr.x-1; // = ((current_x + ((NX/2)-1))%NX); + assign dest_addr.y = (current_addr.y> ((NY+1)/2))? current_addr.y- ((NY+1)/2) -1 : (NY/2)+current_addr.y-1; // = ((current_y + ((NY/2)-1))%NY); + assign dest_addr.z = (current_addr.z> ((NZ+1)/2))? current_addr.z- ((NZ+1)/2) -1 : (NZ/2)+current_addr.z-1; // = ((current_z + ((NZ/2)-1))%NZ); + assign dest_addr.l = current_addr.l; + always @(*) begin + dest_e_addr = EAw'(dest_addr); + if(NL>1) dest_e_addr[EAw-1: EAw-NLw]=dest_addr.l; + end + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); end else if( TRAFFIC == "NEIGHBOR") begin :neighbor //dx = sx + 1 mod k - assign dest_x = (current_x + 1) >= NX? 0 : (current_x + 1); - assign dest_y = (current_y + 1) >= NY? 0 : (current_y + 1); - assign dest_l = current_l; - assign dest_e_addr = (T3==1)? {dest_y,dest_x} : {dest_l,dest_y,dest_x}; - endp_addr_decoder enc( - .code_in(dest_e_addr), - .id_out(dest_ip_num) - ); + assign dest_addr.x = ((current_addr.x + 1) >= NX) ? 0 : (current_addr.x + 1); + assign dest_addr.y = ((current_addr.y + 1) >= NY) ? 0 : (current_addr.y + 1); + assign dest_addr.z = ((current_addr.z + 1) >= NZ) ? 0 : (current_addr.z + 1); + assign dest_addr.l = current_addr.l; + always @(*) begin + dest_e_addr = EAw'(dest_addr); + if(NL>1) dest_e_addr[EAw-1: EAw-NLw]=dest_addr.l; + end + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); end else if( TRAFFIC == "SHUFFLE") begin: shuffle - //di = si−1 mod b + //di = si-1 mod b for(i=1; i<(EAw); i=i+1'b1) begin :lp//reverse the address - assign dest_ip_num[i] = current_e_addr [i-1]; + assign dest_e_addr[i] = current_e_addr [i-1]; end - assign dest_ip_num[0] = current_e_addr [EAw-1]; - endp_addr_encoder addr_encoder( - .id(dest_ip_num), - .code(dest_e_addr) - ); + assign dest_e_addr[0] = current_e_addr [EAw-1]; + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); end else if(TRAFFIC == "BIT_ROTATION") begin :bitrot //di = si+1 mod b for(i=0; i<(EAw-1); i=i+1'b1) begin :lp//reverse the address - assign dest_ip_num[i] = current_e_addr [i+1]; + assign dest_e_addr[i] = current_e_addr [i+1]; end - assign dest_ip_num[EAw-1] = current_e_addr [0]; - endp_addr_encoder addr_encoder( - .id_in(dest_ip_num), - .code_out(dest_e_addr) - ); + assign dest_e_addr[EAw-1] = current_e_addr [0]; + endp_addr_decoder enc (.code_in(dest_e_addr),.id_out(dest_ip_num)); end else if(TRAFFIC == "CUSTOM" )begin - assign dest_ip_num = custom_traffic_t; endp_addr_encoder addr_encoder ( .id_in(dest_ip_num), .code_out(dest_e_addr) ); assign off_flag = ~custom_traffic_en; - end else begin initial begin $display("ERROR: Undefined Traffic pattern:%s",TRAFFIC); $stop; end end - + wire valid_temp = (dest_ip_num <= (NE-1)); - + if (TRAFFIC == "HOTSPOT" || TRAFFIC == "CUSTOM") begin assign valid_dst = ~off_flag & valid_temp; end else begin diff --git a/mpsoc/rtl/src_noc/congestion_analyzer.sv b/mpsoc/rtl/src_noc/congestion_analyzer.sv index c9748ca..d616d6e 100755 --- a/mpsoc/rtl/src_noc/congestion_analyzer.sv +++ b/mpsoc/rtl/src_noc/congestion_analyzer.sv @@ -33,23 +33,12 @@ ***************************************/ //congestion analyzer based on number of occupied VCs module port_presel_based_dst_ports_vc #( - parameter PPSw=4, - parameter P = 5, - parameter V = 4 + parameter P = 5 )( ovc_status, port_pre_sel ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2 congestion_y_plus)? YDIR : XDIR; assign conjestion_cmp[X_MINUS_Y_PLUS] = (congestion_x_min > congestion_y_plus)? YDIR : XDIR; assign conjestion_cmp[X_PLUS_Y_MINUS] = (congestion_x_plus > congestion_y_min)? YDIR : XDIR; @@ -263,14 +238,12 @@ endmodule * CONGESTION_INDEX==8,10 ********************************/ module port_presel_based_dst_routers_ovc #( - parameter PPSw=4, - parameter P=5, - parameter V=4, - parameter CONGw=2 //congestion width per port + parameter P=5 )( port_pre_sel, congestion_in_all ); + import pronoc_pkg::*; localparam P_1 = P-1, CONG_ALw = CONGw* P; // congestion width per router; @@ -289,16 +262,18 @@ module port_presel_based_dst_routers_ovc #( Q1 = 1, Q2 = 2, Q0 = 0; - localparam - EAST = 0, - NORTH = 1, - WEST = 2, - SOUTH = 3; + localparam XDIR =1'b0, YDIR =1'b1; - wire [CONGw-1 : 0] congestion_in [P_1-1 : 0]; - assign {congestion_in[SOUTH],congestion_in[WEST],congestion_in[NORTH],congestion_in[EAST]} = congestion_in_all[CONG_ALw-1 : CONGw]; + wire [CONGw-1 : 0] congestion_in [P-1 : 0]; + genvar i; + generate + for(i=0;i (2**INw)-1) ? {INw{1'b1}} : INw'(MAX_IN); + // One-hot output + logic [OUT_ON_HOT_NUM-1:0] one_hot_out; + // Saturate input + logic [INw-1:0] D_clamped; + assign D_clamped = (D_in > MAX) ? MAX : D_in; + // Generate one-hot bins genvar i; - generate - for(i=0;i< OUT_ON_HOT_NUM;i=i+1)begin :lp - /* verilator lint_off WIDTH */ - if(i==0) begin : i0 assign one_hot_out[i]= (D_in <= (MAX_IN /OUT_ON_HOT_NUM)); end - else begin :ib0 assign one_hot_out[i]= ((D_in> ((MAX_IN *i)/OUT_ON_HOT_NUM)) && (D_in<= ((MAX_IN *(i+1))/OUT_ON_HOT_NUM))); end - /* verilator lint_on WIDTH */ - end//for + generate + for (i = 0; i < OUT_ON_HOT_NUM; i++) begin : BIN_GEN + localparam LOW = (MAX_IN * i) / OUT_ON_HOT_NUM; + localparam HIGH = (MAX_IN * (i+1)) / OUT_ON_HOT_NUM; + assign one_hot_out[i] = + (i == 0) ? (D_clamped < INw'(HIGH)) : // first bin: include MIN_IN + (i == OUT_ON_HOT_NUM-1) ? (D_clamped >= INw'(LOW)) : // last bin: include MAX_IN + (D_clamped >= INw'(LOW)) && (D_clamped < INw'(HIGH)); + end endgenerate - - one_hot_to_bin#( + // Convert one-hot to binary + one_hot_to_bin #( .ONE_HOT_WIDTH(OUT_ON_HOT_NUM) - )cnv ( + ) cnv ( .one_hot_code(one_hot_out), .bin_code(Q_out) ); endmodule + /************************** - congestion_out_gen +* congestion_out_gen *************************/ module congestion_out_gen #( - parameter P=5, - parameter V=4, - parameter ROUTE_TYPE ="ADAPTIVE", - parameter CONGESTION_INDEX=2, - parameter CONGw=2 + parameter P=5 )( ivc_request_all, ivc_num_getting_sw_grant, @@ -950,10 +861,10 @@ module congestion_out_gen #( clk, reset ); - -localparam - PV = P*V, - CONG_ALw = CONGw* P; // congestion width per router;; + import pronoc_pkg::*; + localparam + PV = P*V, + CONG_ALw = CONGw* P; // congestion width per router;; input [PV-1 : 0] ovc_avalable_all; input [PV-1 : 0] ivc_request_all; @@ -962,22 +873,23 @@ localparam input clk,reset; wire [CONG_ALw-1 : 0] congestion_out_all_next; + wire [V-1 : 0] ovc_avalable [P-1 : 0]; + genvar i; generate + for (i=0;i 2) begin :mwb2 wire [MUX_SEL_WIDTH-1 : 0] mux_sel; - wire [DEPTH_DATA_WIDTH-1 : 0] depth_2; - wire empty; + wire [DEPTHw-1 : 0] depth_2; wire out_sel ; if(DATA_WIDTH>1) begin :wb1 wire [MAX_DEPTH-2 : 0] mux_in [DATA_WIDTH-1 :0]; wire [DATA_WIDTH-1 : 0] mux_out; reg [MAX_DEPTH-2 : 0] shiftreg [DATA_WIDTH-1 :0]; - for(i=0;i= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; - assign recieve_more_than_0 = ~ empty; - assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== DEPTH_DATA_WIDTH'(1) ); - assign out_sel = (recieve_more_than_1) ? 1'b1 : 1'b0; - assign out_ld = (depth !=DEPTH_DATA_WIDTH'(0) )? rd_en : wr_en; - assign depth_2 = depth - DEPTH_DATA_WIDTH'(2); + assign out_sel = (status_o.has_multiple) ? 1'b1 : 1'b0; + assign out_ld = (depth !=DEPTHw'(0) )? rd_en : wr_en; + assign depth_2 = depth - DEPTHw'(2); assign mux_sel = depth_2[MUX_SEL_WIDTH-1 : 0]; - end else if ( MAX_DEPTH == 2) begin :mw2 - reg [DATA_WIDTH-1 : 0] din_f; - always @(posedge clk ) begin if(wr_en) din_f <= din; end //always - - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; assign out_ld = (depth !=0 )? rd_en : wr_en; - assign recieve_more_than_0 = (depth != {DEPTH_DATA_WIDTH{1'b0}}); - assign recieve_more_than_1 = ~( depth == 0 || depth== 1 ); - assign dout_next = (recieve_more_than_1) ? din_f : din; - + assign dout_next = (status_o.has_multiple) ? din_f : din; end else begin :mw1 // MAX_DEPTH == 1 assign out_ld = wr_en; assign dout_next = din; - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full= 1'b1; - assign recieve_more_than_0 = full; - assign recieve_more_than_1 = 1'b0; end endgenerate - always_ff @ (`pronoc_clk_reset_edge )begin - if(`pronoc_reset) begin - depth <= {DEPTH_DATA_WIDTH{1'b0}}; - dout <= {DATA_WIDTH{1'b0}}; - end else begin - depth <= depth_next; - dout <= dout_next_ld; - end + + always_ff @ (`pronoc_clk_reset_edge ) begin + if(`pronoc_reset) begin + depth <= {DEPTHw{1'b0}}; + dout <= {DATA_WIDTH{1'b0}}; + end else begin + depth <= depth_next; + dout <= dout_next_ld; end + end always_comb begin depth_next = depth; @@ -614,22 +572,31 @@ module fwft_fifo #( if (wr_en & ~rd_en) depth_next = depth + 1'h1; else if (~wr_en & rd_en) depth_next = depth - 1'h1; if (out_ld) dout_next_ld = dout_next; + status_o.full = (depth == MAX_DEPTH [DEPTHw-1 : 0]); + status_o.nearly_full = + (MAX_DEPTH == 1)? 1'b1 : + (depth >= MAX_DEPTH [DEPTHw-1 : 0] -1'b1); + status_o.empty = (depth == {DEPTHw{1'b0}}); + status_o.has_data = ~ status_o.empty; + status_o.has_multiple = + (MAX_DEPTH == 1)? 1'b0 : + ~( depth == DEPTHw'(0) || depth== DEPTHw'(1) ); end//always -/********************************************* -* Validating Parameters/Simulation -*********************************************/ + /********************************************* + * Validating Parameters/Simulation + *********************************************/ `ifdef SIMULATION always @(posedge clk) begin - if (wr_en & ~rd_en & full) begin + if (wr_en & ~rd_en & status_o.full) begin $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); $finish; end - if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == 0) begin + if (rd_en & status_o.empty & IGNORE_SAME_LOC_RD_WR_WARNING == 0) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin + if (rd_en & ~wr_en & status_o.empty & (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end @@ -637,14 +604,13 @@ module fwft_fifo #( `endif//SIMULATION endmodule -/********************* - - fwft_fifo_with_output_clear - each individual output bit has - its own clear signal - - **********************/ - +/*************************** + * + * fwft_fifo_with_output_clear + * each individual output bit has + * its own clear signal + * + ***************************/ module fwft_fifo_with_output_clear #( parameter DATA_WIDTH = 2, parameter MAX_DEPTH = 2, @@ -652,59 +618,42 @@ module fwft_fifo_with_output_clear #( ) ( din, // Data in wr_en, // Write enable - rd_en, // Read the next word dout, // Data out - full, - nearly_full, - recieve_more_than_0, - recieve_more_than_1, + rd_en, // Read the next word + status_o,// fifo status reset, clk, clear ); - input [DATA_WIDTH-1:0] din; - input wr_en; - input rd_en; - output logic [DATA_WIDTH-1:0] dout; - output full; - output nearly_full; - output recieve_more_than_0; - output recieve_more_than_1; - input reset; - input clk; + import pronoc_pkg::*; + input [DATA_WIDTH-1:0] din; // Data in + input wr_en; // Write enable + input rd_en; // Read the next word + output logic [DATA_WIDTH-1:0] dout; // Data out + input reset, clk; + output fifo_stat_t status_o; input [DATA_WIDTH-1:0] clear; - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log22) begin :mwb2 wire [MUX_SEL_WIDTH-1 : 0] mux_sel; - wire [DEPTH_DATA_WIDTH-1 : 0] depth_2; - wire empty; + wire [DEPTHw-1 : 0] depth_2; wire out_sel ; if(DATA_WIDTH>1) begin :wb1 wire [MAX_DEPTH-2 : 0] mux_in [DATA_WIDTH-1 :0]; wire [DATA_WIDTH-1 : 0] mux_out; reg [MAX_DEPTH-2 : 0] shiftreg [DATA_WIDTH-1 :0]; - for(i=0;i= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; - assign recieve_more_than_0 = ~ empty; - assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); - assign out_sel = (recieve_more_than_1) ? 1'b1 : 1'b0; + assign out_sel = (status_o.has_multiple) ? 1'b1 : 1'b0; assign out_ld = (depth !=0 )? rd_en : wr_en; assign depth_2 = depth-'d2; assign mux_sel = depth_2[MUX_SEL_WIDTH-1 : 0]; - end else if ( MAX_DEPTH == 2) begin :mw2 - reg [DATA_WIDTH-1 : 0] din_f; - always @(posedge clk ) begin if(wr_en) din_f <= din; end //always - - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; assign out_ld = (depth !=0 )? rd_en : wr_en; - assign recieve_more_than_0 = (depth != {DEPTH_DATA_WIDTH{1'b0}}); - assign recieve_more_than_1 = ~( depth == 0 || depth== 1 ); - assign dout_next = (recieve_more_than_1) ? din_f : din; - + assign dout_next = (status_o.has_multiple) ? din_f : din; end else begin :mw1 // MAX_DEPTH == 1 assign out_ld = wr_en; assign dout_next = din; - assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0]; - assign nearly_full= 1'b1; - assign recieve_more_than_0 = full; - assign recieve_more_than_1 = 1'b0; end endgenerate always_ff @ (`pronoc_clk_reset_edge) begin @@ -781,6 +707,15 @@ module fwft_fifo_with_output_clear #( depth_next = depth; if (wr_en & ~rd_en) depth_next = depth + 1'h1; else if (~wr_en & rd_en) depth_next = depth - 1'h1; + status_o.full = (depth == MAX_DEPTH [DEPTHw-1 : 0]); + status_o.nearly_full = + (MAX_DEPTH == 1)? 1'b1 : + (depth >= MAX_DEPTH [DEPTHw-1 : 0] -1'b1); + status_o.empty = (depth == {DEPTHw{1'b0}}); + status_o.has_data = ~ status_o.empty; + status_o.has_multiple = + (MAX_DEPTH == 1)? 1'b0 : + ~( depth == DEPTHw'(0) || depth== DEPTHw'(1) ); end//always always_comb begin @@ -791,22 +726,21 @@ module fwft_fifo_with_output_clear #( end end - -/********************************************* -* Validating Parameters/Simulation -*********************************************/ + /********************************************* + * Validating Parameters/Simulation + *********************************************/ `ifdef SIMULATION always @(posedge clk) begin if(`pronoc_reset==0)begin - if (wr_en && ~rd_en && full) begin + if (wr_en && ~rd_en && status_o.full) begin $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); $finish; end - if (rd_en && !recieve_more_than_0 && (IGNORE_SAME_LOC_RD_WR_WARNING == 0)) begin + if (rd_en && status_o.empty && (IGNORE_SAME_LOC_RD_WR_WARNING == 0)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - if (rd_en && ~wr_en && !recieve_more_than_0 && (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin + if (rd_en && ~wr_en && status_o.empty && (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end @@ -815,64 +749,63 @@ module fwft_fifo_with_output_clear #( `endif // SIMULATION endmodule -/*************** -fwft_fifo_bram -****************/ +/*************************** +*fwft_fifo_bram +* An FWFT FIFO implementation based on BRAMs +* optimized for low LUTs utilization. +***************************/ module fwft_fifo_bram #( parameter DATA_WIDTH = 2, parameter MAX_DEPTH = 2, parameter IGNORE_SAME_LOC_RD_WR_WARNING=1 // 1 : "YES" , 0: "NO" - ) ( - input [DATA_WIDTH-1:0] din, // Data in - input wr_en, // Write enable - input rd_en, // Read the next word - output [DATA_WIDTH-1:0] dout, // Data out - output full, - output nearly_full, - output recieve_more_than_0, - output recieve_more_than_1, - input reset, - input clk + )( + din, // Data in + wr_en, // Write enable + rd_en, // Read the next word + dout, // Data out + stat_o, + reset, + clk ); + import pronoc_pkg::*; + input [DATA_WIDTH-1:0] din; // Data in + input wr_en; // Write enable + input rd_en; // Read the next word + output [DATA_WIDTH-1:0] dout; // Data out + output fifo_stat_t stat_o; + input reset; + input clk; - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2= MAX_DEPTH [DEPTH_DATA_WIDTH-1 : 0] -1'b1; - assign empty = depth == {DEPTH_DATA_WIDTH{1'b0}}; - assign recieve_more_than_0 = ~ empty; - assign recieve_more_than_1 = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} || depth== 1 ); + assign stat_o.full = (depth == MAX_DEPTH [DEPTHw-1 : 0]); + assign stat_o.nearly_full = (depth >= MAX_DEPTH [DEPTHw-1 : 0] -1'b1); + assign stat_o.empty = (depth == {DEPTHw{1'b0}}); + assign stat_o.has_data = ~(depth == {DEPTHw{1'b0}}); + assign stat_o.has_multiple = ~((depth == DEPTHw'(0)) || (depth == DEPTHw'(1))); `ifdef SIMULATION always @(posedge clk) begin - if (wr_en & ~rd_en & full) begin + if (wr_en & ~rd_en & stat_o.full) begin $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH); $finish; end - if (rd_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == 0)) begin + if (rd_en & stat_o.empty & (IGNORE_SAME_LOC_RD_WR_WARNING == 0)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end - if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin + if (rd_en & ~wr_en & stat_o.empty & (IGNORE_SAME_LOC_RD_WR_WARNING == 1)) begin $display("%t ERROR: Attempt to read an empty FIFO: %m", $time); $finish; end end // always `endif // SIMULATION - endmodule /********************************** - bram_based_fifo - *********************************/ +* bram_based_fifo +*********************************/ module bram_based_fifo #( parameter Dw = 72,//data_width parameter B = 10// buffer num @@ -949,22 +878,11 @@ module bram_based_fifo #( wr_en, rd_en, dout, - full, - nearly_full, - empty, + stat_o, reset, clk ); - - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log2=Bint2; // B-1 - assign empty = depth == {DEPTHw{1'b0}}; - + always_comb begin + stat_o.full = depth == B [DEPTHw-1 : 0]; + stat_o.nearly_full = depth >=Bint2; // B-1 + stat_o.empty = depth == {DEPTHw{1'b0}}; + stat_o.has_data = ~(depth == {DEPTHw{1'b0}}); + stat_o.has_multiple = ~((depth == DEPTHw'(0)) || (depth == DEPTHw'(1))); + end `ifdef SIMULATION always @(posedge clk) begin if(`pronoc_reset==1'b0)begin @@ -1041,5 +956,4 @@ module bram_based_fifo #( end//~reset end `endif - endmodule diff --git a/mpsoc/rtl/src_noc/fmesh.sv b/mpsoc/rtl/src_noc/fmesh.sv index 88e5bc8..bb8642f 100644 --- a/mpsoc/rtl/src_noc/fmesh.sv +++ b/mpsoc/rtl/src_noc/fmesh.sv @@ -79,15 +79,9 @@ endmodule module fmesh_destp_generator #( - parameter ROUTE_NAME = "XY", - parameter ROUTE_TYPE = "DETERMINISTIC", parameter P=5, - parameter DSTPw=4, - parameter NL=1, parameter PLw=1, - parameter PPSw=4, - parameter SW_LOC=0, - parameter SELF_LOOP_EN=0 + parameter SW_LOC=0 )( dest_port_out, dest_port_coded, @@ -96,7 +90,7 @@ module fmesh_destp_generator #( port_pre_sel, odd_column ); - + import pronoc_pkg::*; localparam P_1 = (SELF_LOOP_EN )? P : P-1; input [DSTPw-1 : 0] dest_port_coded; @@ -109,14 +103,9 @@ module fmesh_destp_generator #( wire [P_1-1 : 0] dest_port_in; fmesh_destp_decoder #( - .ROUTE_TYPE(ROUTE_TYPE), .P(P), - .DSTPw(DSTPw), - .NL(NL), .PLw(PLw), - .PPSw(PPSw), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) + .SW_LOC(SW_LOC) ) decoder ( .dest_port_coded(dest_port_coded), .dest_port_out(dest_port_in), @@ -130,14 +119,9 @@ endmodule module fmesh_destp_decoder #( - parameter ROUTE_TYPE="DETERMINISTIC", parameter P=6, - parameter DSTPw=4, - parameter NL=2, parameter PLw=1, - parameter PPSw=4, - parameter SW_LOC=0, - parameter SELF_LOOP_EN=0 + parameter SW_LOC=0 )( dest_port_coded, endp_localp_num, @@ -145,6 +129,7 @@ module fmesh_destp_decoder #( swap_port_presel, port_pre_sel ); + import pronoc_pkg::*; localparam P_1 = (SELF_LOOP_EN )? P : P-1; input [DSTPw-1 : 0] dest_port_coded; @@ -159,7 +144,7 @@ module fmesh_destp_decoder #( assign {x,y,a,b} = dest_port_coded; wire [PPSw-1:0] port_pre_sel_final; assign port_pre_sel_final = - ( ROUTE_TYPE == "DETERMINISTIC") ? {PPSw{1'b1}}: + ( IS_DETERMINISTIC ) ? {PPSw{1'b1}}: (swap_port_presel) ? ~port_pre_sel : port_pre_sel; always_comb begin case({a,b}) @@ -176,7 +161,7 @@ module fmesh_destp_decoder #( endp_localp_onehot = {P{1'b0}}; endp_localp_onehot[endp_localp_num] = 1'b1; end - + generate if(NL>1) begin :multi assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ @@ -184,19 +169,17 @@ module fmesh_destp_decoder #( end else begin assign destport_onehot =(portout[0])? endp_localp_onehot : /*select local destination*/ portout; - end - if(SELF_LOOP_EN == 0) begin :nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) remove_sw_loc ( - .destport_in(destport_onehot), - .destport_out(dest_port_out) - ); - end else begin: slp - assign dest_port_out = destport_onehot; - end - endgenerate + end + endgenerate + + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(P), + .SW_LOC(SW_LOC) + ) fix ( + .destport_in(destport_onehot), + .destport_out(dest_port_out) + ); endmodule diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index b7cfb27..0119721 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -180,6 +180,46 @@ module extract_header_flit_info # ( assign hdr_flit_wr_o= (flit_in_wr & hdr_flg_o )? vc_num_o : {V{1'b0}}; endmodule +module header_flit_info #( + parameter DATA_w = 0 +)( + flit, + hdr_flit, + data_o +); + + import pronoc_pkg::*; + + localparam + Dw = (DATA_w==0)? 1 : DATA_w; + + input flit_t flit; + output hdr_flit_t hdr_flit; + output [Dw-1 : 0] data_o; + + localparam + DATA_LSB= MSB_BE+1, + DATA_MSB= (DATA_LSB + DATA_w)1)? flit.payload [CLASS_MSB : CLASS_LSB] : {Cw{1'b0}}; + hdr_flit.weight = (IS_WRRA)? flit.payload [WEIGHT_MSB : WEIGHT_LSB] : {WEIGHTw{1'b0}}; + hdr_flit.be = (BYTE_EN)? flit.payload [BE_MSB : BE_LSB]: {BEw{1'b0}}; + end + + wire [OFFSETw-1 : 0 ] offset = flit.payload [DATA_MSB : DATA_LSB]; + generate + if(Dw > OFFSETw) begin : if1 + assign data_o={{(Dw-OFFSETw){1'b0}},offset}; + end else begin : if2 + assign data_o=offset[Dw-1 : 0]; + end + endgenerate +endmodule /*********************************** * flit_update diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index ac65f6e..f04e998 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -251,11 +251,7 @@ module inout_ports #( ); congestion_out_gen #( - .P(P), - .V(V), - .ROUTE_TYPE(ROUTE_TYPE), - .CONGESTION_INDEX(CONGESTION_INDEX), - .CONGw(CONGw) + .P(P) ) congestion_out ( .ovc_avalable_all(ovc_avalable_all), .ivc_request_all(ivc_request_all), @@ -267,7 +263,7 @@ module inout_ports #( genvar i; generate - + if( SSA_EN == 1 ) begin : ssa ss_allocator #( .P(P) @@ -313,14 +309,12 @@ module inout_ports #( endmodule /****************** - output_vc_status +* output_vc_status ******************/ module output_vc_status #( - parameter V = 4, - parameter B = 16, + parameter PORT_B = 16, parameter CAND_VC_SEL_MODE = 0, // 0: use arbiteration between not full vcs, 1: select the vc with most availble free space - parameter CRDTw = 4, - parameter HETERO_VC=0 + parameter CRDTw = 4 )( credit_init_val_in, ovc_presence, @@ -334,7 +328,7 @@ module output_vc_status #( clk, reset ); - + import pronoc_pkg::*; input [V-1 : 0] [CRDTw-1 : 0 ] credit_init_val_in ; input [V-1 : 0] ovc_presence; input [V-1 : 0] wr_in; @@ -347,16 +341,7 @@ module output_vc_status #( input clk; input reset; - function integer log2; - input integer number; begin - log2=(number <=1) ? 1: 0; - while(2**log20 && vc_num_in[j] && t1[j]==0)begin - $display("%t : Parser:current_r=%h, class_in=%h, destport_in=%h, dest_e_addr_in=%h, src_e_addr_in=%h, vc_num_in=%h,hdr_flit_wr=%h, hdr_flg_in=%h,tail_flg_in=%h ",$time,current_r_addr, class_in, destport_in, dest_e_addr_in, src_e_addr_in, vc_num_in,hdr_flit_wr, hdr_flg_in,tail_flg_in); + if(flit_in_wr > 0 && flit_in.vc[j] && t1[j]==0)begin + $display("%t : Parser:current_r=%h, hdr_info:%p, vc_num_in=%h,hdr_flit_wr=%h",$time,current_r_addr, hdr_flit_i, flit_in.vc,hdr_flit_wr); t1[j]<=1; end end @@ -993,7 +894,7 @@ module destp_generator #( Pw = log2(P), PLw = (IS_FMESH) ? Pw : ELw, P_1 = (SELF_LOOP_EN )? P : P-1; - + input [DSTPw-1 : 0] dest_port_encoded; input [PLw-1 : 0] endp_localp_num; output [P_1-1: 0] dest_port_out; @@ -1004,18 +905,14 @@ module destp_generator #( generate if( ~IS_UNICAST ) begin : muticast - // destination port is not coded for multicast/broadcast - if( SELF_LOOP_EN==0) begin : nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) remove_sw_loc ( - .destport_in(dest_port_encoded), - .destport_out(dest_port_out) - ); - end else begin : slp - assign dest_port_out = dest_port_encoded; - end + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(P), + .SW_LOC(SW_LOC) + ) fix_sw_loc ( + .destport_in(dest_port_encoded), + .destport_out(dest_port_out) + ); end else if( IS_FATTREE ) begin : fat fattree_destp_generator #( .K(T1), @@ -1042,16 +939,9 @@ module destp_generator #( ); end else if( IS_REGULAR_TOPO ) begin : regular regular_topo_destp_generator #( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), .P(P), - .DSTPw(DSTPw), - .NL(NL), .PLw(PLw), - .PPSw(PPSw), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) + .SW_LOC(SW_LOC) ) destp_generator ( .dest_port_coded(dest_port_encoded), .endp_localp_num(endp_localp_num), @@ -1062,15 +952,9 @@ module destp_generator #( ); end else if ( IS_FMESH ) begin :fmesh fmesh_destp_generator #( - .ROUTE_NAME(ROUTE_NAME), - .ROUTE_TYPE(ROUTE_TYPE), .P(P), - .DSTPw(DSTPw), - .NL(NL), .PLw(PLw), - .PPSw(PPSw), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) + .SW_LOC(SW_LOC) ) destp_generator ( .dest_port_coded(dest_port_encoded), .endp_localp_num(endp_localp_num), @@ -1132,19 +1016,14 @@ module custom_topology_destp_decoder #( dest_port_one_hot[dest_port_in_encoded] = 1'b1; end - generate - if( SELF_LOOP_EN==0) begin : nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) remove_sw_loc ( - .destport_in(dest_port_one_hot[P-1 : 0]), - .destport_out(dest_port_out) - ); - end else begin : slp - assign dest_port_out = dest_port_one_hot; - end - endgenerate + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(dest_port_one_hot[P-1 : 0]), + .destport_out(dest_port_out) + ); `ifdef SIMULATION initial begin diff --git a/mpsoc/rtl/src_noc/mesh_3d_top.sv b/mpsoc/rtl/src_noc/mesh_3d_top.sv new file mode 100644 index 0000000..67ff523 --- /dev/null +++ b/mpsoc/rtl/src_noc/mesh_3d_top.sv @@ -0,0 +1,151 @@ +`include "pronoc_def.v" +/********************************************************************** +** File: mesh_cluster.sv +** +** Copyright (C) 2014-2017 Alireza Monemi +** +** This file is part of ProNoC +** +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. +** +** ProNoC 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 Lesser General +** Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . +** +** +** +** Description: +** A `mesh_cluster` refers to a group of interconnected routers arranged in a **3D Mesh topology** +** within a larger **Multi-Mesh NoC** for chiplets. In this architecture, each chiplet functions +** as an independent cluster of nodes, featuring its own local mesh-based communication network. +** +** Each router in the `mesh_cluster` drives two I/O channels: +** 1. **Endpoint Channel** – Connects to processing elements (PEs) or memory endpoints. +** 2. **Vertical Link Channel** – Facilitates inter-cluster communication. +** +** If an endpoint or vertical link is not present in the target Multi-Mesh topology, +** the corresponding input is tied to **ground**, enabling synthesis optimizations +** that effectively remove unused logic. +** +***************************************/ + +module mesh_3d_noc_top ( + reset, + clk, + chan_in_all, + chan_out_all, + router_event +); + import pronoc_pkg::*; + input clk,reset; + //Endpoints ports + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; + //Events + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; + + //indididual routers interconnect ports + smartflit_chanel_t router_chan_in [NZ-1:0][NY-1:0][NX-1:0][MAX_P-1:0]; + smartflit_chanel_t router_chan_out [NZ-1:0][NY-1:0][NX-1:0][MAX_P-1:0]; + //Unused Input channels are connected to ground + smartflit_chanel_t is_grounded; + assign is_grounded= {SMARTFLIT_CHANEL_w{1'b0}}; + + regular_topo_router_addr_t current_r_addr [NR-1:0]; + regular_topo_endp_addr_t endp_addr [NE-1:0]; + router_config_t router_config_in [NR-1 : 0]; + + genvar x,y,z,l; + generate + if(IS_MESH_3D) begin + for (z=0; z current_router_addr_i.x)? MASS:(dest_router_addr_i.x == current_router_addr_i.x)?EQUAL : LESS; + assign Dy = (dest_router_addr_i.y > current_router_addr_i.y)? MASS:(dest_router_addr_i.y == current_router_addr_i.y)?EQUAL : LESS; + assign Dz = (dest_router_addr_i.z > current_router_addr_i.z)? MASS:(dest_router_addr_i.z == current_router_addr_i.z)?EQUAL : LESS; + + always_comb begin + destport=0; + if(Dx==MASS) destport =DSTPw'(EAST); + else if(Dx==LESS) destport =DSTPw'(WEST); + else if(Dy==MASS) destport =DSTPw'(SOUTH); + else if(Dy==LESS) destport =DSTPw'(NORTH); + else if(Dz==MASS) destport =DSTPw'(UP); + else if(Dz==LESS) destport =DSTPw'(DOWN); + else destport = DSTPw'(LOCAL); + end +endmodule + diff --git a/mpsoc/rtl/src_noc/mesh_torus.sv b/mpsoc/rtl/src_noc/mesh_torus.sv index 73d6cae..5b40cd1 100755 --- a/mpsoc/rtl/src_noc/mesh_torus.sv +++ b/mpsoc/rtl/src_noc/mesh_torus.sv @@ -33,14 +33,7 @@ * ---------x * 0 | 2 ***************************/ -module regular_topo_vc_alloc_request_gen_adaptive #( - parameter ROUTE_TYPE = "FULL_ADAPTIVE", // "FULL_ADAPTIVE", "PAR_ADAPTIVE" - parameter V = 4, - parameter DSTPw=4, - parameter SSA_EN = 0, - parameter PPSw=4, - parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000 // mask scape vc, valid only for full adaptive -)( +module regular_topo_vc_alloc_request_gen_adaptive ( ovc_avalable_all, dest_port_coded_all, candidate_ovc_all, @@ -56,6 +49,7 @@ module regular_topo_vc_alloc_request_gen_adaptive #( reset, clk ); + import pronoc_pkg::*; localparam P = 5, P_1 = P-1, @@ -64,13 +58,6 @@ module regular_topo_vc_alloc_request_gen_adaptive #( VP_1 = V * P_1, PVDSTPw = PV * DSTPw; - localparam - LOCAL = 3'd0, - EAST = 3'd1, - NORTH = 3'd2, - WEST = 3'd3, - SOUTH = 3'd4; - input [PV-1 : 0] ovc_avalable_all; input [PVDSTPw-1 : 0] dest_port_coded_all; input [PV-1 : 0] ivc_request_all; @@ -85,7 +72,6 @@ module regular_topo_vc_alloc_request_gen_adaptive #( input [PV-1 : 0] ssa_ivc_num_getting_ovc_grant_all; input reset,clk; - wire [PV-1 : 0] non_assigned_ovc_request_all; wire [PV-1 : 0] y_evc_forbiden,x_evc_forbiden; wire [V-1 : 0] ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus,ovc_avb_local; @@ -93,7 +79,6 @@ module regular_topo_vc_alloc_request_gen_adaptive #( wire [PPSw-1 : 0] port_pre_sel_perport [P-1 : 0]; wire [PVV-1 : 0] candidate_ovc_x_all, candidate_ovc_y_all; - assign non_assigned_ovc_request_all = ivc_request_all & ~ovc_is_assigned_all; assign {ovc_avb_y_minus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_x_plus,ovc_avb_local} = ovc_avalable_all; assign ovc_avalable_perport[LOCAL] = {ovc_avb_x_plus,ovc_avb_x_minus,ovc_avb_y_plus,ovc_avb_y_minus}; @@ -124,8 +109,7 @@ module regular_topo_vc_alloc_request_gen_adaptive #( ); regular_topo_port_selector #( - .SW_LOC (i/V), - .PPSw(PPSw) + .SW_LOC (i/V) ) the_portsel ( .port_pre_sel (port_pre_sel_perport[i/V]), .swap_port_presel (swap_port_presel[i]), @@ -136,8 +120,6 @@ module regular_topo_vc_alloc_request_gen_adaptive #( ); regular_topo_dspt_clear_gen #( - .SSA_EN(SSA_EN), - .DSTPw(DSTPw), .SW_LOC(i/V) ) dspt_clear_gen ( .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]), @@ -154,8 +136,6 @@ module regular_topo_vc_alloc_request_gen_adaptive #( assign avc_unavailable[i] = (masked_ovc_request_all [((i+1)*V)-1 : i*V] & ~ESCAP_VC_MASK) == {V{1'b0}}; regular_topo_swap_port_presel_gen #( - .V(V), - .ESCAP_VC_MASK(ESCAP_VC_MASK), .VC_NUM(i) ) swap_presel ( .avc_unavailable(avc_unavailable[i]), @@ -179,8 +159,6 @@ endmodule module regular_topo_dspt_clear_gen #( - parameter SSA_EN = 1, - parameter DSTPw =4, parameter SW_LOC=0 )( destport_clear, @@ -188,16 +166,12 @@ module regular_topo_dspt_clear_gen #( sel, ssa_ivc_num_getting_ovc_grant ); - + import pronoc_pkg::*; output [DSTPw-1 : 0] destport_clear; input ivc_num_getting_ovc_grant; input sel; input ssa_ivc_num_getting_ovc_grant; - localparam - LOCAL = 3'd0, - EAST = 3'd1, - WEST = 3'd3; generate if ( SSA_EN==1 ) begin :predict_if if (SW_LOC == LOCAL ) begin :local_if @@ -220,18 +194,15 @@ module regular_topo_dspt_clear_gen #( endmodule -module regular_topo_mask_non_assignable_destport #( - parameter TOPOLOGY="MESH", - parameter ROUTE_NAME="XY", +module regular_topo_mask_non_assignable_destport #( parameter SW_LOC=0, - parameter P=5, - parameter SELF_LOOP_EN=0 + parameter P=5 ) ( odd_column,// use only for odd even routing dest_port_in, dest_port_out ); - + import pronoc_pkg::*; localparam P_1 = (SELF_LOOP_EN )? P : P-1; input [P_1-1 : 0 ] dest_port_in; output [P_1-1 : 0 ] dest_port_out; @@ -266,8 +237,6 @@ module regular_topo_mask_non_assignable_destport #( endgenerate regular_topo_mask_non_assignable_destport_no_self_loop # ( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), .SW_LOC(SW_LOC), .P(P) ) mask_no_self_loop ( @@ -278,8 +247,6 @@ module regular_topo_mask_non_assignable_destport #( endmodule module regular_topo_mask_non_assignable_destport_no_self_loop #( - parameter TOPOLOGY="MESH", - parameter ROUTE_NAME="XY", parameter SW_LOC=0, parameter P=5 )( @@ -287,12 +254,7 @@ module regular_topo_mask_non_assignable_destport_no_self_loop #( dest_port_in, dest_port_out ); - - localparam - EAST = 1, - NORTH = 2, - WEST = 3, - SOUTH = 4; + import pronoc_pkg::*; //port number in north port localparam N_LOCAL = 0, @@ -333,7 +295,7 @@ module regular_topo_mask_non_assignable_destport_no_self_loop #( assign dest_port_out[P_1-1:4] = dest_port_in[P_1-1:4]; //other local ports end /* verilator lint_off WIDTH */ - if ( ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY") begin :xy + if ( ROUTE_NAME == "DOR" || ROUTE_NAME == "TRANC_DOR") begin :xy /* verilator lint_on WIDTH */ if (SW_LOC == NORTH ) begin : nort_p // The port located in y axsis does not send packets to x dimension assign dest_port_out[N_LOCAL]= dest_port_in[N_LOCAL]; @@ -427,8 +389,6 @@ endmodule module regular_topo_swap_port_presel_gen #( - parameter V = 4, - parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000, // mask scape vc, valid only for full adaptive parameter VC_NUM=0 )( avc_unavailable, @@ -440,7 +400,7 @@ module regular_topo_swap_port_presel_gen #( clk, reset ); - + import pronoc_pkg::*; localparam LOCAL_VC_NUM= VC_NUM % V; input avc_unavailable; input y_evc_forbiden,x_evc_forbiden; @@ -528,8 +488,7 @@ endmodule module regular_topo_port_selector #( - parameter SW_LOC = 0, - parameter PPSw=4 + parameter SW_LOC = 0 )( port_pre_sel, dest_port_in, @@ -538,7 +497,7 @@ module regular_topo_port_selector #( y_evc_forbiden, x_evc_forbiden ); - + import pronoc_pkg::*; /************************ * * destination-port_in @@ -666,15 +625,15 @@ module mesh_line_distance_gen ( input [EAw-1 : 0] src_e_addr; input [EAw-1 : 0] dest_e_addr; output[DISTw-1: 0]distance; - wire [NXw-1 : 0]src_x,dest_x; - wire [NYw-1 : 0]src_y,dest_y; - regular_topo_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); - regular_topo_endp_addr_decode dst_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); + regular_topo_router_addr_t src_router_addr, dest_router_addr; + assign src_router_addr = regular_topo_router_addr_t'(src_e_addr); + assign dest_router_addr = regular_topo_router_addr_t'(dest_e_addr); + logic [NXw-1 : 0] x_offset; logic [NYw-1 : 0] y_offset; always_comb begin - x_offset = (src_x > dest_x) ? src_x - dest_x : dest_x - src_x; - y_offset = (src_y > dest_y) ? src_y - dest_y : dest_y - src_y; + x_offset = (src_router_addr.x > dest_router_addr.x) ? src_router_addr.x - dest_router_addr.x : dest_router_addr.x - src_router_addr.x; + y_offset = (src_router_addr.y > dest_router_addr.y) ? src_router_addr.y - dest_router_addr.y : dest_router_addr.y - src_router_addr.y; end /* verilator lint_off WIDTH */ assign distance = x_offset+y_offset+1'b1; @@ -692,8 +651,13 @@ module ring_torus_distance_gen ( output[DISTw-1: 0]distance; wire [NXw-1 : 0]src_x,dest_x; wire [NYw-1 : 0]src_y,dest_y; - regular_topo_endp_addr_decode src_addr_decode (.e_addr(src_e_addr), .ex(src_x), .ey(src_y), .el(), .valid()); - regular_topo_endp_addr_decode dest_addr_decode (.e_addr(dest_e_addr), .ex(dest_x), .ey(dest_y), .el(), .valid()); + regular_topo_router_addr_t src_router_addr, dest_router_addr; + assign src_router_addr = regular_topo_router_addr_t'(src_e_addr); + assign dest_router_addr = regular_topo_router_addr_t'(dest_e_addr); + assign src_x = src_router_addr.x; + assign src_y = src_router_addr.y; + assign dest_x = dest_router_addr.x; + assign dest_y = dest_router_addr.y; logic [NXw-1 : 0] x_offset; logic [NYw-1 : 0] y_offset; wire tranc_x_plus,tranc_x_min,tranc_y_plus,tranc_y_min,same_x,same_y; @@ -744,36 +708,26 @@ module ring_torus_distance_gen ( endmodule -module regular_topo_ssa_check_destport #( - parameter ROUTE_TYPE="DETERMINISTIC", +module two_dim_ssa_check_destport #( parameter SW_LOC = 0, - parameter P=5, - parameter DEBUG_EN = 0, - parameter DSTPw = P-1, parameter SS_PORT=0 )( destport_encoded, //exsited packet dest port destport_in_encoded, // incomming packet dest port ss_port_hdr_flit, - ss_port_nonhdr_flit + ss_port_nonhdr_flit `ifdef SIMULATION ,clk, ivc_num_getting_sw_grant, hdr_flg `endif ); - + import pronoc_pkg::*; input [DSTPw-1 : 0] destport_encoded, destport_in_encoded; output ss_port_hdr_flit, ss_port_nonhdr_flit; `ifdef SIMULATION input clk, ivc_num_getting_sw_grant,hdr_flg; `endif - //MESH, TORUS Topology p=5 - localparam - LOCAL = 0, - EAST = 1, - WEST = 3; - /************************* * destination port is coded * destination-port_in @@ -818,12 +772,8 @@ endgenerate endmodule -module line_ring_ssa_check_destport #( - parameter ROUTE_TYPE="DETERMINISTIC", +module one_dim_ssa_check_destport #( parameter SW_LOC = 0, - parameter P=3, - parameter DEBUG_EN = 0, - parameter DSTPw = P-1, parameter SS_PORT=0 )( destport_encoded, //exsited packet dest port @@ -831,9 +781,10 @@ module line_ring_ssa_check_destport #( ss_port_hdr_flit, ss_port_nonhdr_flit ); + import pronoc_pkg::*; input [DSTPw-1 : 0] destport_encoded, destport_in_encoded; output ss_port_hdr_flit, ss_port_nonhdr_flit; - wire [P-1 : 0] dest_port_num,assigned_dest_port_num; + wire [MAX_P-1 : 0] dest_port_num,assigned_dest_port_num; line_ring_decode_dstport cnv1( .dstport_one_hot(dest_port_num), @@ -859,7 +810,7 @@ module regular_topo_router_addr_decode ( localparam RXw = log2(NX), // number of node in x axis - RYw = (IS_RING | IS_LINE) ? 1 : log2(NY); // number of node in y axis + RYw = (IS_1D_TOPO) ? 1 : log2(NY); // number of node in y axis /* verilator lint_off WIDTH */ localparam [RXw-1 : 0] MAXX = (NX-1); localparam [RYw-1 : 0] MAXY = (NY-1); @@ -871,7 +822,7 @@ module regular_topo_router_addr_decode ( output valid; generate - if (IS_RING | IS_LINE) begin :oneD + if (IS_1D_TOPO) begin :D1_ assign rx = r_addr; assign ry = 1'b0; end else begin : twoD @@ -883,63 +834,32 @@ module regular_topo_router_addr_decode ( /* verilator lint_on CMPCONST */ endmodule - -module regular_topo_endp_addr_decode -( - e_addr, - ex, - ey, - el, +module regular_topo_address_validator ( + addr, valid ); import pronoc_pkg::*; - localparam - EXw = log2(NX), // number of node in x axis - EYw = (IS_RING | IS_LINE) ? 1 : log2(NY), - ELw = log2(NL); // number of node in y axis - /* verilator lint_off WIDTH */ - localparam [EXw-1 : 0] MAXX = (NX-1); - localparam [EYw-1 : 0] MAXY = (NY-1); - localparam [ELw-1 : 0] MAXL = (NL-1); - /* verilator lint_on WIDTH */ - - input [EAw-1 : 0] e_addr; - output [EXw-1 : 0] ex; - output [EYw-1 : 0] ey; - output [ELw-1 : 0] el; - output valid; - - generate - if (IS_RING | IS_LINE) begin :oneD - if(NL==1) begin:one_local - assign ex = e_addr; - assign ey = 1'b0; - assign el = 1'b0; - /* verilator lint_off CMPCONST */ - assign valid = ex<= MAXX; - /* verilator lint_on CMPCONST */ - end else begin: multi_local - assign {el,ex} = e_addr; - assign ey = 1'b0; - /* verilator lint_off CMPCONST */ - assign valid = ((ex<= MAXX) & (el<=MAXL)); - /* verilator lint_on CMPCONST */ + input [EAw-1 : 0] addr; + output logic valid; + regular_topo_endp_addr_t endp_addr; + always_comb begin + endp_addr = regular_topo_endp_addr_t'(addr); + //for 2/1d we need to re-extact the l + endp_addr.l=addr[EAw-1: EAw-NLw]; + end + always_comb begin + valid = 1'b1; + if(32'(endp_addr.x) >= NX) valid = 1'b0; + if((IS_2D_TOPO | IS_3D_TOPO) && ((NY & (NY - 1)) != 0) ) begin + if(32'(endp_addr.y) >= NY) valid = 1'b0; end - end else begin : twoD - if(NL==1)begin:one_local - assign {ey,ex} = e_addr; - assign el = 1'b0; - /* verilator lint_off CMPCONST */ - assign valid = (ex<= MAXX) & (ey <= MAXY); - /* verilator lint_on CMPCONST */ - end else begin :multi_l - assign {el,ey,ex} = e_addr; - /* verilator lint_off CMPCONST */ - assign valid = ( (ex<= MAXX) & (ey <= MAXY) & (el<=MAXL) ); - /* verilator lint_on CMPCONST */ + if(IS_3D_TOPO) begin + if(32'(endp_addr.z) >= NZ) valid = 1'b0; + end + if(NL>1) begin + if(32'(endp_addr.l) >= NL) valid = 1'b0; end end - endgenerate endmodule @@ -947,7 +867,6 @@ endmodule * Regular_topo_endp_addr_encoder * most probably it is only needed for simulation purposes ***************/ - module regular_topo_endp_addr_encoder ( id, @@ -989,16 +908,9 @@ module regular_topo_addr_coder ( endmodule module regular_topo_destp_generator #( - parameter TOPOLOGY = "MESH", - parameter ROUTE_NAME = "XY", - parameter ROUTE_TYPE = "DETERMINISTIC", parameter P=5, - parameter DSTPw=4, - parameter NL=1, parameter PLw=1, - parameter PPSw=4, - parameter SW_LOC=0, - parameter SELF_LOOP_EN=0 + parameter SW_LOC=0 )( dest_port_out, dest_port_coded, @@ -1007,46 +919,53 @@ module regular_topo_destp_generator #( port_pre_sel, odd_column ); - localparam P_1 = (SELF_LOOP_EN )? P : P-1; + import pronoc_pkg::*; + localparam + P_1 = (SELF_LOOP_EN )? P : P-1, + Pw = log2(P); input [DSTPw-1 : 0] dest_port_coded; input [PLw-1 : 0] endp_localp_num; output [P_1-1 : 0] dest_port_out; - input swap_port_presel; + input swap_port_presel; input [PPSw-1 : 0] port_pre_sel; input odd_column; wire [P_1-1 : 0] dest_port_in; generate - /* verilator lint_off WIDTH */ - if (TOPOLOGY == "RING" || TOPOLOGY == "LINE" ) begin : one_D - /* verilator lint_on WIDTH */ + if (IS_1D_TOPO) begin : D1_ line_ring_destp_decoder #( - .ROUTE_TYPE(ROUTE_TYPE), .P(P), - .DSTPw(DSTPw), - .NL(NL), .ELw(PLw), - .PPSw(PPSw), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) + .SW_LOC(SW_LOC) ) decoder ( - .dest_port_coded(dest_port_coded), + .dest_port_coded(dest_port_coded), .dest_port_out(dest_port_in), - .endp_localp_num(endp_localp_num) + .endp_localp_num(endp_localp_num) + ); + end else if (IS_MESH_3D) begin : three_D + logic [P-1 : 0] mesh_3d_one_hot_dest_port; + logic [Pw-1 : 0] local_dest_port; + always @(*) begin + local_dest_port =Pw'(endp_localp_num) + Pw'(DOWN); + mesh_3d_one_hot_dest_port = {P{1'b0}}; + if(dest_port_coded == 0 && endp_localp_num!=0 && NL >1) mesh_3d_one_hot_dest_port[local_dest_port] = 1'b1; + else mesh_3d_one_hot_dest_port[dest_port_coded] = 1'b1; + end + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(mesh_3d_one_hot_dest_port[P-1 : 0]), + .destport_out(dest_port_out) ); - end else begin :two_D regular_topo_destp_decoder #( - .ROUTE_TYPE(ROUTE_TYPE), .P(P), - .DSTPw(DSTPw), - .NL(NL), .ELw(PLw), - .PPSw(PPSw), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) + .SW_LOC(SW_LOC) ) decoder ( .dest_port_coded(dest_port_coded), .dest_port_out(dest_port_in), @@ -1058,11 +977,8 @@ module regular_topo_destp_generator #( endgenerate regular_topo_mask_non_assignable_destport #( - .TOPOLOGY(TOPOLOGY), - .ROUTE_NAME(ROUTE_NAME), .SW_LOC(SW_LOC), - .P(P), - .SELF_LOOP_EN(SELF_LOOP_EN) + .P(P) ) mask_destport ( .dest_port_in(dest_port_in), .dest_port_out(dest_port_out), @@ -1071,14 +987,9 @@ module regular_topo_destp_generator #( endmodule module regular_topo_destp_decoder #( - parameter ROUTE_TYPE="DETERMINISTIC", parameter P=6, - parameter DSTPw=4, - parameter NL=2, parameter ELw=1, - parameter PPSw=4, - parameter SW_LOC=0, - parameter SELF_LOOP_EN=0 + parameter SW_LOC=0 )( dest_port_coded, endp_localp_num, @@ -1086,11 +997,12 @@ module regular_topo_destp_decoder #( swap_port_presel, port_pre_sel ); + import pronoc_pkg::*; localparam P_1 = (SELF_LOOP_EN )? P : P-1; input [DSTPw-1 : 0] dest_port_coded; input [ELw-1 : 0] endp_localp_num; output [P_1-1 : 0] dest_port_out; - input swap_port_presel; + input swap_port_presel; input [PPSw-1 : 0] port_pre_sel; logic [NL-1 : 0] endp_localp_onehot; @@ -1117,34 +1029,27 @@ module regular_topo_destp_decoder #( end generate if(NL==1) begin :slp - if(SELF_LOOP_EN == 0) begin :nslp - remove_sw_loc_one_hot #( - .P(5), - .SW_LOC(SW_LOC) - ) conv ( - .destport_in(portout), - .destport_out(dest_port_out) - ); - end else begin : slp - assign dest_port_out = portout; - end + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(5), + .SW_LOC(SW_LOC) + ) conv ( + .destport_in(portout), + .destport_out(dest_port_out) + ); end else begin :mlp wire [P-1 : 0] destport_onehot; - assign destport_onehot =(portout[0])? { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/ { {(NL-1){1'b0}} ,portout}; - if(SELF_LOOP_EN == 0) begin :nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) remove_sw_loc ( - .destport_in(destport_onehot), - .destport_out(dest_port_out) - ); - end else begin: slp - assign dest_port_out = destport_onehot; - end + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(destport_onehot), + .destport_out(dest_port_out) + ); end endgenerate endmodule @@ -1154,19 +1059,15 @@ endmodule * line_ring_destp_decoder **************************/ module line_ring_destp_decoder #( - parameter ROUTE_TYPE="DETERMINISTIC", parameter P=4, - parameter DSTPw=2, - parameter NL=2, parameter ELw=1, - parameter PPSw=4, - parameter SW_LOC=0, - parameter SELF_LOOP_EN= 0 + parameter SW_LOC=0 )( dest_port_coded, endp_localp_num, dest_port_out ); + import pronoc_pkg::*; localparam P_1 = (SELF_LOOP_EN )? P : P-1; input [DSTPw-1 : 0] dest_port_coded; input [ELw-1 : 0] endp_localp_num; @@ -1186,34 +1087,27 @@ module line_ring_destp_decoder #( end generate if(NL==1) begin :_se - if(SELF_LOOP_EN == 0) begin :nslp - remove_sw_loc_one_hot #( - .P(3), - .SW_LOC(SW_LOC) - ) conv ( - .destport_in(portout), - .destport_out(dest_port_out) - ); - end else begin : slp - assign dest_port_out = portout; - end + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(3), + .SW_LOC(SW_LOC) + ) conv ( + .destport_in(portout), + .destport_out(dest_port_out) + ); end else begin :_me wire [P-1 : 0] destport_onehot; - assign destport_onehot =(portout[0])? { endp_localp_onehot[NL-1 : 1] ,{(P-NL){1'b0}},endp_localp_onehot[0]}: /*select local destination*/ { {(NL-1){1'b0}} ,portout}; - if(SELF_LOOP_EN == 0) begin :nslp - remove_sw_loc_one_hot #( - .P(P), - .SW_LOC(SW_LOC) - ) remove_sw_loc ( - .destport_in(destport_onehot), - .destport_out(dest_port_out) - ); - end else begin :slp - assign dest_port_out = destport_onehot; - end + destport_non_selfloop_fix #( + .SELF_LOOP_EN(SELF_LOOP_EN), + .P(P), + .SW_LOC(SW_LOC) + ) remove_sw_loc ( + .destport_in(destport_onehot), + .destport_out(dest_port_out) + ); end endgenerate endmodule @@ -1222,13 +1116,7 @@ endmodule * regular_topo_dynamic_portsel_control *****************/ module regular_topo_dynamic_portsel_control #( - parameter P = 5, - parameter ROUTE_TYPE = "FULL_ADAPTIVE", // "FULL_ADAPTIVE", "PAR_ADAPTIVE" - parameter V = 4, - parameter DSTPw=4, - parameter SSA_EN = 0, // 1: SSA enabled, 0: SSA disabled - parameter PPSw=4, - parameter [V-1 : 0] ESCAP_VC_MASK = 4'b1000 // mask scape vc, valid only for full adaptive + parameter P = 5 )( dest_port_coded_all, ivc_request_all, @@ -1243,15 +1131,12 @@ module regular_topo_dynamic_portsel_control #( reset, clk ); + import pronoc_pkg::*; localparam PV = V * P, PVV= PV * V, PVDSTPw = PV * DSTPw; - localparam LOCAL = 0, - EAST = 1, - NORTH = 2, - WEST = 3, - SOUTH = 4; + input [PVDSTPw-1 : 0] dest_port_coded_all; input [PV-1 : 0] ivc_request_all; input [PV-1 : 0] ovc_is_assigned_all; @@ -1262,11 +1147,11 @@ module regular_topo_dynamic_portsel_control #( output [PVDSTPw-1 : 0] destport_clear_all; input [PV-1 : 0] ivc_num_getting_ovc_grant; input [PV-1 : 0] ssa_ivc_num_getting_ovc_grant_all; - input reset,clk; + input reset,clk; - wire [PV-1 : 0] non_assigned_ovc_request_all; - wire [PV-1 : 0] y_evc_forbiden,x_evc_forbiden; - wire [PPSw-1 : 0] port_pre_sel_perport [P-1 : 0]; + wire [PV-1 : 0] non_assigned_ovc_request_all; + wire [PV-1 : 0] y_evc_forbiden,x_evc_forbiden; + wire [PPSw-1 : 0] port_pre_sel_perport [P-1 : 0]; assign non_assigned_ovc_request_all = ivc_request_all & ~ovc_is_assigned_all; assign port_pre_sel_perport[LOCAL] = port_pre_sel; assign port_pre_sel_perport[EAST] = {2'b00,port_pre_sel[1:0]}; @@ -1279,8 +1164,7 @@ module regular_topo_dynamic_portsel_control #( for(i=0;i< PV;i=i+1) begin : PV_ localparam SW_LOC = ((i/V)<5)? i/V : LOCAL; regular_topo_port_selector #( - .SW_LOC (SW_LOC), - .PPSw(PPSw) + .SW_LOC (SW_LOC) ) the_portsel ( .port_pre_sel (port_pre_sel_perport[SW_LOC]), .swap_port_presel (swap_port_presel[i]), @@ -1290,8 +1174,6 @@ module regular_topo_dynamic_portsel_control #( .x_evc_forbiden (x_evc_forbiden[i]) ); regular_topo_dspt_clear_gen #( - .SSA_EN(SSA_EN), - .DSTPw(DSTPw), .SW_LOC(SW_LOC) ) dspt_clear_gen( .destport_clear(destport_clear_all[((i+1)*DSTPw)-1 : i*DSTPw]), @@ -1304,8 +1186,6 @@ module regular_topo_dynamic_portsel_control #( /* verilator lint_on WIDTH */ assign avc_unavailable[i] = (masked_ovc_request_all [((i+1)*V)-1 : i*V] & ~ESCAP_VC_MASK) == {V{1'b0}}; regular_topo_swap_port_presel_gen #( - .V(V), - .ESCAP_VC_MASK(ESCAP_VC_MASK), .VC_NUM(i) ) the_swap_port_presel ( .avc_unavailable(avc_unavailable[i]), diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 067b0db..60473e0 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -56,7 +56,7 @@ module regular_topo_noc_top ( genvar x,y,l; generate - if( IS_RING | IS_LINE) begin : D1_ + if( IS_1D_TOPO ) begin : D1_ for (x=0; x YY); /* verilator lint_on CMPCONST */ @@ -218,13 +212,10 @@ module multicast_routing_fmesh #( wire [NE-1 : 0] y_plus,y_min; //Only one-bit is asserted for each local_p[i] wire [NE-1 : 0] local_p [MAX_P_FMESH-1 : 0]; - regular_topo_router_addr_decode router_addr_decode - ( - .r_addr(current_r_addr), - .rx(current_rx), - .ry(current_ry), - .valid( ) - ); + regular_topo_router_addr_t current_router_addr_struct; + assign current_router_addr_struct = regular_topo_router_addr_t'(current_r_addr); + assign current_rx = current_router_addr_struct.x; + assign current_ry = current_router_addr_struct.y; wire [NX-1 : 0] row_has_any_dest; wire [NE-1 : 0] dest_mcast_all_endp; @@ -540,29 +531,45 @@ module multicast_dst_sel ( input [DSTPw-1 : 0] destport_in; output [DSTPw-1 : 0] destport_out; wire [DSTPw-1 : 0] arb_in, arb_out; + + function integer three_dim_topo_priority_order; + input integer x; + begin + case(x) + 0 : three_dim_topo_priority_order = DOWN; + 1 : three_dim_topo_priority_order = UP; + 2 : three_dim_topo_priority_order = EAST; + 3 : three_dim_topo_priority_order = WEST; + 4 : three_dim_topo_priority_order = NORTH; + 5 : three_dim_topo_priority_order = SOUTH; + 6 : three_dim_topo_priority_order = LOCAL; + default : three_dim_topo_priority_order =x; + endcase + end + endfunction // pririty_order - function integer regular_topo_pririty_order; + function integer two_dim_topo_priority_order; input integer x; begin case(x) - 0 : regular_topo_pririty_order = EAST; - 1 : regular_topo_pririty_order = WEST; - 2 : regular_topo_pririty_order = NORTH; - 3 : regular_topo_pririty_order = SOUTH; - 4 : regular_topo_pririty_order = LOCAL; - default : regular_topo_pririty_order =x; + 0 : two_dim_topo_priority_order = EAST; + 1 : two_dim_topo_priority_order = WEST; + 2 : two_dim_topo_priority_order = NORTH; + 3 : two_dim_topo_priority_order = SOUTH; + 4 : two_dim_topo_priority_order = LOCAL; + default : two_dim_topo_priority_order =x; endcase end endfunction // pririty_order - function integer ring_lin_pririty_order; + function integer one_dim_topo_priority_order; input integer x; begin case(x) - 0 : ring_lin_pririty_order = FORWARD; - 1 : ring_lin_pririty_order = BACKWARD; - 2 : ring_lin_pririty_order = LOCAL; - default : ring_lin_pririty_order =x; + 0 : one_dim_topo_priority_order = FORWARD; + 1 : one_dim_topo_priority_order = BACKWARD; + 2 : one_dim_topo_priority_order = LOCAL; + default : one_dim_topo_priority_order =x; endcase end endfunction // pririty_order @@ -571,8 +578,9 @@ module multicast_dst_sel ( generate for (i=0; i1)? flit.payload [CLASS_MSB : CLASS_LSB] : {Cw{1'b0}}; - hdr_flit.weight = (IS_WRRA)? flit.payload [WEIGHT_MSB : WEIGHT_LSB] : {WEIGHTw{1'b0}}; - hdr_flit.be = (BYTE_EN)? flit.payload [BE_MSB : BE_LSB]: {BEw{1'b0}}; - end - - wire [OFFSETw-1 : 0 ] offset = flit.payload [DATA_MSB : DATA_LSB]; - generate - if(Dw > OFFSETw) begin : if1 - assign data_o={{(Dw-OFFSETw){1'b0}},offset}; - end else begin : if2 - assign data_o=offset[Dw-1 : 0]; - end - endgenerate -endmodule - `ifdef SIMULATION module smart_chanel_check ( flit_chanel, @@ -367,10 +325,25 @@ module check_straight_oport #( import pronoc_pkg::*; input [DSTPw-1 : 0] destport_coded_i; output goes_straight_o; - + generate - if(IS_MESH | IS_TORUS | IS_FMESH) begin :twoD - if (SS_PORT_LOC == 0 || SS_PORT_LOC > 4) begin : local_ports + if(IS_3D_TOPO) begin : D3_ + if (SS_PORT_LOC == 0 || SS_PORT_LOC > DOWN) begin : local_ports + assign goes_straight_o = 1'b0; // There is not a next router in this case at all + end else begin :non_local + logic [MAX_P-1 : 0 ] destport_one_hot; + always @(*) begin + destport_one_hot = '0; + //for deterministic routing destination port is decimal encoded + if(IS_DETERMINISTIC) destport_one_hot[destport_coded_i] = 1'b1; + //for non-deterministic routing destination port is one-hot encoded + else destport_one_hot [DSTPw-1 : 0] = destport_coded_i; + end + assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; + end//else + end//regular_topo + if(IS_2D_TOPO) begin : D2_ + if (SS_PORT_LOC == 0 || SS_PORT_LOC > SOUTH) begin : local_ports assign goes_straight_o = 1'b0; // There is not a next router in this case at all end else begin :non_local wire [4 : 0 ] destport_one_hot; @@ -378,12 +351,11 @@ module check_straight_oport #( .dstport_encoded(destport_coded_i), .dstport_one_hot(destport_one_hot) ); - assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; end//else end//regular_topo - else if(IS_RING | IS_LINE) begin :oneD - if (SS_PORT_LOC == 0 || SS_PORT_LOC > 2) begin : local_ports + else if(IS_1D_TOPO) begin : D1_ + if (SS_PORT_LOC == 0 || SS_PORT_LOC > BACKWARD) begin : local_ports assign goes_straight_o = 1'b0; // There is not a next router in this case at all end else begin :non_local wire [2: 0 ] destport_one_hot; @@ -394,7 +366,6 @@ module check_straight_oport #( assign goes_straight_o = destport_one_hot [SS_PORT_LOC]; end //non_local end// oneD - //TODO Add fattree & custom endgenerate endmodule @@ -595,8 +566,8 @@ module smart_allocator_per_iport # ( wire goes_straight; localparam LOCATED_IN_NI = - (IS_RING | IS_LINE) ? (SW_LOC == 0 || SW_LOC > 2) : - (IS_MESH | IS_TORUS | IS_FMESH) ? (SW_LOC == 0 || SW_LOC > 4 ) : 0; + (IS_1D_TOPO) ? (SW_LOC == 0 || SW_LOC > 2) : + (IS_2D_TOPO) ? (SW_LOC == 0 || SW_LOC > 4 ) : 0; // does the route computation for the current router conventional_routing #( diff --git a/mpsoc/rtl/src_noc/router_top.sv b/mpsoc/rtl/src_noc/router_top.sv index 548e891..673c286 100644 --- a/mpsoc/rtl/src_noc/router_top.sv +++ b/mpsoc/rtl/src_noc/router_top.sv @@ -424,4 +424,11 @@ module router_top_v .reset(reset) ); + `ifdef SIMULATION + initial begin + if (current_r_addr==0) begin + display_noc_parameters(); + end + end + `endif endmodule diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index a56c270..6d71110 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -161,8 +161,12 @@ module router_two_stage #( wire [EAw-1 : 0] endp_addrs [NE_PER_R-1 : 0]; function automatic int get_enp_num(input int i); - if(IS_LINE | IS_RING | IS_MESH | IS_FMESH | IS_TORUS) begin - return (i > SOUTH) ? i - SOUTH : LOCAL; + if(IS_1D_TOPO) begin + return (i > BACKWARD) ? i - BACKWARD : LOCAL; + end else if(IS_2D_TOPO) begin + return (i > SOUTH) ? i - SOUTH : LOCAL; + end else if(IS_3D_TOPO) begin + return (i > DOWN) ? i - DOWN : LOCAL; end else if (IS_MULTI_MESH) begin return LOCAL; end else return 0; //TODO complete it for fattree and bin tree @@ -458,9 +462,6 @@ module router_two_stage #( generate if(DEBUG_EN & IS_MESH)begin :dbg debug_mesh_edges #( - .T1(T1), - .T2(T2), - .RAw(RAw), .P(P) ) debug_edges ( .clk(clk), diff --git a/mpsoc/rtl/src_noc/routing.sv b/mpsoc/rtl/src_noc/routing.sv index 0ea5f5d..e8332d1 100755 --- a/mpsoc/rtl/src_noc/routing.sv +++ b/mpsoc/rtl/src_noc/routing.sv @@ -47,47 +47,17 @@ module conventional_routing #( output [DSTPw-1 :0] destport; generate - if( IS_MESH | IS_FMESH | IS_TORUS | IS_RING | IS_LINE ) begin : regular_topo - localparam - RXw = log2(NX), - RYw = (IS_RING | IS_LINE) ? 1 :log2(NY), - EXw = RXw, - EYw =(IS_RING | IS_LINE) ? 1 : RYw; - wire [RXw-1 : 0] current_rx; - wire [RYw-1 : 0] current_ry; - wire [EXw-1 : 0] dest_ex; - wire [EYw-1 : 0] dest_ey; - - regular_topo_router_addr_decode router_addr_decode ( - .r_addr(current_r_addr), - .rx(current_rx), - .ry(current_ry), - .valid( ) - ); - if( IS_FMESH) begin :fmesh - fmesh_endp_addr_decode end_addr_decode ( - .e_addr(dest_e_addr), - .ex(dest_ex), - .ey(dest_ey), - .ep( ), - .valid() - ); - end else begin : mesh - regular_topo_endp_addr_decode end_addr_decode ( - .e_addr(dest_e_addr), - .ex(dest_ex), - .ey(dest_ey), - .el( ), - .valid() - ); - end//mesh + if( IS_REGULAR_TOPO | IS_FMESH ) begin : regular_topo + regular_topo_router_addr_t dest_router_addr, current_router_addr; + always @(*) begin + dest_router_addr = regular_topo_router_addr_t'(dest_e_addr); + current_router_addr = regular_topo_router_addr_t'(current_r_addr); + end regular_topo_conventional_routing #( .LOCATED_IN_NI(LOCATED_IN_NI) ) the_conventional_routing ( - .current_x(current_rx), - .current_y(current_ry), - .dest_x(dest_ex), - .dest_y(dest_ey), + .current_router_addr_i(current_router_addr), + .dest_router_addr_i(dest_router_addr), .destport(destport) ); end else if(IS_FATTREE | IS_TREE ) begin : ftree @@ -184,48 +154,23 @@ module look_ahead_routing #( input [DSTPw-1 : 0] destport_encoded; output [DSTPw-1 : 0] lkdestport_encoded; input reset,clk; + localparam PP = ( IS_MESH | IS_FMESH | IS_TORUS ) ? 5 : (IS_MESH_3D) ? 7 : 3; + logic [RAw-1 : 0] neighbors_r_addr_array [PP-1 : 0]; genvar i; generate + for (i=0;i SOUTH) ) : - (IS_RING | IS_LINE) ? ((SW_LOC==LOCAL) || (SW_LOC > BACKWARD) ) : 0; + (IS_3D_TOPO)? ((SW_LOC==LOCAL) || (SW_LOC > DOWN) ) : + (IS_2D_TOPO)? ((SW_LOC==LOCAL) || (SW_LOC > SOUTH) ) : + (IS_1D_TOPO) ? ((SW_LOC==LOCAL) || (SW_LOC > BACKWARD) ) : 0; hdr_flit_t hdr_flit_i; wire [DSTPw-1 :0] destport; header_flit_info #( diff --git a/mpsoc/rtl/src_noc/ss_allocator.sv b/mpsoc/rtl/src_noc/ss_allocator.sv index 8b090e5..924d2fd 100755 --- a/mpsoc/rtl/src_noc/ss_allocator.sv +++ b/mpsoc/rtl/src_noc/ss_allocator.sv @@ -282,7 +282,6 @@ module ssa_per_vc #( ssa_check_destport #( .SW_LOC(SW_LOC), - .P(P), .SS_PORT(SS_PORT) ) check_destport ( .destport_encoded(destport_encoded), @@ -335,7 +334,6 @@ endmodule module ssa_check_destport #( parameter SW_LOC = 0, - parameter P=5, parameter SS_PORT=0 ) ( destport_encoded, //non header flit dest port @@ -370,13 +368,9 @@ module ssa_check_destport #( .ss_port_hdr_flit(ss_port_hdr_flit), .ss_port_nonhdr_flit(ss_port_nonhdr_flit) ); - end else if (IS_MESH | IS_TORUS ) begin : mesh - regular_topo_ssa_check_destport #( - .ROUTE_TYPE(ROUTE_TYPE), + end else if (IS_MESH | IS_TORUS ) begin : D2_ + two_dim_ssa_check_destport #( .SW_LOC(SW_LOC), - .P(P), - .DEBUG_EN(DEBUG_EN), - .DSTPw(DSTPw), .SS_PORT(SS_PORT) ) destport_check ( .destport_encoded(destport_encoded), @@ -392,21 +386,13 @@ module ssa_check_destport #( end else if (IS_FMESH) begin :fmesh localparam ELw = log2(T3), - Pw = log2(P); + Pw = log2(MAX_P); wire [Pw-1 : 0] endp_p_in; wire [MAX_P-1 : 0] destport_one_hot_in; - - fmesh_endp_addr_decode endp_addr_decode ( - .e_addr(dest_e_addr_in), - .ex(), - .ey(), - .ep(endp_p_in), - .valid() - ); - + assign endp_p_in = dest_e_addr_in[DAw-1 : DAw-Pw]; destp_generator #( - .P(P), + .P(MAX_P), .SW_LOC(SW_LOC) ) decoder ( .destport_one_hot (destport_one_hot_in), @@ -419,13 +405,9 @@ module ssa_check_destport #( ); assign ss_port_nonhdr_flit = destport_one_hot [SS_PORT]; assign ss_port_hdr_flit = destport_one_hot_in [SS_PORT]; - end else begin : line - line_ring_ssa_check_destport #( - .ROUTE_TYPE(ROUTE_TYPE), + end else if(IS_LINE | IS_RING) begin : D1_ + one_dim_ssa_check_destport #( .SW_LOC(SW_LOC), - .P(P), - .DEBUG_EN(DEBUG_EN), - .DSTPw(DSTPw), .SS_PORT(SS_PORT) ) destport_check ( .destport_encoded(destport_encoded), @@ -433,6 +415,17 @@ module ssa_check_destport #( .ss_port_hdr_flit(ss_port_hdr_flit), .ss_port_nonhdr_flit(ss_port_nonhdr_flit) ); + end else begin : other + logic [MAX_P-1 : 0] destport_one_hot_in; + always @(*) begin + destport_one_hot_in = '0; + //for deterministic routing destination port is decimal encoded + if(IS_DETERMINISTIC) destport_one_hot_in[destport_in_encoded] = 1'b1; + //for non-deterministic routing destination port is one-hot encoded + else destport_one_hot_in [DSTPw-1 : 0] = destport_in_encoded; + end + assign ss_port_nonhdr_flit = destport_one_hot [SS_PORT]; + assign ss_port_hdr_flit = destport_one_hot_in [SS_PORT]; end endgenerate endmodule diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index c16f8f5..6b03106 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -19,7 +19,11 @@ IS_TREE= (TOPOLOGY == "TREE"), IS_STAR= (TOPOLOGY == "STAR"), IS_MULTI_MESH=(TOPOLOGY == "MULTI_MESH"), - IS_REGULAR_TOPO = (IS_RING | IS_LINE | IS_MESH | IS_TORUS), + IS_MESH_3D= (TOPOLOGY == "MESH_3D"), + IS_REGULAR_TOPO = (IS_RING | IS_LINE | IS_MESH | IS_TORUS | IS_MESH_3D), + IS_1D_TOPO = (IS_LINE | IS_RING), + IS_2D_TOPO = (IS_MESH | IS_TORUS | IS_FMESH), + IS_3D_TOPO = (IS_MESH_3D | IS_MULTI_MESH), IS_MULTI_ENDP_ROUTER = (T3 > 1) ; /* verilator lint_on WIDTH */ @@ -96,16 +100,16 @@ input integer router_port_num; //router port num input integer current_port; begin - if(IS_MESH | IS_FMESH | IS_TORUS | IS_MULTI_MESH) begin + if(IS_2D_TOPO | IS_3D_TOPO) begin strieght_port = (current_port == EAST)? WEST: (current_port == WEST)? EAST: (current_port == SOUTH)? NORTH: (current_port == NORTH)? SOUTH: - (IS_MULTI_MESH && current_port== UP)? DOWN: - (IS_MULTI_MESH && current_port== DOWN)? UP: + (IS_3D_TOPO && current_port== UP)? DOWN: + (IS_3D_TOPO && current_port== DOWN)? UP: router_port_num; //DISABLED; - end else if (IS_RING | IS_LINE) begin + end else if (IS_1D_TOPO) begin strieght_port = (current_port== FORWARD )? BACKWARD: (current_port== BACKWARD)? FORWARD: @@ -131,38 +135,42 @@ input integer router_port_num; //router port num begin port_buffer_size = B; - if(IS_MESH || IS_FMESH || IS_TORUS || IS_RING || IS_LINE)begin - if (router_port_num == 0 || router_port_num > 4 ) port_buffer_size = LB; - end else if (IS_MULTI_MESH) begin - if (router_port_num == 0) port_buffer_size = LB; + if(IS_1D_TOPO) begin + if (router_port_num == 0 || router_port_num > BACKWARD ) port_buffer_size = LB; + end else if (IS_2D_TOPO) begin + if (router_port_num == 0 || router_port_num > SOUTH ) port_buffer_size = LB; + end else if (IS_3D_TOPO) begin + if (router_port_num == 0 || router_port_num > DOWN) port_buffer_size = LB; end end endfunction /******************* - * REGULAR_TOPO: "RING" "LINE" "MESH" TORUS" "FMESH" + * REGULAR_TOPO: "RING" "LINE" "MESH" TORUS" "FMESH" "MESH_3D" ******************/ localparam NX = T1, - NY = (IS_RING | IS_LINE) ? 1 : T2, - NL = T3, + NY = (IS_1D_TOPO) ? 1 : T2, + NL = (IS_3D_TOPO)? T4 : T3, + NZ = (IS_3D_TOPO)? T3 : 1, NXw = log2(NX), NYw = log2(NY), NLw = log2(NL), + NZw= log2(NZ), PPSw_REGULAR = 4, //port presel width for adaptive routing /* verilator lint_off WIDTH */ ROUTE_TYPE_REGULAR = - (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" )? "DETERMINISTIC" : + (ROUTE_NAME == "DOR" || ROUTE_NAME == "TRANC_DOR" )? "DETERMINISTIC" : (ROUTE_NAME == "FULL_ADPT" || ROUTE_NAME == "TRANC_FULL_ADPT" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE", /* verilator lint_on WIDTH */ - R2R_CHANELS_REGULAR= (IS_RING || IS_LINE)? 2 : 4, + R2R_CHANELS_REGULAR= (IS_1D_TOPO)? 2 : (IS_3D_TOPO)? 6 : 4, R2E_CHANELS_REGULAR= NL, - RAw_REGULAR = ( IS_RING | IS_LINE)? NXw : NXw + NYw, - EAw_REGULAR = (NL==1) ? RAw_REGULAR : RAw_REGULAR + NLw, - NR_REGULAR = (IS_RING || IS_LINE)? NX : NX*NY, + RAw_REGULAR = ( IS_1D_TOPO )? NXw : (IS_3D_TOPO)? NXw + NYw + NZw : NXw + NYw, + EAw_REGULAR = (NL==1 ) ? RAw_REGULAR : RAw_REGULAR + NLw, + NR_REGULAR = (IS_1D_TOPO)? NX :(IS_3D_TOPO)? NX*NY*NZ : NX*NY, NE_REGULAR = NR_REGULAR * NL, MAX_P_REGULAR = R2R_CHANELS_REGULAR + R2E_CHANELS_REGULAR, - DSTPw_REGULAR = R2R_CHANELS_REGULAR, // P-1 + DSTPw_REGULAR = (IS_3D_TOPO)? log2(MAX_P_REGULAR) : R2R_CHANELS_REGULAR, // P-1 NE_PER_R_REGULAR = NL; /**************** @@ -213,7 +221,7 @@ localparam ROUTE_TYPE_STAR = "DETERMINISTIC", NE_STAR = T1, //total number of endpoints - NR_STAR = 1, // total number of routers + NR_STAR = 1, // total number of routers RAw_STAR = 1, EAw_STAR = log2(NE_STAR), DSTPw_STAR = (~IS_UNICAST) ? NE_STAR :EAw_STAR, @@ -244,6 +252,20 @@ EAw_MULTI_MESH = T2, MAX_P_MULTI_MESH = 7, DSTPw_MULTI_MESH = log2(MAX_P_MULTI_MESH); + /************************* + * regular_topo address struct + **************************/ + typedef struct packed { + logic [NZw-1 : 0] z; + logic [NYw-1 : 0] y; + logic [NXw-1 : 0] x; + } regular_topo_router_addr_t; + typedef struct packed { + logic [NLw-1 : 0] l; + logic [NZw-1 : 0] z; + logic [NYw-1 : 0] y; + logic [NXw-1 : 0] x; + } regular_topo_endp_addr_t; localparam PPSw = PPSw_REGULAR, @@ -390,12 +412,17 @@ function automatic integer regular_topo_endp_addr; input integer endp_id; - integer y, x, l,p, diff,mul; + integer y, x, z, l,rid; begin - y = ((endp_id/NL) / NX ); - x = ((endp_id/NL) % NX ); - l = (endp_id % NL); - regular_topo_endp_addr = ( l << ( NXw+NYw) | (y<> parameter.v printf " parameter MAX_PCK_SIZ=$MAX_PCK_SIZ;\n" >> parameter.v printf " parameter TIMSTMP_FIFO_NUM=$TIMSTMP_FIFO_NUM;\n" >> parameter.v - printf " parameter ROUTE_TYPE = (ROUTE_NAME == \"XY\" || ROUTE_NAME == \"TRANC_XY\" )? \"DETERMINISTIC\" : \n" >> parameter.v + printf " parameter ROUTE_TYPE = (ROUTE_NAME == \"DOR\" || ROUTE_NAME == \"TRANC_DOR\" )? \"DETERMINISTIC\" : \n" >> parameter.v printf " (ROUTE_NAME == \"FULL_ADPT\" || ROUTE_NAME == \"TRANC_FULL_ADPT\" )? \"FULL_ADAPTIVE\": \"PAR_ADAPTIVE\"; \n" >> parameter.v printf " parameter DEBUG_EN=$DEBUG_EN;\n" >> parameter.v printf " parameter ROUTE_SUBFUNC= \"$ROUTE_SUBFUNC\";\n">> parameter.v diff --git a/mpsoc/script/synfull/noc_localparam.v b/mpsoc/script/synfull/noc_localparam.v index 09a939c..feff061 100644 --- a/mpsoc/script/synfull/noc_localparam.v +++ b/mpsoc/script/synfull/noc_localparam.v @@ -38,7 +38,7 @@ localparam B=4; localparam LB=4; localparam Fpay=64; - localparam ROUTE_NAME="XY"; + localparam ROUTE_NAME="DOR"; localparam PCK_TYPE="MULTI_FLIT"; localparam MIN_PCK_SIZE=1; localparam BYTE_EN=0; diff --git a/mpsoc/script/verilator_2D_mesh.sh b/mpsoc/script/verilator_2D_mesh.sh index 4a1d247..a4cf231 100755 --- a/mpsoc/script/verilator_2D_mesh.sh +++ b/mpsoc/script/verilator_2D_mesh.sh @@ -42,8 +42,8 @@ CORE_NUM(){ FIRST_ARBITER_EXT_P_EN=1 TOPOLOGY="MESH" #"MESH" or "TORUS" ROUTE_NAME="FULL_ADPT" # Routing algorithm - # mesh : "XY" , "WEST_FIRST" , "NORTH_LAST" , "NEGETIVE_FIRST" , "FULL_ADPT" - # torus: "TRANC_XY" , "TRANC_WEST_FIRST", "TRANC_NORTH_LAST", "TRANC_NEGETIVE_FIRST", "TRANC_FULL_ADPT" + # mesh : "DOR" , "WEST_FIRST" , "NORTH_LAST" , "NEGETIVE_FIRST" , "FULL_ADPT" + # torus: "TRANC_DOR" , "TRANC_WEST_FIRST", "TRANC_NORTH_LAST", "TRANC_NEGETIVE_FIRST", "TRANC_FULL_ADPT" CONGESTION_INDEX="VC" #"CREDIT","VC" CLASS_SETTING="4'b1111" #0: no class. packets can be sent to any available OVC @@ -81,7 +81,7 @@ CORE_NUM(){ # for minimal fully adaptive on 2D mesh paper - ROUTING_SUBFUNCTION= "XY" # "XY" "NORTH_LAST" + ROUTING_SUBFUNCTION= "DOR" # "DOR" "NORTH_LAST" AVC_REALLOCATION= "" generate_parameter_v (){ @@ -112,7 +112,7 @@ generate_parameter_v (){ printf " parameter TOTAL_PKT_PER_ROUTER=$TOTAL_PKT_PER_ROUTER;\n" >> parameter.v printf " parameter MAX_DELAY_BTWN_PCKTS=$MAX_DELAY_BTWN_PCKTS;\n" >> parameter.v printf " parameter DEBUG_EN=$DEBUG_EN;\n" >> parameter.v - printf " parameter ROUTE_TYPE = (ROUTE_NAME == \"XY\" || ROUTE_NAME == \"TRANC_XY\" )? \"DETERMINISTIC\" : \n" >> parameter.v + printf " parameter ROUTE_TYPE = (ROUTE_NAME == \"DOR\" || ROUTE_NAME == \"TRANC_DOR\" )? \"DETERMINISTIC\" : \n" >> parameter.v printf " (ROUTE_NAME == \"FULL_ADPT\" || ROUTE_NAME == \"TRANC_FULL_ADPT\" )? \"FULL_ADAPTIVE\": \"PAR_ADAPTIVE\"; \n" >> parameter.v printf " parameter ADD_PIPREG_AFTER_CROSSBAR= $ADD_PIPREG_AFTER_CROSSBAR;\n" >> parameter.v printf " parameter CVw=(C==0)? V : C * V;\n" >> parameter.v @@ -168,7 +168,7 @@ for PACKET_SIZE in 3 2 4 6 for TRAFFIC in "RANDOM" "TRANSPOSE1" "TRANSPOSE2" "HOTSPOT" do - for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" + for ROUTE_NAME in "DOR" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" do # regenerate NoC generate_parameter_v @@ -190,7 +190,7 @@ for PACKET_SIZE in 3 2 4 6 #run multiple testbench files in the same time cd $multiple_path - for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" + for ROUTE_NAME in "DOR" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" do ./$ROUTE_NAME$TRAFFIC"_"$PACKET_SIZE $ROUTE_NAME$TRAFFIC"_"$PACKET_SIZE & @@ -200,7 +200,7 @@ for PACKET_SIZE in 3 2 4 6 wait # merge the result in one file - for ROUTE_NAME in "XY" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" + for ROUTE_NAME in "DOR" "WEST_FIRST" "NORTH_LAST" "NEGETIVE_FIRST" "FULL_ADPT" do data_file=$data_path/$TRAFFIC"_"$PACKET_SIZE"_all.txt" plot_file=$plot_path/$TRAFFIC"_"$PACKET_SIZE".eps" diff --git a/mpsoc/smart-netrace/models/B4_V1_S0 b/mpsoc/smart-netrace/models/B4_V1_S0 index 3b9e23c..6f9937f 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S0 +++ b/mpsoc/smart-netrace/models/B4_V1_S0 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", diff --git a/mpsoc/smart-netrace/models/B4_V1_S2 b/mpsoc/smart-netrace/models/B4_V1_S2 index 893796d..94c23d7 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S2 +++ b/mpsoc/smart-netrace/models/B4_V1_S2 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", diff --git a/mpsoc/smart-netrace/models/B4_V1_S4 b/mpsoc/smart-netrace/models/B4_V1_S4 index 87959c4..8bcb6e2 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S4 +++ b/mpsoc/smart-netrace/models/B4_V1_S4 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", diff --git a/mpsoc/smart-netrace/models/B4_V1_S7 b/mpsoc/smart-netrace/models/B4_V1_S7 index c624e39..936f5e9 100644 --- a/mpsoc/smart-netrace/models/B4_V1_S7 +++ b/mpsoc/smart-netrace/models/B4_V1_S7 @@ -1,6 +1,6 @@ $model = bless( { 'noc_param'=> { - "ROUTE_NAME" => "\"XY\"", + "ROUTE_NAME" => "\"DOR\"", "ADD_PIPREG_AFTER_CROSSBAR" => "1'b1", "V" => "1", "B" => "4", diff --git a/mpsoc/smart-netrace/src/deafult_noc_param b/mpsoc/smart-netrace/src/deafult_noc_param index 1affbb5..4c3b565 100644 --- a/mpsoc/smart-netrace/src/deafult_noc_param +++ b/mpsoc/smart-netrace/src/deafult_noc_param @@ -8,7 +8,7 @@ $model = bless( { "B" => "4", "LB" => "B", "Fpay" => "32", -"ROUTE_NAME" => "\"XY\"", +"ROUTE_NAME" => "\"DOR\"", "PCK_TYPE" => " \"MULTI_FLIT\"", "MIN_PCK_SIZE" => "2", "BYTE_EN" => "0", diff --git a/mpsoc/src_c/plot/parameter.v b/mpsoc/src_c/plot/parameter.v index aa4c112..66b4001 100755 --- a/mpsoc/src_c/plot/parameter.v +++ b/mpsoc/src_c/plot/parameter.v @@ -12,7 +12,7 @@ parameter COMBINATION_TYPE="BASELINE"; parameter FIRST_ARBITER_EXT_P_EN=0; parameter TOPOLOGY="MESH"; - parameter ROUTE_NAME="XY"; + parameter ROUTE_NAME="DOR"; parameter CONGESTION_INDEX=3; parameter CLASS_CONFIG_NUM=0; parameter C0_p=100; @@ -32,7 +32,7 @@ parameter MAX_PCK_SIZ=10; parameter TIMSTMP_FIFO_NUM=64; parameter [V-1 : 0] ESCAP_VC_MASK=1; - parameter ROUTE_TYPE = (ROUTE_NAME == "XY" || ROUTE_NAME == "TRANC_XY" || ROUTE_NAME == "TRANC")? "DETERMINISTIC" : + parameter ROUTE_TYPE = (ROUTE_NAME == "DOR" || ROUTE_NAME == "TRANC_DOR" || ROUTE_NAME == "TRANC")? "DETERMINISTIC" : (ROUTE_NAME == "FULL_ADPT" || ROUTE_NAME == "TRANC_FULL_ADPT" )? "FULL_ADAPTIVE": "PAR_ADAPTIVE"; parameter DEBUG_EN=0; parameter ROUTE_SUBFUNC= "NORTH_LAST"; diff --git a/mpsoc/src_verilator/simulator.cpp b/mpsoc/src_verilator/simulator.cpp index 1be9cb2..f773427 100755 --- a/mpsoc/src_verilator/simulator.cpp +++ b/mpsoc/src_verilator/simulator.cpp @@ -52,7 +52,7 @@ int main(int argc, char** argv) { mcast_init(); topology_init(); - + if( TRAFFIC_TYPE == NETRACE){ netrace_init(netrace_file); // should be called first to initiate header pck_inj_init((int)header->num_nodes); @@ -64,10 +64,9 @@ int main(int argc, char** argv) { else traffic_gen_init(); main_time=0; - print_parameter(); if( thread_num>1) initial_threads(); - while (!Verilated::gotFinish()) { + if(main_time == 1) print_parameter(); if(main_time - saved_time < 50) {//set reset and start #ifdef FLAT_MODE reset_active_high = ((noc_top->router_event[0][0] & ACTIVE_HIGH_RST)!=0) ? 1 : 0; @@ -371,8 +370,7 @@ int parse_string ( char * str, int * array) unsigned int pck_dst_gen_unicast ( unsigned int core_num, unsigned char * inject_en) { if(TRAFFIC_TYPE==TASK) return pck_dst_gen_task_graph ( core_num, inject_en); - if((strcmp (TOPOLOGY,"MESH")==0)||(strcmp (TOPOLOGY,"TORUS")==0)) return pck_dst_gen_2D (core_num, inject_en); - return pck_dst_gen_1D (core_num, inject_en); + return pck_dst_gen_synthetic (core_num, inject_en); } void mcast_full_rnd (unsigned int core_num){ @@ -645,7 +643,7 @@ void traffic_gen_init( void ){ unsigned int dest_e_addr; for (i=0;icurrent_e_addr = endp_addr_encoder(i); traffic[i]->start=0; traffic[i]->pck_class_in= pck_class_in_gen( i); @@ -1232,45 +1230,6 @@ void print_statistic_new (unsigned long int total_clk){ } void print_parameter (){ - printf ("NoC parameters:---------------- \n"); - printf ("\tTopology: %s\n",TOPOLOGY); - printf ("\tRouting algorithm: %s\n",ROUTE_NAME); - printf ("\tVC_per port: %d\n", V); - printf ("\tNon-local port buffer_width per VC: %d\n", B); - printf ("\tLocal port buffer_width per VC: %d\n", LB); - #if defined (IS_MESH) || defined (IS_FMESH) || defined (IS_TORUS) - printf ("\tRouter num in row: %d \n",T1); - printf ("\tRouter num in column: %d \n",T2); - printf ("\tEndpoint num per router: %d\n",T3); - #elif defined (IS_LINE) || defined (IS_RING ) - printf ("\tTotal Router num: %d \n",T1); - printf ("\tEndpoint num per router: %d\n",T3); - #elif defined (IS_FATTREE) || defined (IS_TREE) - printf ("\tK: %d \n",T1); - printf ("\tL: %d \n",T2); - #elif defined (IS_STAR) - printf ("\tTotal Endpoints number: %d \n",T1); - #else//CUSTOM - printf ("\tTotal Endpoints number: %d \n",T1); - printf ("\tTotal Routers number: %d \n",T2); - #endif - printf ("\tNumber of Class: %d\n", C); - printf ("\tFlit data width: %d \n", Fpay); - printf ("\tVC reallocation mechanism: %s \n", VC_REALLOCATION_TYPE); - printf ("\tVC/sw combination mechanism: %s \n", COMBINATION_TYPE); - printf ("\tAVC_ATOMIC_EN:%d \n", AVC_ATOMIC_EN); - printf ("\tCongestion Index:%d \n",CONGESTION_INDEX); - printf ("\tADD_PIPREG_AFTER_CROSSBAR:%d\n",ADD_PIPREG_AFTER_CROSSBAR); - printf ("\tSSA_EN enabled: %d \n",SSA_EN); - printf ("\tSwitch allocator arbitration type:%s \n",SWA_ARBITER_TYPE); - printf ("\tMinimum supported packet size:%d flit(s) \n",MIN_PCK_SIZE); - printf ("\tLoop back is enabled:%d \n",SELF_LOOP_EN); - printf ("\tNumber of multihop bypass (SMART max):%d \n",SMART_MAX); - printf ("\tCastying type:%s.\n",CAST_TYPE); - if (IS_MCAST_PARTIAL){ - printf ("\tCAST LIST:%s\n",MCAST_ENDP_LIST); - } - printf ("NoC parameters:---------------- \n"); printf ("\nSimulation parameters-------------\n"); #if(DEBUG_EN) printf ("\tDebuging is enabled\n"); diff --git a/mpsoc/src_verilator/topology/mesh.h b/mpsoc/src_verilator/topology/mesh.h index f64b633..5f9ba85 100644 --- a/mpsoc/src_verilator/topology/mesh.h +++ b/mpsoc/src_verilator/topology/mesh.h @@ -1,491 +1,294 @@ #ifndef MESH_H - #define MESH_H - - #define LOCAL 0 - #define EAST 1 - #define NORTH 2 - #define WEST 3 - #define SOUTH 4 - //ring line - #define FORWARD 1 - #define BACKWARD 2 - #define router_id(x,y) ((y * T1) + x) - #define endp_id(x,y,l) ((y * T1) + x) * T3 + l +#define MESH_H - unsigned int nxw=0; - unsigned int nyw=0; - unsigned int maskx=0; - unsigned int masky=0; +#define LOCAL 0 +#define EAST 1 +#define NORTH 2 +#define SOUTH 4 +//ring line +#define FORWARD 1 +#define BACKWARD 2 - void mesh_tori_addrencod_sep(unsigned int id, unsigned int *x, unsigned int *y, unsigned int *l){ - (*l)=id%T3; // id%NL - (*x)=(id/T3)%T1;// (id/NL)%NX - (*y)=(id/T3)/T1;// (id/NL)/NX - } +#define UP 5 +#define DOWN 6 - void mesh_tori_addr_sep(unsigned int code, unsigned int *x, unsigned int *y, unsigned int *l){ - (*x) = code & maskx; - code>>=nxw; - (*y) = code & masky; - code>>=nyw; - (*l) = code; - } +#if defined (IS_LINE) || defined (IS_RING ) + #define X_MAX T1 + #define Y_MAX 1 + #define Z_MAX 1 + #define L_MAX T3 + #define DIM 1 +#elif defined (IS_MESH_3D) + #define X_MAX T1 + #define Y_MAX T2 + #define Z_MAX T3 + #define L_MAX T4 + #define DIM 3 +#elif defined (IS_TORUS) || defined (IS_MESH) || defined (IS_FMESH) + #define X_MAX T1 + #define Y_MAX T2 + #define Z_MAX 1 + #define L_MAX T3 + #define DIM 2 +#endif - void ring_line_addr_sep(unsigned int code, unsigned int *x, unsigned int *l){ - (*x) = code & maskx; - code>>=nxw; - (*l) = code; - } +#if defined (IS_LINE) || defined (IS_RING ) + #define WEST BACKWARD + #define R2R_CHANELS_MESH_TORI 2 +#else + #define WEST 3 + #if defined (IS_MESH_3D) + #define R2R_CHANELS_MESH_TORI 6 + #else + #define R2R_CHANELS_MESH_TORI 4 + #endif //IS_MESH_3D +#endif - unsigned int mesh_tori_addr_join(unsigned int x, unsigned int y, unsigned int l){ - unsigned int addrencode=0; - addrencode =(T3==1)? (y< SOUTH) return l; + if(x==0 && l == WEST) return l; + if(x== (T1-1) && l == EAST) return l; + if(y==0 && l == NORTH) return l; + if(y== (T2-1) && l == SOUTH) return l; + if(x==0) return WEST; + if(x== (T1-1)) return EAST; + if(y==0) return NORTH; + if(y== (T2-1)) return SOUTH; + return LOCAL; +} - void fmesh_addrencod_sep(unsigned int id, unsigned int *x, unsigned int *y, unsigned int *p){ - unsigned int l, diff,mul,addrencode; - mul = T1*T2*T3; - 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; - } else if ( diff < 2* T1) { //bottom mesh edge - *y = T2-1; - *x = diff-T1; - *p = SOUTH; - } else if ( 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; - } +void fmesh_Eid_to_coords(unsigned int id, unsigned int *x, unsigned int *y, unsigned int *p){ + unsigned int l, diff,mul,addrencode; + mul = T1*T2*T3; + 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; + } else if ( diff < 2* T1) { //bottom mesh edge + *y = T2-1; + *x = diff-T1; + *p = SOUTH; + } else if ( 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; } } +} - unsigned int fmesh_addrencode(unsigned int id){ - //input integer in,nx,nxw,nl,nyw,ny; - unsigned int y, x, p, addrencode; - fmesh_addrencod_sep(id, &x, &y, &p); - addrencode = ( p<<(nxw+nyw) | (y< SOUTH) return ((y*T1)+x)*T3+(p-SOUTH); - if(p== NORTH) return ((T1*T2*T3) + x); - if(p== SOUTH) return ((T1*T2*T3) + T1 + x); - if(p== WEST ) return ((T1*T2*T3) + 2*T1 + y); - if(p== EAST ) return ((T1*T2*T3) + 2*T1 + T2 + y); - return 0;//should not reach here +unsigned int regular_topo_coords_to_Eaddr(unsigned int x, unsigned int y, unsigned int z, unsigned int l){ + unsigned int code=x; + unsigned int shift =nxw; + if(DIM > 1) { + code|=y< 2) { + code|=z<>=nxw; + if(DIM > 1) { + (*y) = code & masky; + code>>=nyw; + } else (*y)=0; + if(DIM > 2) { + (*z) = code & maskz; + code>>=nzw; + } else (*z)=0; + (*l) = code; +} + +unsigned int reqular_topo_addr_encode (unsigned int id){ + unsigned int y, x, z, l; + regular_topo_Eid_to_coords(id,&x,&y,&z,&l); + return regular_topo_coords_to_Eaddr(x,y,z,l); +} + +unsigned int regular_topo_addr_decoder (unsigned int code){ + unsigned int y, x, z, l; + regular_topo_Eaddr_to_coords(code,&x,&y,&z,&l); + return endp_id(x,y,z,l); +} + +unsigned int fmesh_endp_addr_decoder (unsigned int code){ + unsigned int x, y, z, p; + regular_topo_Eaddr_to_coords(code,&x,&y,&z,&p); + if(p== LOCAL) return ((y*T1)+x)*T3; + if(p > SOUTH) return ((y*T1)+x)*T3+(p-SOUTH); + if(p== NORTH) return ((T1*T2*T3) + x); + if(p== SOUTH) return ((T1*T2*T3) + T1 + x); + if(p== WEST ) return ((T1*T2*T3) + 2*T1 + y); + if(p== EAST ) return ((T1*T2*T3) + 2*T1 + T2 + y); + return 0;//should not reach here +} + +unsigned int fmesh_addrencode(unsigned int id){ + unsigned int y, x, p, addrencode; + fmesh_Eid_to_coords(id, &x, &y, &p); + addrencode = ( p<<(nxw+nyw) | (y< %d,%d\n",r2r_cnt_all[n].r1, r2r_cnt_all[n].p1,r2r_cnt_all[n].r2,r2r_cnt_all[n].p2); + conect_r2r(1,r2r_cnt_all[n].r1,r2r_cnt_all[n].p1,1,r2r_cnt_all[n].r2,r2r_cnt_all[n].p2); +} + +static inline void topology_connect_r2e (int n){ + //printf ("%d,%d -> %d\n",r2e_cnt_all[n].r1,r2e_cnt_all[n].p1,n); + connect_r2e(1,r2e_cnt_all[n].r1,r2e_cnt_all[n].p1,n); +} + +#define fill_r2r_cnt(T1,R1,P1,T2,R2,P2) (r2r_cnt_table_t){.id1=R1,.t1=T1,.r1=R1,.p1=P1,.id2=R2,.t2=T2,.r2=R2,.p2=P2} -/* -void topology_connect_all_nodes_old (void){ + +static inline void topology_edge_connect(unsigned id1, unsigned id2, unsigned int p1, unsigned int p2, unsigned int fmesh_id,unsigned int R_ADDR, unsigned *num) { + #if defined (IS_MESH) || defined (IS_MESH_3D) || defined (IS_LINE) + connect_r2gnd(1,id1,p1); + #elif defined (IS_TORUS) || defined (IS_RING) + r2r_cnt_all[*num]=fill_r2r_cnt(1,id1,p1,1,id2,p2); + (*num)++; + #elif defined (IS_FMESH) + r2e_cnt_all[fmesh_id].r1=id1; + r2e_cnt_all[fmesh_id].p1=p1; + er_addr [fmesh_id] = R_ADDR; + #endif//topology +} + +void topology_init(void){ + nxw=Log2(X_MAX); + nyw=Log2(Y_MAX); + nzw=Log2(Z_MAX); - unsigned int x,y,l; - #if defined (IS_LINE) || defined (IS_RING ) - #define R2R_CHANELS_MESH_TORI 2 - for (x=0; xcurrent_r_addr = x; - router1[x]->current_r_id = x; - if(x < T1-1){// not_last_node - //assign router_chan_in[x][FORWARD] = router_chan_out [(x+1)][BACKWARD]; - conect_r2r(1,x,FORWARD,1,(x+1),BACKWARD); - } else { //last_node - - #if defined (IS_LINE) // : line_last_x - //assign router_chan_in[x][FORWARD]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,FORWARD); - #else // : ring_last_x - //assign router_chan_in[x][FORWARD]= router_chan_out [0][BACKWARD]; - conect_r2r(1,x,FORWARD,1,0,BACKWARD); - #endif - } - if(x>0){// :not_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; - conect_r2r(1,x,BACKWARD,1,(x-1),FORWARD); - - }else {// :first_x - #if defined (IS_LINE) // : line_first_x - //assign router_chan_in[x][BACKWARD]={SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,BACKWARD); - #else // : ring_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; - conect_r2r(1,x,BACKWARD,1,(T1-1),FORWARD); - #endif - } - // connect other local ports - for (l=0; lcurrent_r_addr = R_ADDR; router1[ROUTER_NUM]->current_r_id = ROUTER_NUM; - if(x < T1-1) {//: not_last_x - //assign router_chan_in[`router_id(x,y)][EAST]= router_chan_out [`router_id(x+1,y)][WEST]; - conect_r2r(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); - - }else {// :last_x - #if defined (IS_MESH) // :last_x_mesh - // assign router_chan_in[`router_id(x,y)][EAST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),EAST); - #elif defined (IS_TORUS) // : last_x_torus - //assign router_chan_in[`router_id(x,y)][EAST] = router_chan_out [`router_id(0,y)][WEST]; - conect_r2r(1,router_id(x,y),EAST,1,router_id(0,y),WEST); - #elif defined (IS_FMESH) //:last_x_fmesh - //connect to endp - unsigned int EAST_ID = T1*T2*T3 + 2*T1 + T2 + y; - connect_r2e(1,router_id(x,y),EAST,EAST_ID); - er_addr [EAST_ID] = R_ADDR; - #endif//topology - } - if(y>0) {// : not_first_y - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; - conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); - }else {// :first_y - #if defined (IS_MESH) // : first_y_mesh - //assign router_chan_in[`router_id(x,y)][NORTH] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),NORTH); - #elif defined (IS_TORUS)// :first_y_torus - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(T2-1))][SOUTH]; - conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); - #elif defined (IS_FMESH) // :first_y_fmesh - unsigned int NORTH_ID = T1*T2*T3 + x; - connect_r2e(1,router_id(x,y),NORTH,NORTH_ID); - er_addr [NORTH_ID] = R_ADDR; - #endif//topology - }//y>0 - if(x>0){// :not_first_x - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; - conect_r2r(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); - }else {// :first_x - - #if defined (IS_MESH) // :first_x_mesh - //assign router_chan_in[`router_id(x,y)][WEST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),WEST); - - #elif defined (IS_TORUS) // :first_x_torus - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; - conect_r2r(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); - #elif defined (IS_FMESH) // :first_x_fmesh - unsigned int WEST_ID = T1*T2*T3 + 2*T1 + y; - connect_r2e(1,router_id(x,y),WEST,WEST_ID); - er_addr [WEST_ID] = R_ADDR; - #endif//topology - } - if(y < T2-1) {// : firsty - //assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; - conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); - }else {// : lasty - - #if defined (IS_MESH) // :ly_mesh - - //assign router_chan_in[`router_id(x,y)][SOUTH]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),SOUTH); - - #elif defined (IS_TORUS) // :ly_torus - //assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; - conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); - #elif defined (IS_FMESH) // :ly_Fmesh - unsigned int SOUTH_ID = T1*T2*T3 + T1 + x; - connect_r2e(1,router_id(x,y),SOUTH,SOUTH_ID); - er_addr [SOUTH_ID] = R_ADDR; - #endif//topology - } + unsigned int FMESH_EAST_ID = T1*T2*T3 + 2*T1 + T2 + y; + unsigned int FMESH_WEST_ID = T1*T2*T3 + 2*T1 + y; + unsigned int FMESH_SOUTH_ID = T1*T2*T3 + T1 + x; + unsigned int FMESH_NORTH_ID = T1*T2*T3 + x; // endpoint(s) connection - // connect other local ports - for (l=0; l0) r2r_cnt_all[num++]=fill_r2r_cnt(1,ROUTER_NUM,WEST,1,router_id((x-1),y,z),EAST); + else topology_edge_connect(ROUTER_NUM, router_id((X_MAX-1),y,z), WEST, EAST, FMESH_WEST_ID, R_ADDR, &num); + if(DIM==1) continue; + if (y < Y_MAX-1) r2r_cnt_all[num++] = fill_r2r_cnt(1, ROUTER_NUM, SOUTH, 1, router_id(x, y + 1, z), NORTH); + else topology_edge_connect(ROUTER_NUM, router_id(x, 0, z), SOUTH, NORTH, FMESH_SOUTH_ID, R_ADDR, &num); + + if (y>0) r2r_cnt_all[num++] = fill_r2r_cnt(1, ROUTER_NUM, NORTH, 1, router_id(x, y - 1, z), SOUTH); + else topology_edge_connect(ROUTER_NUM, router_id(x, (Y_MAX-1), z), NORTH, SOUTH, FMESH_NORTH_ID, R_ADDR, &num); + if(DIM==2) continue; + if (z < Z_MAX-1) r2r_cnt_all[num++] = fill_r2r_cnt(1, router_id(x, y, z), UP, 1, router_id(x, y, z + 1), DOWN); + else connect_r2gnd(1,ROUTER_NUM,UP); + if (z > 0) r2r_cnt_all[num++] = fill_r2r_cnt(1, ROUTER_NUM, DOWN, 1, router_id(x, y, z - 1), UP); + else connect_r2gnd(1,ROUTER_NUM,DOWN); }//y }//x - #endif -} -*/ -#define fill_r2r_cnt(T1,R1,P1,T2,R2,P2) (r2r_cnt_table_t){.id1=R1,.t1=T1,.r1=R1,.p1=P1,.id2=R2,.t2=T2,.r2=R2,.p2=P2} - -void topology_init(void){ - nxw=Log2(T1); - nyw=Log2(T2); - maskx = (0x1<current_r_addr = x; - router1[x]->current_r_id = x; - if(x < T1-1){// not_last_node - //assign router_chan_in[x][FORWARD] = router_chan_out [(x+1)][BACKWARD]; - //conect_r2r(1,x,FORWARD,1,(x+1),BACKWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,FORWARD,1,(x+1),BACKWARD); - num++; - } else { //last_node - #if defined (IS_LINE) // : line_last_x - //assign router_chan_in[x][FORWARD]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,FORWARD); - #else // : ring_last_x - //assign router_chan_in[x][FORWARD]= router_chan_out [0][BACKWARD]; - //conect_r2r(1,x,FORWARD,1,0,BACKWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,FORWARD,1,0,BACKWARD); - num++; - #endif - } - if(x>0){// :not_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(x-1)][FORWARD]; - //conect_r2r(1,x,BACKWARD,1,(x-1),FORWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,BACKWARD,1,(x-1),FORWARD); - num++; - }else {// :first_x - #if defined (IS_LINE) // : line_first_x - //assign router_chan_in[x][BACKWARD]={SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,x,BACKWARD); - #else // : ring_first_x - //assign router_chan_in[x][BACKWARD]= router_chan_out [(NX-1)][FORWARD]; - //conect_r2r(1,x,BACKWARD,1,(T1-1),FORWARD); - r2r_cnt_all[num]=fill_r2r_cnt(1,x,BACKWARD,1,(T1-1),FORWARD); - num++; - #endif - } - // connect other local ports - for (l=0; lcurrent_r_addr = R_ADDR; - router1[ROUTER_NUM]->current_r_id = ROUTER_NUM; - if(x < T1-1) {//: not_last_x - //assign router_chan_in[`router_id(x,y)][EAST]= router_chan_out [`router_id(x+1,y)][WEST]; - //conect_r2r(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),EAST,1,router_id(x+1,y),WEST); - num++; - }else {// :last_x - #if defined (IS_MESH) // :last_x_mesh - // assign router_chan_in[`router_id(x,y)][EAST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),EAST); - #elif defined (IS_TORUS) // : last_x_torus - //assign router_chan_in[`router_id(x,y)][EAST] = router_chan_out [`router_id(0,y)][WEST]; - //conect_r2r(1,router_id(x,y),EAST,1,router_id(0,y),WEST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),EAST,1,router_id(0,y),WEST); - num++; - #elif defined (IS_FMESH) //:last_x_fmesh - //connect to endp - unsigned int EAST_ID = T1*T2*T3 + 2*T1 + T2 + y; - //connect_r2e(1,router_id(x,y),EAST,EAST_ID); - r2e_cnt_all[EAST_ID].r1=router_id(x,y); - r2e_cnt_all[EAST_ID].p1=EAST; - er_addr [EAST_ID] = R_ADDR; - #endif//topology - } - if(y>0) {// : not_first_y - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(y-1))][SOUTH]; - //conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),NORTH,1,router_id(x,(y-1)),SOUTH); - num++; - }else {// :first_y - #if defined (IS_MESH) // : first_y_mesh - //assign router_chan_in[`router_id(x,y)][NORTH] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),NORTH); - #elif defined (IS_TORUS)// :first_y_torus - //assign router_chan_in[`router_id(x,y)][NORTH] = router_chan_out [`router_id(x,(T2-1))][SOUTH]; - //conect_r2r(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),NORTH,1,router_id(x,(T2-1)),SOUTH); - num++; - #elif defined (IS_FMESH) // :first_y_fmesh - unsigned int NORTH_ID = T1*T2*T3 + x; - //connect_r2e(1,router_id(x,y),NORTH,NORTH_ID); - r2e_cnt_all[NORTH_ID].r1=router_id(x,y); - r2e_cnt_all[NORTH_ID].p1=NORTH; - er_addr [NORTH_ID] = R_ADDR; - #endif//topology - }//y>0 - if(x>0){// :not_first_x - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((x-1),y)][EAST]; - //conect_r2r(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),WEST,1,router_id((x-1),y),EAST); - num++; - }else {// :first_x - #if defined (IS_MESH) // :first_x_mesh - //assign router_chan_in[`router_id(x,y)][WEST] = {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),WEST); - #elif defined (IS_TORUS) // :first_x_torus - //assign router_chan_in[`router_id(x,y)][WEST] = router_chan_out [`router_id((NX-1),y)][EAST] ; - //conect_r2r(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),WEST,1,router_id((T1-1),y),EAST); - num++; - #elif defined (IS_FMESH) // :first_x_fmesh - unsigned int WEST_ID = T1*T2*T3 + 2*T1 + y; - //connect_r2e(1,router_id(x,y),WEST,WEST_ID); - r2e_cnt_all[WEST_ID].r1=router_id(x,y); - r2e_cnt_all[WEST_ID].p1=WEST; - er_addr [WEST_ID] = R_ADDR; - #endif//topology - } - if(y < T2-1) {// : firsty - //assign router_chan_in[`router_id(x,y)][SOUTH] = router_chan_out [`router_id(x,(y+1))][NORTH]; - // conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),SOUTH,1,router_id(x,(y+1)),NORTH); - num++; - }else {// : lasty - #if defined (IS_MESH) // :ly_mesh - //assign router_chan_in[`router_id(x,y)][SOUTH]= {SMARTFLIT_CHANEL_w{1'b0}}; - connect_r2gnd(1,router_id(x,y),SOUTH); - #elif defined (IS_TORUS) // :ly_torus - //assign router_chan_in[`router_id(x,y)][SOUTH]= router_chan_out [`router_id(x,0)][NORTH]; - // conect_r2r(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); - r2r_cnt_all[num]=fill_r2r_cnt(1,router_id(x,y),SOUTH,1,router_id(x,0),NORTH); - num++; - #elif defined (IS_FMESH) // :ly_Fmesh - unsigned int SOUTH_ID = T1*T2*T3 + T1 + x; - //connect_r2e(1,router_id(x,y),SOUTH,SOUTH_ID); - r2e_cnt_all[SOUTH_ID].r1=router_id(x,y); - r2e_cnt_all[SOUTH_ID].p1=SOUTH; - er_addr [SOUTH_ID] = R_ADDR; - #endif//topology - } - // endpoint(s) connection - // connect other local ports - for (l=0; l x2) ? (x1 - x2) : (x2 - x1); unsigned int y_diff = (y1 > y2) ? (y1 - y2) : (y2 - y1); - return x_diff + y_diff; + unsigned int z_diff = (z1 > z2) ? (z1 - z2) : (z2 - z1); + return x_diff + y_diff + z_diff; } -#endif +#endif \ No newline at end of file diff --git a/mpsoc/src_verilator/topology/topology_top.h b/mpsoc/src_verilator/topology/topology_top.h index 361292c..5143e4d 100644 --- a/mpsoc/src_verilator/topology/topology_top.h +++ b/mpsoc/src_verilator/topology/topology_top.h @@ -37,7 +37,7 @@ NR_num-=1; offset += router_NRs[NR_num]; } - return offset + NR_id; + return offset + NR_id; } #endif @@ -52,12 +52,12 @@ } unsigned int powi (unsigned int x, unsigned int y){ // x^y - unsigned int i; + unsigned int i; unsigned int pow=1; for (int i = 0; i >1; mcast_list_array[i*4+2] = (ch & 0x4)>>2; mcast_list_array[i*4+3] = (ch & 0x8)>>3; @@ -350,28 +158,152 @@ void mcast_init(){ ch&=0xf; mcast_list_array[i ] = ch; } - } - for (i=0;i Date: Wed, 19 Nov 2025 11:49:57 +0100 Subject: [PATCH 096/107] add amba chi wrapper --- .gitignore | 1 + mpsoc/rtl/src_ambachi/chi_wrapper.sv | 354 ++++++++++++++++++ mpsoc/rtl/src_ambachi/noc_localparam.v | 79 ++++ mpsoc/rtl/src_openpiton/noc_localparam.v | 1 + .../{wrapper.sv => piton_wrapper.sv} | 0 mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh | 42 +++ .../script/phy_noc_gen/OpenPiton_nocs_gen.sh | 6 +- 7 files changed, 480 insertions(+), 3 deletions(-) create mode 100644 mpsoc/rtl/src_ambachi/chi_wrapper.sv create mode 100644 mpsoc/rtl/src_ambachi/noc_localparam.v rename mpsoc/rtl/src_openpiton/{wrapper.sv => piton_wrapper.sv} (100%) create mode 100644 mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh diff --git a/.gitignore b/.gitignore index addcd4a..90d2654 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ mpsoc/remove_cycle/__pycache__ mpsoc_work/ mpsoc/rtl/src_openpiton/nocs +mpsoc/rtl/src_ambachi/nocs mpsoc/Integration_test/**/work mpsoc/Integration_test/**/result_logs/* diff --git a/mpsoc/rtl/src_ambachi/chi_wrapper.sv b/mpsoc/rtl/src_ambachi/chi_wrapper.sv new file mode 100644 index 0000000..8d4f819 --- /dev/null +++ b/mpsoc/rtl/src_ambachi/chi_wrapper.sv @@ -0,0 +1,354 @@ +`include "pronoc_def.v" + +/************************************** +* Module: chi_wrapper +* Date:2019-05-03 +* Author: alireza +* +* Description: +***************************************/ + + +module chi_to_pronoc_wrapper ( + chi_flit_i, + chi_flitpend_i, + chi_flitv_i, + chi_lcrdv_i, + current_r_addr_i, + pronoc_chan_out, + clk, + reset +); + import pronoc_pkg::*; + import amba_5_chi_c_pkg::*; + + input chi_flitpend_i, chi_flitv_i, chi_lcrdv_i, clk,reset; + input [Fpay-1 : 0] chi_flit_i; + input [RAw-1 : 0] current_r_addr_i; + output smartflit_chanel_t pronoc_chan_out; + + wire [QOS_REQ-1 : 0] qos; + wire [TGTID_REQ-1 : 0] target_id; + wire [SRCID_REQ-1 : 0] src_id; + wire [Fpay-QOS_REQ-TGTID_REQ-SRCID_REQ-1 : 0] rest_flit; + assign {qos,target_id,src_id,rest_flit} = chi_flit_i; + + wire [ EAw-1 : 0] dest_e_addr;// = target_id[ EAw-1 : 0];//TODO need to check how they code the destiation adreeses + wire [ EAw-1 : 0] src_e_addr;// = src_id[ EAw-1 : 0];//TODO need to check how they code the source adreeses + wire [DSTPw-1: 0] destport; + wire [Fw-1 : 0] pronoc_hdr_flit; + + endp_addr_encoder des_addr_encoder ( + .id_in(target_id[NEw-1:0]), + .code_out(dest_e_addr) + ); + + endp_addr_encoder src_addr_encoder ( + .id_in(src_id[NEw-1:0]), + .code_out(src_e_addr) + ); + + generate + if((CAST_TYPE == "UNICAST") && (IS_LOOKAHEAD==1'b1)) begin : uni + //The router is configured with lookaheadrouting. + //The header flit is supposed to carry the destinaion output port + conventional_routing #( + .LOCATED_IN_NI(1) + ) route_compute ( + .reset(1'b0), //only needed for fattree + .clk(1'b0), // only needed for fattree + .current_r_addr(current_r_addr_i), + .dest_e_addr(dest_e_addr), + .src_e_addr(src_e_addr), + .destport(destport) + ); + end + endgenerate + localparam [WEIGHTw-1 : 0] WINIT = 1; + + header_flit_generator #( + .DATA_w(Fpay) + ) hdr_flit_gen ( + .flit_out(pronoc_hdr_flit), + .class_in(1'b0), + .dest_e_addr_in(dest_e_addr), + .src_e_addr_in(src_e_addr), + .destport_in(destport), + .vc_num_in(1'b0), + .weight_in(WINIT), + .data_in(chi_flit_i), + .be_in(1'b0) + ); + + assign pronoc_chan_out.flit_chanel.flit_wr = chi_flitv_i; + assign pronoc_chan_out.flit_chanel.credit = chi_lcrdv_i; + assign pronoc_chan_out.flit_chanel.flit.hdr_flag = 1'b1; + assign pronoc_chan_out.flit_chanel.flit.tail_flag = 1'b1; + assign pronoc_chan_out.flit_chanel.flit.vc = 1'b1; + assign pronoc_chan_out.flit_chanel.flit.payload = pronoc_hdr_flit[FPAYw-1 : 0]; + //credit release should be asserted externaly via register. For simulation we just use a counter to set it few cycles after reset + reg [3:0] counter; + always @(posedge clk or posedge reset)begin + if(reset) counter<=0; + else if(counter<4) counter=counter+1'b1; + end + + wire credit_release = counter==4; + genvar i; + generate + for (i=0; i. +******************************************************************************/ + +`ifdef NOC_LOCAL_PARAM +//TODO: replace it with package + + import amba_5_chi_c_pkg::*; + `include "pronoc_conf.svh" + + + //NoC parameters + localparam NOC_ID=0; + localparam V=1; + localparam LB=B; + localparam ROUTE_MODE="LOOKAHEAD"; + localparam PCK_TYPE="SINGLE_FLIT"; + localparam MIN_PCK_SIZE=1; + localparam BYTE_EN=0; + localparam SSA_EN="NO"; + localparam SMART_MAX=0; + localparam CONGESTION_INDEX=3; + localparam ESCAP_VC_MASK=1; + localparam VC_REALLOCATION_TYPE="NONATOMIC"; + localparam COMBINATION_TYPE="COMB_NONSPEC"; + localparam MUX_TYPE="BINARY"; + localparam C=1; + localparam ADD_PIPREG_AFTER_CROSSBAR=1'b0; + localparam FIRST_ARBITER_EXT_P_EN=1; + localparam SWA_ARBITER_TYPE="RRA"; + localparam WEIGHTw=4; + localparam SELF_LOOP_EN="NO"; + localparam AVC_ATOMIC_EN=0; + localparam CVw=(C==0)? V : C * V; + localparam CLASS_SETTING={CVw{1'b1}}; + localparam CAST_TYPE = "UNICAST"; + localparam MCAST_ENDP_LIST = 'b11110011; + localparam HETERO_VC=0; + localparam DEBUG_EN=1; + + //simulation parameter + //localparam MAX_RATIO = 1000; + localparam MAX_PCK_NUM = 1000000000; + localparam MAX_PCK_SIZ = 16383; + localparam MAX_SIM_CLKs= 1000000000; + localparam TIMSTMP_FIFO_NUM = 16; + localparam MAX_ROUTER=1; + localparam MAX_PORT=1; + localparam int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]='{'{0}}; + + localparam Fpay = + (NOC_ID =="dat")? DAT_FLIT_SIZE : + (NOC_ID =="req")? REQ_FLIT_SIZE : + (NOC_ID =="rsp")? RSP_FLIT_SIZE : SNP_FLIT_SIZE; +`endif diff --git a/mpsoc/rtl/src_openpiton/noc_localparam.v b/mpsoc/rtl/src_openpiton/noc_localparam.v index 11684b8..a286697 100644 --- a/mpsoc/rtl/src_openpiton/noc_localparam.v +++ b/mpsoc/rtl/src_openpiton/noc_localparam.v @@ -9,6 +9,7 @@ localparam T1=`PITON_X_TILES; localparam T2=`PITON_Y_TILES; localparam T3=1; + localparam T4=1; localparam V=1; localparam C=0; localparam B=4; diff --git a/mpsoc/rtl/src_openpiton/wrapper.sv b/mpsoc/rtl/src_openpiton/piton_wrapper.sv similarity index 100% rename from mpsoc/rtl/src_openpiton/wrapper.sv rename to mpsoc/rtl/src_openpiton/piton_wrapper.sv diff --git a/mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh b/mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh new file mode 100644 index 0000000..e660b58 --- /dev/null +++ b/mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# This script generates three physical NoCs for OpenPiton using ProNoC RTL code. +# Each physical NoC (phynoc) is configured with unified module and parameter names. +# The NoC number is appended to parameters, functions, and module names to ensure uniqueness. + +# Get the full path of the script +SCRIPT_FULL_PATH=$(realpath "${BASH_SOURCE[0]}") +SCRIPT_DIR_PATH=$(dirname "$SCRIPT_FULL_PATH") + +# OpenPiton target NoC directory +op_nocs_dir="$SCRIPT_DIR_PATH/../../rtl/src_ambachi" + +# ProNoC RTL dir +pronoc_dir="$SCRIPT_DIR_PATH/../../rtl/src_noc" + +# Script to create physical NoCs +phy_noc_gen="$SCRIPT_DIR_PATH/phy_noc.pl" + +cp "$op_nocs_dir/chi_wrapper.sv" "$pronoc_dir/chi_wrapper.sv" +mv "$pronoc_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v.tmp" +cp "$op_nocs_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v" + +# Loop to generate three physical NoCs +IN="" +LIST="" +arr=("dat" "rsp" "snp" "req") + +for i in "${arr[@]}"; do + mkdir -p "$op_nocs_dir/nocs/noc_$i" + perl "$phy_noc_gen" "$i" "$op_nocs_dir/nocs/noc_$i" + IN+="+incdir+./noc_${i}\n" + LIST+="-F ./noc_${i}/noc_filelist_${i}.f\n" + LIST+="./noc_${i}/chi_wrapper_${i}.sv\n" +done + +# Clean up and restore the original file +rm "$pronoc_dir/chi_wrapper.sv" +mv "$pronoc_dir/noc_localparam.v.tmp" "$pronoc_dir/noc_localparam.v" + +# Generate the file list for physical NoCs +printf "${IN}$LIST" > "$op_nocs_dir/nocs/Flist.pronoc" diff --git a/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh b/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh index 81548ed..246e0f1 100644 --- a/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh +++ b/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh @@ -17,7 +17,7 @@ pronoc_dir="$SCRIPT_DIR_PATH/../../rtl/src_noc" # Script to create physical NoCs phy_noc_gen="$SCRIPT_DIR_PATH/phy_noc.pl" -cp "$op_nocs_dir/wrapper.sv" "$pronoc_dir/wrapper.sv" +cp "$op_nocs_dir/piton_wrapper.sv" "$pronoc_dir/piton_wrapper.sv" mv "$pronoc_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v.tmp" cp "$op_nocs_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v" @@ -29,11 +29,11 @@ for i in {1..3}; do perl "$phy_noc_gen" "N$i" "$op_nocs_dir/nocs/noc$i" IN+="+incdir+./noc${i}\n" LIST+="-F ./noc${i}/noc_filelist_N${i}.f\n" - LIST+="./noc${i}/wrapper_N${i}.sv\n" + LIST+="./noc${i}/piton_wrapper_N${i}.sv\n" done # Clean up and restore the original file -rm "$pronoc_dir/wrapper.sv" +rm "$pronoc_dir/piton_wrapper.sv" mv "$pronoc_dir/noc_localparam.v.tmp" "$pronoc_dir/noc_localparam.v" # Generate the file list for physical NoCs From fd6727745fc3f2eb443af1ec7b0e6f280e8f4e57 Mon Sep 17 00:00:00 2001 From: amonemi Date: Tue, 25 Nov 2025 14:29:02 +0100 Subject: [PATCH 097/107] Correct the graph title in endp-to-endp statistics view --- mpsoc/perl_gui/lib/perl/graph.pl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/graph.pl b/mpsoc/perl_gui/lib/perl/graph.pl index 1ab5661..29b983d 100755 --- a/mpsoc/perl_gui/lib/perl/graph.pl +++ b/mpsoc/perl_gui/lib/perl/graph.pl @@ -145,9 +145,20 @@ sub gen_heat_map{ my $save = def_image_button('icons/save.png',undef,TRUE); my $type_combo=gen_combobox_object ($self,"${graph_id}","type","Table,Image",'Table','ref',2); my @samples =$self->object_get_attribute_order("samples"); - @samples = ('-') if (scalar @samples == 0); - my $sample_combx=gen_combobox_object ($self,${graph_id},"sample_sel",join(",", @samples),$samples[0],'ref',2); + my @sample_names; + for my $i (0..$#samples) { + my $name=$self->object_get_attribute($samples[$i],"line_name"); + $sample_names[$i]=$name if(defined $name); + } + @sample_names = ('-') if (scalar @samples == 0); + my $sample_combx=gen_combobox_object ($self,${graph_id},"sample_sel",join(",", @sample_names),$sample_names[0],'ref',2); my $sample = $self->object_get_attribute("${graph_id}","sample_sel"); + for my $i (0..$#samples) { + if ($sample_names[$i] eq $sample){ + $sample = $samples[$i]; + last; + } + } my $ref=$self->object_get_attribute ($sample,$result_name); my @ratios; @ratios = get_uniq_keys($ref,@ratios); From 301335fe7b950f1e25f26082d287a656ad2d75f7 Mon Sep 17 00:00:00 2001 From: amonemi Date: Tue, 25 Nov 2025 15:09:14 +0100 Subject: [PATCH 098/107] replace some generate loops with always_comb --- mpsoc/rtl/src_noc/inout_ports.sv | 28 ++++++++++++------------- mpsoc/rtl/src_noc/input_ports.sv | 6 +++--- mpsoc/rtl/src_noc/mesh_torus_noc_top.sv | 2 +- mpsoc/rtl/src_noc/router_top.sv | 23 +++----------------- mpsoc/rtl/src_noc/router_two_stage.sv | 12 +++++------ mpsoc/rtl/src_noc/ss_allocator.sv | 5 ++--- 6 files changed, 29 insertions(+), 47 deletions(-) diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index f04e998..8d2284f 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -27,7 +27,7 @@ module inout_ports #( parameter ROUTER_ID=0, - parameter P=5 + parameter P=5 )( clk, reset, @@ -99,7 +99,7 @@ module inout_ports #( WPP = WP * P; input router_info_t router_info; - input [PFw-1 : 0] flit_in_all; + input flit_t flit_in_all [P-1 : 0]; input [P-1 : 0] flit_in_wr_all; output[PV-1 : 0] credit_out_all; input [PV-1 : 0] credit_in_all; @@ -132,7 +132,7 @@ module inout_ports #( // to crossbar output [Fw-1 : 0] flit_out_all [P-1:0]; - output [P-1 : 0] ssa_flit_wr_all; + output logic [P-1 : 0] ssa_flit_wr_all; output [WP-1: 0] iport_weight_all; output [WPP-1:0] oports_weight_all; input refresh_w_counter; @@ -281,16 +281,16 @@ module inout_ports #( ); end else begin :non_ssa - for(i=0;i< P;i=i+1) begin :p_ + for(i=0;i< P;i=i+1) begin :P_ assign ssa_ctrl[i] = {SSA_CTRL_w{1'b0}}; end - end //ssa - - for(i=0;i< P;i=i+1) begin :p_ - assign ssa_flit_wr_all [i] = ssa_ctrl[i].ssa_flit_wr; - end//for - - `ifdef SIMULATION + end //ssa + always_comb begin + for(int k=0;k< P;k++) begin + ssa_flit_wr_all [k] = ssa_ctrl[k].ssa_flit_wr; + end//for + end + `ifdef SIMULATION if(DEBUG_EN && MIN_PCK_SIZE >1 )begin :dbg wire [PV-1 : 0] non_vsa_ivc_num_getting_ovc_grant_all; integer kk; @@ -300,12 +300,12 @@ module inout_ports #( always @(posedge clk ) begin for(kk=0; kk< PV; kk=kk+1'b1 ) if(reset_ivc_all[kk] & (ivc_num_getting_ovc_grant[kk] | non_vsa_ivc_num_getting_ovc_grant_all[kk])) begin $display("%t: ERROR: the ovc %d released and allocat signal is asserted in the same clock cycle : %m",$time,kk); - $finish; + $finish; end end end - `endif// SIMULATION - endgenerate + `endif// SIMULATION + endgenerate endmodule /****************** diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 7aa730d..a42602f 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -82,14 +82,14 @@ module input_ports #( input router_info_t router_info; output [PV-1 : 0] ivc_num_getting_sw_grant; input [P-1 : 0] any_ivc_sw_request_granted_all; - input [PFw-1 : 0] flit_in_all; + input flit_t flit_in_all [P-1 : 0]; input [P-1 : 0] flit_in_wr_all; output [PV-1 : 0] reset_ivc_all; output [PV-1 : 0] flit_is_tail_all; output [PV-1 : 0] ivc_request_all; output [PV-1 : 0] credit_out_all; output [PVP_1-1 : 0] dest_port_all; - output [Fw-1 : 0] flit_out_all [P-1 : 0]; + output flit_t flit_out_all [P-1 : 0]; input [PV-1 : 0] assigned_ovc_not_full_all; output [PV-1 : 0] ovc_is_assigned_all; input [PV-1 : 0] sel; @@ -127,7 +127,7 @@ module input_ports #( .credit_out(credit_out_all [(i+1)*V-1 : i*V]), .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant [(i+1)*V-1 : i*V]),// for non spec ivc_num_getting_first_sw_grant, .any_ivc_sw_request_granted(any_ivc_sw_request_granted_all [i]), - .flit_in(flit_in_all[(i+1)*Fw-1 : i*Fw]), + .flit_in(flit_in_all[i]), .flit_in_wr(flit_in_wr_all[i]), .reset_ivc(reset_ivc_all [(i+1)*V-1 : i*V]), .flit_is_tail(flit_is_tail_all [(i+1)*V-1 : i*V]), diff --git a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv index 60473e0..64099a5 100644 --- a/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv +++ b/mpsoc/rtl/src_noc/mesh_torus_noc_top.sv @@ -172,7 +172,7 @@ module regular_topo_noc_top ( end // endpoint(s) connection // connect other local ports - for (l=0; l Date: Wed, 26 Nov 2025 11:58:32 +0100 Subject: [PATCH 099/107] fix linting warning --- mpsoc/rtl/src_noc/mesh_3d_top.sv | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/mpsoc/rtl/src_noc/mesh_3d_top.sv b/mpsoc/rtl/src_noc/mesh_3d_top.sv index 67ff523..43048e4 100644 --- a/mpsoc/rtl/src_noc/mesh_3d_top.sv +++ b/mpsoc/rtl/src_noc/mesh_3d_top.sv @@ -69,7 +69,13 @@ module mesh_3d_noc_top ( for (y=0; yobject_add_attribute($noc_param,'T2',$param{$topology_name}{'T2'}); + $noc_param_comment{"T2"} = "Total number of routers in the CUSTOM topology."; $mpsoc->object_add_attribute($noc_param,'T3',$param{$topology_name}{'T3'}); - $mpsoc->object_add_attribute($noc_param,'T4',$param{$topology_name}{'T4'}); + $noc_param_comment{"T3"} = "Maximum number of ports in a router in the CUSTOM topology."; + $mpsoc->object_add_attribute($noc_param,'T4',0); + $noc_param_comment{"T4"} = "Unused in the CUSTOM topology."; $mpsoc->object_add_attribute('noc_connection','er_addr',$param{$topology_name}{'er_addr'}); + $noc_param_comment{"ROUTE_NAME"} = "Source-destination routing name for the CUSTOM topology."; return ($row,$coltmp); } diff --git a/mpsoc/perl_gui/lib/perl/network_maker.pl b/mpsoc/perl_gui/lib/perl/network_maker.pl index cddfe6f..6f1a589 100644 --- a/mpsoc/perl_gui/lib/perl/network_maker.pl +++ b/mpsoc/perl_gui/lib/perl/network_maker.pl @@ -13,6 +13,9 @@ use tsort; use File::Basename; use Cwd 'abs_path'; +use YAML::PP; +use YAML::PP::Common; +use Data::Dumper; __PACKAGE__->mk_accessors(qw{ window @@ -313,8 +316,8 @@ sub take_node_num_page{ my $table= def_table(2,10,FALSE); my $row=0; my $col=4; - $table->attach (def_label('Network Element'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=2; - $table->attach (def_label('Number'),$col,$col+1,$row,$row+1,'fill','shrink',2,2); + # $table->attach (def_label('Network Element'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col+=2; + # $table->attach (def_label('Number'),$col,$col+1,$row,$row+1,'fill','shrink',2,2); $row++;$col=0; $table->attach (def_icon('icons/e.png'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++; ($row,$col)=add_param_widget ($self,"# Endpoints","NUM", 0,'Spin-button','0,1024,1',undef, $table,$row,$col,1,'ENDP',10,'redraw');$col=0; @@ -347,7 +350,7 @@ sub take_instance_page{ $n=0 if(!defined $n); for ( my $j=0;$j<$n; $j++){ my $d=get_default_instance_name($self,"ROUTER${i}_$j"); - ($row,$col)=add_param_widget ($self,"Router $Rnum","NAME", "$d",'Entry',undef,"router instance name", $table,$row,$col,1,"ROUTER${i}_$j",10,'redraw');$col=0; + ($row,$col)=add_param_widget ($self,"${i}-PortRouter${j}","NAME", "$d",'Entry',undef,"router instance name", $table,$row,$col,1,"ROUTER${i}_$j",10,'redraw');$col=0; $Rnum++; } } @@ -662,7 +665,7 @@ sub evaluate_eqation{ } else{ my ($v, $start, $end, $step) = sscanf("%s[%d,%d,%d]", $p); - print "($v, $start, $end, $step)\n"; + #print "($v, $start, $end, $step)\n"; my @a; for (my $i=$start; $i<$end;$i++){ push (@a,$i); @@ -1629,7 +1632,7 @@ sub get_forbiden_turns_old { if (defined $path){ #path counting my @a_nodes= get_adjacent_node_in_a_path($path);#get_adjacent_router_in_a_path($path); - print "@a_nodes = \@a_nodes \n"; + #print "@a_nodes = \@a_nodes \n"; %edge_graph = get_path_edges_graph_file (\@a_nodes,\%edge_graph); #$graph =$graph. $str1; #$graph_coded = $graph_coded . $str2; @@ -2311,6 +2314,135 @@ sub load_nwm{ add_color_to_gd($self); } +sub Get_yaml_noc_conf{ + my ($self,$info)=@_; + my $file; + my $dialog = gen_file_dialog (undef, 'yml'); + my $dir = Cwd::getcwd(); + $dialog->set_current_folder ("$dir/../script/noc_yml_gen") ; + if ( "ok" eq $dialog->run ) { + $file = $dialog->get_filename; + my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$"); + if($suffix eq '.yml'){ + #Read yml file + add_info($info,"Loading Custom NoC configuration from $file\n"); + Read_yaml_noc_conf_file($self,$info,$file); + } + } + $dialog->destroy; + set_gui_status($self,"ref",1) +} + +sub Read_yaml_noc_conf_file{ + my ($self,$info,$file)=@_; + my $yp = YAML::PP->new(preserve => YAML::PP::Common->PRESERVE_ORDER); + my $data = $yp->load_file($file); + my %connections = map { $_->{source} => $_->{dest} } @{$data->{connections}}; + my %endpoints = map { $_->{id} => $_->{endpoints} } @{$data->{nodes}}; + my %port_count; + my %router_hash; + # Track per-port router counters + my %port_counters; + my $enps_count=0; + foreach my $router_id (sort { $a <=> $b } keys %connections) { + my $ports = scalar @{$connections{$router_id}}; # number of dest nodes = ports + my $eps = scalar @{$endpoints{$router_id} // []}; # number of endpoints for this router + $ports+=$eps; + $port_count{$ports}++; + $enps_count+=$eps; + # assign router name router_${p}_${n} + my $n = $port_counters{$ports} // 0; + $router_hash{$router_id} = "ROUTER${ports}_${n}"; + $port_counters{$ports} = $n + 1; + } + $self->object_add_attribute ("ENDP","NUM",$enps_count); + foreach my $p (sort { $a <=> $b } keys %port_count) { + add_info($info,"Add $p-Ports Router: $port_count{$p} number\n"); + $self->object_add_attribute ("ROUTER${p}","NUM",$port_count{$p}); + } + my %port_map; + # Track destination port counters (optional simple assumption: dest ports assigned sequentially) + my %dest_port_counter; + $enps_count=0; + # remembers port assignment between router pairs + my %link_ports; + # track used ports per router + my %router_used_ports; + +foreach my $src_id (sort { $a <=> $b } keys %connections) { + + my $src_router = $router_hash{$src_id}; + my @dst_ids = @{$connections{$src_id}}; + $port_map{$src_router} = []; + + for my $src_port (0 .. $#dst_ids) { + + my $dst_id = $dst_ids[$src_port]; + my $dst_router = $router_hash{$dst_id}; + + my ($assigned_src_port, $assigned_dst_port); + + ############################################################ + # CASE 1: Check if this src–dst link already has port numbers + ############################################################ + if ( exists $link_ports{$src_router}{$dst_router} ) { + + # retrieve the existing pair + ($assigned_src_port, $assigned_dst_port) = + @{ $link_ports{$src_router}{$dst_router} }; + + } else { + + ############################################################ + # CASE 2: New src/dst link → find free ports + ############################################################ + + # ---- find first free src port ---- + my $src_port = 0; + $src_port++ while $router_used_ports{$src_router}{$src_port}; + $assigned_src_port = $src_port; + + # ---- find first free dst port ---- + my $dst_port = 0; + $dst_port++ while $router_used_ports{$dst_router}{$dst_port}; + $assigned_dst_port = $dst_port; + + # Save symmetric mapping + $link_ports{$src_router}{$dst_router} = + [ $assigned_src_port, $assigned_dst_port ]; + + $link_ports{$dst_router}{$src_router} = + [ $assigned_dst_port, $assigned_src_port ]; + + # Mark ports as used + $router_used_ports{$src_router}{$assigned_src_port} = 1; + $router_used_ports{$dst_router}{$assigned_dst_port} = 1; + } + + ############################################################ + # Connect routers with the consistent port numbers + ############################################################ + + connect_nodes( + $self, + $src_router, "Port[$assigned_src_port]", + $dst_router, "Port[$assigned_dst_port]", + $info + ); + } + my $eps = scalar @{$endpoints{$src_id} // []}; + + for (my $e= 0; $e<$eps;$e++ ){ + my $src_port=$#dst_ids + $e +1; + connect_nodes ($self,$src_router,"Port[$src_port]","ENDP_$enps_count","Port[0]",$info); + } + $enps_count+=$eps; + } + #print "\nRouter hash mapping:\n"; + #print Dumper(\%router_hash); + set_gui_status($self,"redraw",1) +} + sub build_network_maker_gui { my ($self) = @_; set_gui_status($self,"ideal",0); @@ -2344,6 +2476,8 @@ sub build_network_maker_gui { my $v2=gen_vpaned($h1,.65,$infobox); my $pronoc_dir = get_project_dir(); #mpsoc dir addr my $target_dir= "$pronoc_dir/mpsoc/rtl/src_topology/"; + my $yml = def_image_button('icons/yaml.png','Load YAML'); + set_tip($yml, "Read Custom NoC configuration from yaml file."); my ($entrybox,$entry ) =gen_save_load_widget ( $self, #the object "Topology name",#the label shown for setting configuration @@ -2363,6 +2497,7 @@ sub build_network_maker_gui { $self->object_add_attribute ("routing_name",undef,$name); }); $main_table->attach_defaults ($v2 , 0, 12, 0,24); + $main_table->attach ($yml,0, 2, 24,25,'expand','shrink',2,2); $main_table->attach ($entrybox,2, 4, 24,25,'expand','shrink',2,2); $main_table->attach ($entrybox2,4, 6, 24,25,'expand','shrink',2,2); $main_table->attach ($generate, 6, 9, 24,25,'expand','shrink',2,2); @@ -2379,6 +2514,9 @@ sub build_network_maker_gui { $generate->signal_connect("clicked" => sub{ generate_topology($self,$info); }); + $yml->signal_connect("clicked" => sub{ + Get_yaml_noc_conf($self,$info); + }); #check soc status every 0.5 second. refresh device table if there is any changes Glib::Timeout->add (100, sub{ my ($state,$timeout)= get_gui_status($self); diff --git a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl index abd52b7..af2f081 100755 --- a/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl +++ b/mpsoc/perl_gui/lib/perl/topology_verilog_gen.pl @@ -1191,7 +1191,9 @@ sub add_routing_instance_v{ #################################### my $str=" //do not modify this line ===${Vname}=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : $Vname + /* verilator lint_on WIDTH */ ${Vname}_ni_routing #( .RAw(RAw), .EAw(EAw), @@ -1226,7 +1228,9 @@ sub add_routing_instance_v{ #################################### $str=" //do not modify this line ===${Vname}=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : ${Vname} + /* verilator lint_on WIDTH */ ${Vname}_look_ahead_routing #( .RAw(RAw), .EAw(EAw), @@ -1262,7 +1266,9 @@ sub add_routing_instance_v{ #################################### $str=" //do not modify this line ===${Vname}=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == \"$name\" && ROUTE_NAME== \"$rname\" ) begin : ${Vname} + /* verilator lint_on WIDTH */ ${Vname}_conv_routing_comb #( .RAw(RAw), .EAw(EAw), @@ -1312,7 +1318,9 @@ sub add_noc_instance_v{ "; my $str=" //do not modify this line ===${name}=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == \"$name\" ) begin : T$name + /* verilator lint_on WIDTH */ ${name}_connection connection ( $ports ); @@ -1333,7 +1341,9 @@ sub add_noc_instance_v{ $str=" //do not modify this line ===${name}=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == \"$name\" ) begin : T$name + /* verilator lint_on WIDTH */ ${name}_noc_genvar the_noc ( .reset(reset), .clk(clk), @@ -1362,4 +1372,4 @@ sub add_noc_instance_v{ add_info($info,"$file has been modified. The ${name}_noc has been added to the file\n ",'blue'); } } -1 \ No newline at end of file +1 diff --git a/mpsoc/perl_gui/lib/perl/widget3.pl b/mpsoc/perl_gui/lib/perl/widget3.pl index fcfbb68..daa322f 100755 --- a/mpsoc/perl_gui/lib/perl/widget3.pl +++ b/mpsoc/perl_gui/lib/perl/widget3.pl @@ -9,6 +9,7 @@ use Consts; require "common.pl"; use IO::CaptureOutput qw(capture qxx qxy); +use File::Temp qw/tempfile/; #use ColorButton; use HexSpin3; #use Tk::Animation; @@ -1744,56 +1745,34 @@ sub file_edit_tree { ########## # run external commands ########## -sub run_cmd_in_back_ground -{ - my $command = shift; - #print "\t$command\n"; - ### Start running the Background Job: - my $proc = Proc::Background->new($command); - my $PID = $proc->pid; - my $start_time = $proc->start_time; - my $alive = $proc->alive; - ### While $alive is NOT '0', then keep checking till it is... - # *When $alive is '0', it has finished executing. - while($alive ne 0) - { - $alive = $proc->alive; - # This while loop will cause Gtk3 to continue processing events, if - # there are events pending... *which there are... +sub run_cmd_in_back_ground { + my ($command, $stdout_file, $stderr_file) = @_; + chomp $command; #remove newline + my $cmd =(defined $stdout_file) ? "$command 1>$stdout_file 2>$stderr_file" : "$command"; + my $proc = Proc::Background->new($cmd); + while ($proc->alive) { while (Gtk3::events_pending) { Gtk3::main_iteration; } Gtk3::Gdk::flush; usleep(1000); } - my $end_time = $proc->end_time; - # print "*Command Completed at $end_time, with PID = $PID\n\n"; - # Since the while loop has exited, the BG job has finished running: - # so close the pop-up window... - # $popup_window->hide; - # Get the RETCODE from the Background Job using the 'wait' method - my $retcode = $proc->wait; - $retcode /= 256; - #print "\t*RETCODE == $retcode\n\n"; - Gtk3::Gdk::flush; - ### Check if the RETCODE returned with an Error: - if ($retcode ne 0) { - print "Error: The Background Job ($command) returned with an Error...!\n"; - return 1; - } else { - #print "Success: The Background Job Completed Successfully...!\n"; - return 0; - } + my $ret = $proc->wait / 256; + return $ret; } sub run_cmd_in_back_ground_get_stdout { my $cmd=shift; my $exit; - my ($stdout, $stderr); - STDOUT->flush(); - STDERR->flush(); - capture { $exit=run_cmd_in_back_ground($cmd) } \$stdout, \$stderr; + # Create temp files in /dev/shm (RAM) + my ($stderr_fh, $stderr_file) = tempfile(DIR => "/dev/shm", UNLINK => 1); + my ($stdout_fh, $stdout_file) = tempfile(DIR => "/dev/shm", UNLINK => 1); + close $stderr_fh; + close $stdout_fh; + $exit=run_cmd_in_back_ground($cmd, $stdout_file, $stderr_file) ; + my $stderr = do { local (@ARGV, $/) = ($stderr_file); <> }; + my $stdout = do { local (@ARGV, $/) = ($stdout_file); <> }; return ($stdout,$exit,$stderr); } @@ -1894,4 +1873,4 @@ sub get_pressed_key{ my $key = Gtk3::Gdk::keyval_name( $event->keyval ); return $key; } -1; \ No newline at end of file +1; diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index a42602f..49baaad 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -965,11 +965,8 @@ module destp_generator #( ); end else begin :custom custom_topology_destp_decoder #( - .ROUTE_TYPE(ROUTE_TYPE), - .DSTPw(DSTPw), .P(P), - .SW_LOC(SW_LOC), - .SELF_LOOP_EN(SELF_LOOP_EN) + .SW_LOC(SW_LOC) ) destp_generator ( .dest_port_in_encoded(dest_port_encoded), .dest_port_out(dest_port_out) @@ -992,16 +989,14 @@ endmodule * custom_topology_destp_decoder * ***************/ module custom_topology_destp_decoder #( - parameter ROUTE_TYPE="DETERMINISTIC", - parameter DSTPw=4, parameter P=5, - parameter SW_LOC=0, - parameter SELF_LOOP_EN=0 + parameter SW_LOC=0 )( dest_port_in_encoded, dest_port_out ); + import pronoc_pkg::*; localparam P_1 = (SELF_LOOP_EN )? P : P-1, MAXW =2**DSTPw; diff --git a/mpsoc/rtl/src_topology/common/custom_conv_routing.v b/mpsoc/rtl/src_topology/common/custom_conv_routing.v index 330acb2..961ada2 100644 --- a/mpsoc/rtl/src_topology/common/custom_conv_routing.v +++ b/mpsoc/rtl/src_topology/common/custom_conv_routing.v @@ -23,7 +23,9 @@ module custom_conv_routing #( generate //do not modify this line ===Tcustom1Rcustom=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == "custom1" && ROUTE_NAME== "custom" ) begin : Tcustom1Rcustom + /* verilator lint_on WIDTH */ Tcustom1Rcustom_conv_routing_comb #( .RAw(RAw), .EAw(EAw), diff --git a/mpsoc/rtl/src_topology/common/custom_lkh_routing.v b/mpsoc/rtl/src_topology/common/custom_lkh_routing.v index 34ac188..a18c5d2 100644 --- a/mpsoc/rtl/src_topology/common/custom_lkh_routing.v +++ b/mpsoc/rtl/src_topology/common/custom_lkh_routing.v @@ -25,7 +25,9 @@ module custom_lkh_routing #( generate //do not modify this line ===Tcustom1Rcustom=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == "custom1" && ROUTE_NAME== "custom" ) begin : Tcustom1Rcustom + /* verilator lint_on WIDTH */ Tcustom1Rcustom_look_ahead_routing #( .RAw(RAw), .EAw(EAw), diff --git a/mpsoc/rtl/src_topology/common/custom_ni_routing.v b/mpsoc/rtl/src_topology/common/custom_ni_routing.v index 069c2ce..3b7ad6a 100644 --- a/mpsoc/rtl/src_topology/common/custom_ni_routing.v +++ b/mpsoc/rtl/src_topology/common/custom_ni_routing.v @@ -16,16 +16,18 @@ module custom_ni_routing #( output [DSTPw-1 :0] destport; generate //do not modify this line ===Tcustom1Rcustom=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == "custom1" && ROUTE_NAME== "custom" ) begin : Tcustom1Rcustom - Tcustom1Rcustom_conventional_routing #( + /* verilator lint_on WIDTH */ + Tcustom1Rcustom_ni_routing #( .RAw(RAw), .EAw(EAw), .DSTPw(DSTPw) - ) the_conventional_routing ( + ) the_ni_routing ( .dest_e_addr(dest_e_addr), .src_e_addr(src_e_addr), .destport(destport) ); end endgenerate -endmodule \ No newline at end of file +endmodule diff --git a/mpsoc/rtl/src_topology/common/custom_noc_top.sv b/mpsoc/rtl/src_topology/common/custom_noc_top.sv index bd314dd..53c02a6 100644 --- a/mpsoc/rtl/src_topology/common/custom_noc_top.sv +++ b/mpsoc/rtl/src_topology/common/custom_noc_top.sv @@ -20,7 +20,9 @@ module custom_noc_top generate //do not modify this line ===custom1=== + /* verilator lint_off WIDTH */ if(TOPOLOGY == "custom1" ) begin : Tcustom1 + /* verilator lint_on WIDTH */ custom1_noc_genvar the_noc ( .reset(reset), .clk(clk), diff --git a/mpsoc/script/noc_yml_gen/gen_mesh_yaml.pl b/mpsoc/script/noc_yml_gen/gen_mesh_yaml.pl new file mode 100644 index 0000000..490d111 --- /dev/null +++ b/mpsoc/script/noc_yml_gen/gen_mesh_yaml.pl @@ -0,0 +1,95 @@ +#!/usr/bin/perl +use strict; +use warnings; +use YAML::PP; +use YAML::PP::Common qw/ PRESERVE_ORDER PRESERVE_FLOW_STYLE YAML_FLOW_SEQUENCE_STYLE YAML_FLOW_MAPPING_STYLE /; + +my $yp = YAML::PP->new( + preserve => PRESERVE_ORDER, # preserve mapping order when dumping +); + +# Usage: +# ./gen_mesh_yaml.pl +my ($xdim, $ydim, $eps_per_node) = @ARGV; +die "Usage: $0 \n" + unless defined $xdim && defined $ydim && defined $eps_per_node; + +my $num_nodes = $xdim * $ydim; + +############################################################ +# Helpers: create preserved sequence/map objects +############################################################ +sub oseq { + my ($arr_ref) = @_; + # create a preserved sequence object from arrayref + return $yp->preserved_sequence([ @$arr_ref ]); +} + +sub omap { + my ($hashref) = @_; + # create a preserved mapping object and populate keys in insertion order + my $pm = $yp->preserved_mapping({}); + # copy keys in insertion order from provided hashref + # NOTE: the passed-in hashref may be a normal hash; we iterate in numeric order where appropriate + foreach my $k (keys %$hashref) { + $pm->{$k} = $hashref->{$k}; + } + return $pm; +} + +############################################################ +# Generate nodes (id + endpoints) as preserved sequence of preserved maps +############################################################ + +my @node_items; +my $ep_id = 0; + +for my $id (0 .. $num_nodes - 1) { + my @eps = map { $ep_id++ } 1 .. $eps_per_node; + + # create preserved mapping for this node, and preserved sequence for endpoints + my $node_map = $yp->preserved_mapping({}); + $node_map->{id} = $id; + $node_map->{endpoints} = $yp->preserved_sequence(\@eps); + + push @node_items, $node_map; +} + +my $nodes_seq = $yp->preserved_sequence(\@node_items); + +############################################################ +# Generate mesh connections (preserved sequence of preserved maps) +############################################################ + +my @conn_items; + +for my $y (0 .. $ydim - 1) { + for my $x (0 .. $xdim - 1) { + my $id = $y * $xdim + $x; + my @dest; + + push @dest, $id - 1 if $x > 0; # left + push @dest, $id + 1 if $x < $xdim - 1; # right + push @dest, $id - $xdim if $y > 0; # up + push @dest, $id + $xdim if $y < $ydim - 1; # down + + my $conn_map = $yp->preserved_mapping({}); + $conn_map->{source} = $id; + $conn_map->{dest} = $yp->preserved_sequence(\@dest); + + push @conn_items, $conn_map; + } +} + +my $conns_seq = $yp->preserved_sequence(\@conn_items); + +############################################################ +# Top-level preserved mapping (ordered) +############################################################ + +my $top = $yp->preserved_mapping({}); +$top->{nodes} = $nodes_seq; +$top->{connections} = $conns_seq; + +print $yp->dump($top); + diff --git a/mpsoc/script/noc_yml_gen/mesh_4x4.yml b/mpsoc/script/noc_yml_gen/mesh_4x4.yml new file mode 100644 index 0000000..7c5c0ae --- /dev/null +++ b/mpsoc/script/noc_yml_gen/mesh_4x4.yml @@ -0,0 +1,131 @@ +--- +nodes: +- id: 0 + endpoints: + - 0 +- id: 1 + endpoints: + - 1 +- id: 2 + endpoints: + - 2 +- id: 3 + endpoints: + - 3 +- id: 4 + endpoints: + - 4 +- id: 5 + endpoints: + - 5 +- id: 6 + endpoints: + - 6 +- id: 7 + endpoints: + - 7 +- id: 8 + endpoints: + - 8 +- id: 9 + endpoints: + - 9 +- id: 10 + endpoints: + - 10 +- id: 11 + endpoints: + - 11 +- id: 12 + endpoints: + - 12 +- id: 13 + endpoints: + - 13 +- id: 14 + endpoints: + - 14 +- id: 15 + endpoints: + - 15 +connections: +- source: 0 + dest: + - 1 + - 4 +- source: 1 + dest: + - 0 + - 2 + - 5 +- source: 2 + dest: + - 1 + - 3 + - 6 +- source: 3 + dest: + - 2 + - 7 +- source: 4 + dest: + - 5 + - 0 + - 8 +- source: 5 + dest: + - 4 + - 6 + - 1 + - 9 +- source: 6 + dest: + - 5 + - 7 + - 2 + - 10 +- source: 7 + dest: + - 6 + - 3 + - 11 +- source: 8 + dest: + - 9 + - 4 + - 12 +- source: 9 + dest: + - 8 + - 10 + - 5 + - 13 +- source: 10 + dest: + - 9 + - 11 + - 6 + - 14 +- source: 11 + dest: + - 10 + - 7 + - 15 +- source: 12 + dest: + - 13 + - 8 +- source: 13 + dest: + - 12 + - 14 + - 9 +- source: 14 + dest: + - 13 + - 15 + - 10 +- source: 15 + dest: + - 14 + - 11 From c4ecd914746c1ee4473504103cee4e64be5cbb9e Mon Sep 17 00:00:00 2001 From: Davy Million Date: Sun, 30 Nov 2025 00:49:42 +0100 Subject: [PATCH 101/107] Support for "Multi-mesh" (3.5D) NoC Topologies with Depth-First Routing Algorithm (#8) --- .gitignore | 3 +- mpsoc/perl_gui/lib/perl/mpsoc_gen.pl | 15 +- mpsoc/rtl/src_multi_mesh/mesh_cluster.sv | 645 ++++++++++ mpsoc/rtl/src_multi_mesh/multi_mesh.flist | 5 + mpsoc/rtl/src_multi_mesh/piton_wrapper.sv | 627 +++++++++ mpsoc/rtl/src_noc/debug.sv | 4 - mpsoc/rtl/src_noc/flit_buffer.sv | 8 +- mpsoc/rtl/src_noc/header_flit.sv | 3 + mpsoc/rtl/src_noc/inout_ports.sv | 2 + mpsoc/rtl/src_noc/input_ports.sv | 28 +- mpsoc/rtl/src_noc/noc_top.sv | 2 - mpsoc/rtl/src_noc/output_ports.sv | 10 +- mpsoc/rtl/src_noc/pronoc_pkg.sv | 25 +- mpsoc/rtl/src_noc/router_two_stage.sv | 10 +- mpsoc/rtl/src_noc/routing.sv | 2 - mpsoc/rtl/src_noc/topology_localparam.v | 11 +- .../src_openpiton/piton_tail_hdr_detect.sv | 68 + mpsoc/rtl/src_openpiton/piton_wrapper.sv | 61 - mpsoc/script/multimesh/deprecated/Readme | 18 + .../deprecated/channel_size_extractor.py | 41 + .../script/multimesh/deprecated/multi_mesh.pl | 101 ++ .../multimesh/deprecated/yaml_noc_gen.pl | 1141 +++++++++++++++++ mpsoc/script/multimesh/pronoc_dp_gen.py | 862 +++++++++++++ mpsoc/script/multimesh/run_test.sh | 81 ++ mpsoc/script/multimesh/src/file_list.f | 6 + mpsoc/script/multimesh/src/model.tcl | 33 + mpsoc/script/multimesh/src/sim_param.sv | 34 + .../script/phy_noc_gen/OpenPiton_nocs_gen.sh | 134 +- mpsoc/script/phy_noc_gen/phy_noc.pl | 70 +- 29 files changed, 3916 insertions(+), 134 deletions(-) create mode 100644 mpsoc/rtl/src_multi_mesh/mesh_cluster.sv create mode 100644 mpsoc/rtl/src_multi_mesh/multi_mesh.flist create mode 100644 mpsoc/rtl/src_multi_mesh/piton_wrapper.sv create mode 100644 mpsoc/rtl/src_openpiton/piton_tail_hdr_detect.sv create mode 100644 mpsoc/script/multimesh/deprecated/Readme create mode 100755 mpsoc/script/multimesh/deprecated/channel_size_extractor.py create mode 100644 mpsoc/script/multimesh/deprecated/multi_mesh.pl create mode 100644 mpsoc/script/multimesh/deprecated/yaml_noc_gen.pl create mode 100755 mpsoc/script/multimesh/pronoc_dp_gen.py create mode 100755 mpsoc/script/multimesh/run_test.sh create mode 100644 mpsoc/script/multimesh/src/file_list.f create mode 100644 mpsoc/script/multimesh/src/model.tcl create mode 100644 mpsoc/script/multimesh/src/sim_param.sv mode change 100644 => 100755 mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh diff --git a/.gitignore b/.gitignore index 90d2654..e24c077 100644 --- a/.gitignore +++ b/.gitignore @@ -46,7 +46,7 @@ mpsoc/src_c/plot/plot mpsoc/perl_gui/lib/Paths mpsoc/src_c/**/*.o -mpsoc/remove_cycle/__pycache__ +**/__pycache__/* mpsoc_work/ mpsoc/rtl/src_openpiton/nocs @@ -54,3 +54,4 @@ mpsoc/rtl/src_ambachi/nocs mpsoc/Integration_test/**/work mpsoc/Integration_test/**/result_logs/* +mpsoc/rtl/src_multi_mesh/build diff --git a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl index abdf40b..0d8fd1c 100755 --- a/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl +++ b/mpsoc/perl_gui/lib/perl/mpsoc_gen.pl @@ -449,19 +449,30 @@ sub defualt_tilles_setting { sub noc_topology_setting_gui { my ($mpsoc,$table,$txview,$row,$show_noc,$noc_id)=@_; my $noc_param="noc_param$noc_id"; + my $noc_type="noc_type$noc_id"; my $coltmp=0; # topology my $label='Topology'; my $param='TOPOLOGY'; my $default='"MESH"'; - my $content='"MESH","FMESH","MESH_3D","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM"'; + my $content='"MESH","FMESH","MESH_3D","TORUS","RING","LINE","FATTREE","TREE","STAR","CUSTOM","MULTI_MESH"'; my $type='Combo-box'; my $info="Specifies the NoC topology. Options include $content"; $noc_param_comment{$param}="$info"; ($row,$coltmp)=add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_param,1); my $topology=$mpsoc->object_get_attribute($noc_param,'TOPOLOGY'); - if($topology ne '"CUSTOM"' ){ + if ($topology eq '"MULTI_MESH"') { + # Multi-Mesh requires YAML configuration file selection + $label= "Select yaml file"; + $param= 'YAML_FILE'; + $info= "Select the YAML file containing the Multi-Mesh configuration settings"; + $type= 'FILE_path'; + $default = undef; + my $dir = "$ENV{PITON_ROOT}/configs"; + $content = "yaml:$dir"; + ($row,$coltmp)= add_param_widget ($mpsoc,$label,$param, $default,$type,$content,$info, $table,$row,undef,$show_noc,$noc_type,1); + } elsif ($topology ne '"CUSTOM"') { #topology T1 parameter $label= ($topology eq '"FATTREE"' || $topology eq '"TREE"')? 'K' : diff --git a/mpsoc/rtl/src_multi_mesh/mesh_cluster.sv b/mpsoc/rtl/src_multi_mesh/mesh_cluster.sv new file mode 100644 index 0000000..e916691 --- /dev/null +++ b/mpsoc/rtl/src_multi_mesh/mesh_cluster.sv @@ -0,0 +1,645 @@ +`include "pronoc_def.v" +/********************************************************************** +** File: mesh_cluster.sv +** +** Copyright (C) 2014-2017 Alireza Monemi +** +** This file is part of ProNoC +** +** ProNoC ( stands for Prototype Network-on-chip) is free software: +** you can redistribute it and/or modify it under the terms of the GNU +** Lesser General Public License as published by the Free Software Foundation, +** either version 2 of the License, or (at your option) any later version. +** +** ProNoC 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 Lesser General +** Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with ProNoC. If not, see . +** +** +** +** Description: +** A `mesh_cluster` refers to a group of interconnected routers arranged in a **3D Mesh topology** +** within a larger **Multi-Mesh NoC** for chiplets. In this architecture, each chiplet functions +** as an independent cluster of nodes, featuring its own local mesh-based communication network. +** +** Each router in the `mesh_cluster` drives two I/O channels: +** 1. **Endpoint Channel** – Connects to processing elements (PEs) or memory endpoints. +** 2. **Vertical Link Channel** – Facilitates inter-cluster communication. +** +** If an endpoint or vertical link is not present in the target Multi-Mesh topology, +** the corresponding input is tied to **ground**, enabling synthesis optimizations +** that effectively remove unused logic. +** +***************************************/ + + +module mesh_cluster + import pronoc_pkg::*; +#( + parameter + CLUSTER_ID = 0, + RID_INIT = 0, + // The initial value of Router IDs (RIDs) in this mesh cluster. + // This parameter is used to generate unique RIDs for each router in the cluster. + // It ensures that RIDs are distinct across multiple meshes when used in a multi-mesh configuration. + CLUSTER_NX = 2, + //Total number of nodes in the X dimension (horizontal axis) of the mesh cluster. + CLUSTER_NY = 2, + //Total number of nodes in the Y dimension (vertical axis) of the mesh cluster. + CLUSTER_NZ = 2, + //Total number of nodes in the Z dimension (depth axis) of the mesh cluster. + CLUSTER_NE = 8, + // Total number of endpoints (processing elements) + + localparam + CLUSTER_NR = CLUSTER_NX * CLUSTER_NY * CLUSTER_NZ, + // Total number of routers in cluster + CLUSTER_NVP = + // Total number of vertical ports per router used for inter-cluster + // communication i.e. the down ports of the routers on the first + // layer and the up ports of the routers in the last layer + (CLUSTER_NX * CLUSTER_NY) * 2, + CLUSTER_MAX_P = 7 +)( + input logic clk, + input logic reset, + input logic [CLUSTER_IDw-1:0] cluster_id, + // Endpoints ports + input smartflit_chanel_t endpoint_chan_in [CLUSTER_NE-1:0], + output smartflit_chanel_t endpoint_chan_out[CLUSTER_NE-1:0], + // Inter-Cluster interconnect ports + input smartflit_chanel_t inter_cluster_chan_in [CLUSTER_NVP-1:0], + output smartflit_chanel_t inter_cluster_chan_out[CLUSTER_NVP-1:0], + // Events + output router_event_t router_event[CLUSTER_NR-1:0][CLUSTER_MAX_P-1:0] +); + // Indididual routers interconnect ports + smartflit_chanel_t router_chan_in [CLUSTER_NZ-1:0][CLUSTER_NY-1:0][CLUSTER_NX-1:0][CLUSTER_MAX_P-1:0]; + smartflit_chanel_t router_chan_out[CLUSTER_NZ-1:0][CLUSTER_NY-1:0][CLUSTER_NX-1:0][CLUSTER_MAX_P-1:0]; + + // Unused Input channels are connected to ground + smartflit_chanel_t is_grounded; + assign is_grounded = {SMARTFLIT_CHANEL_w{1'b0}}; + + multimesh_router_addr_t current_r_addr[CLUSTER_NR-1:0]; + router_config_t router_config_in[CLUSTER_NR-1:0]; + + genvar x, y, z; + generate + for (z = 0; z < CLUSTER_NZ; z = z + 1) begin: Z_ + for (y = 0; y < CLUSTER_NY; y = y + 1) begin: Y_ + for (x = 0; x < CLUSTER_NX; x = x + 1) begin: X_ + localparam + V_DOWN_ID = (y * CLUSTER_NX) + x, + V_UP_ID = (y * CLUSTER_NX) + x + (CLUSTER_NX * CLUSTER_NY), + RID = z * (CLUSTER_NX * CLUSTER_NY) + (y * CLUSTER_NX) + x, + EID = RID, + // NOTE: as an optimization, we could disable the Up/Down + // ICR also when no VL reaches the router + UP_ICR_EN = (z == 0), + DOWN_ICR_EN = (z == (CLUSTER_NZ-1)), + // NOTE: as an optimization, we could disable it if there + // is no endpoint connected + LOCAL_ICR_EN = 1, + // NOTE: as an optimization, we could only enable the ICR + // of the 2D ports when an endpoint is connected + NORTH_ICR_EN = 1, + SOUTH_ICR_EN = 1, + WEST_ICR_EN = 1, + EAST_ICR_EN = 1; + + assign current_r_addr[RID] = '{x:x, y:y, z:z, c:cluster_id}; + + depth_first_router #( + .ROUTER_ID(RID+RID_INIT), + .P(CLUSTER_MAX_P), + // NOTE: ICR must be enable for: + // (*) The port Up (or Down) when a VL leaves or (reaches) + // the port and the Router Z dimension is 0 or Max_Z ; + // (*) The local port, if an endpoint is connected to it ; + // (*) Any 2D port (N/S/W/E) where an endpoint is connected + // to it ; + .UP_ICR_EN(UP_ICR_EN), + .DOWN_ICR_EN(DOWN_ICR_EN), + .LOCAL_ICR_EN(LOCAL_ICR_EN), + .NORTH_ICR_EN(NORTH_ICR_EN), + .SOUTH_ICR_EN(SOUTH_ICR_EN), + .WEST_ICR_EN(WEST_ICR_EN), + .EAST_ICR_EN(EAST_ICR_EN) +`ifndef DYNAMIC_CLUSTER_INIT + ,.CLUSTER_ID(CLUSTER_ID), + .CLUSTER_RID(RID) +`endif + ) the_router( + .clk(clk), + .reset(reset), +`ifdef DYNAMIC_CLUSTER_INIT + // NOTE: The dynamic ICRT has not been integrated for now + .program_port(), +`endif + .router_config_in(router_config_in[RID]), + .chan_in(router_chan_in [z][y][x]), + .chan_out(router_chan_out[z][y][x]), + .router_event(router_event[RID]) + ); + assign router_config_in[RID].router_addr = current_r_addr[RID]; + assign router_config_in[RID].endp_addrs = current_r_addr[RID]; + assign router_config_in[RID].router_id = RID+RID_INIT; + assign router_config_in[RID].endp_ids = RID+RID_INIT; + // **Mesh Interconnect Logic** +`ifndef PITON_EXTRA_MEMS + assign router_chan_in[z][y][x][EAST] = (x < CLUSTER_NX-1) ? + router_chan_out[z][y][x+1][WEST] : is_grounded; + assign router_chan_in[z][y][x][NORTH] = (y > 0) ? + router_chan_out[z][y-1][x][SOUTH] : is_grounded; + // ProNoC is used standalone, without OpenPiton + `ifndef PITON_PRONOC + assign router_chan_in[z][y][x][WEST] = (x > 0) ? + router_chan_out[z][y][x-1][EAST] : is_grounded; + `else // PITON_PRONOC + if (CLUSTER_ID == 0) begin + // Leave the western connection (x=0) unconnected + if (x > 0) begin + assign router_chan_in[z][y][x][WEST] = + router_chan_out[z][y][x-1][EAST]; + end + end else begin + assign router_chan_in[z][y][x][WEST] = (x > 0) ? + router_chan_out[z][y][x-1][EAST] : is_grounded; + end + `endif // PITON_PRONOC + assign router_chan_in[z][y][x][SOUTH] = (y < CLUSTER_NY-1) ? + router_chan_out[z][y+1][x][NORTH] : is_grounded; +`else // PITON_EXTRA_MEMS + // Only for Chiplet 0 (Interposer) + if (CLUSTER_ID == 0) begin + // Compared to the code below, this connects the outputs + // (coming in) of the endpoints on the edges of the mesh, + // to the router's incoming traffic + assign router_chan_in[z][y][x][EAST] = (x < CLUSTER_NX-1) ? + router_chan_out[z][y][x+1][WEST] : + endpoint_chan_in[CLUSTER_NX*CLUSTER_NY+CLUSTER_NX*2+CLUSTER_NY+y]; + assign router_chan_in[z][y][x][NORTH] = (y > 0) ? + router_chan_out[z][y-1][x][SOUTH] : + endpoint_chan_in[CLUSTER_NX*CLUSTER_NY+x]; + assign router_chan_in[z][y][x][WEST] = (x > 0) ? + router_chan_out[z][y][x-1][EAST] : + endpoint_chan_in[CLUSTER_NX*CLUSTER_NY+CLUSTER_NX*2+y]; + assign router_chan_in[z][y][x][SOUTH] = (y < CLUSTER_NY-1) ? + router_chan_out[z][y+1][x][NORTH] : + endpoint_chan_in[CLUSTER_NX*CLUSTER_NY+CLUSTER_NX+x]; + // Other chiplets + end else begin + assign router_chan_in[z][y][x][EAST] = (x < CLUSTER_NX-1) ? + router_chan_out[z][y][x+1][WEST] : is_grounded; + assign router_chan_in[z][y][x][NORTH] = (y > 0) ? + router_chan_out[z][y-1][x][SOUTH] : is_grounded; + assign router_chan_in[z][y][x][WEST] = (x > 0) ? + router_chan_out[z][y][x-1][EAST] : is_grounded; + assign router_chan_in[z][y][x][SOUTH] = (y < CLUSTER_NY-1) ? + router_chan_out[z][y+1][x][NORTH] : is_grounded; + end +`endif // PITON_EXTRA_MEMS + assign router_chan_in[z][y][x][UP] = (z < CLUSTER_NZ-1) ? + router_chan_out[z+1][y][x][DOWN] : inter_cluster_chan_in[V_UP_ID]; + assign router_chan_in[z][y][x][DOWN] = (z > 0) ? + router_chan_out[z-1][y][x][UP] : inter_cluster_chan_in[V_DOWN_ID]; + //endpoint connections + assign router_chan_in[z][y][x][LOCAL] = endpoint_chan_in[EID]; + assign endpoint_chan_out[EID] = router_chan_out[z][y][x][LOCAL]; + //inter_cluster connections + if (z==0) begin + assign inter_cluster_chan_out[V_UP_ID] = router_chan_out[z][y][x][UP]; + end + if (z==CLUSTER_NZ-1) begin + assign inter_cluster_chan_out[V_DOWN_ID] = router_chan_out[z][y][x][DOWN]; + end + end //X + end //Y + end //Z + endgenerate +`ifndef PITON_EXTRA_MEMS + `ifdef PITON_PRONOC + generate + if (CLUSTER_ID == 0) begin + // Tile 0-0 W <-> Chipset connections + assign router_chan_in[0][0][0][WEST] = + endpoint_chan_in[CLUSTER_NX*CLUSTER_NY*CLUSTER_NZ]; + assign endpoint_chan_out[CLUSTER_NX*CLUSTER_NY*CLUSTER_NZ] = + router_chan_out[0][0][0][WEST]; + end + endgenerate + `endif // PITON_PRONOC +`else // PITON_EXTRA_MEMS + genvar ex, ey; + generate + if (CLUSTER_ID == 0) begin + // Connect the routers output connections on the edges of the mesh + // (north and south) to the corresponding endpoints (MCs) + for (ex = 0; ex < CLUSTER_NX; ex = ex + 1) begin: EX_ + assign endpoint_chan_out[CLUSTER_NX*CLUSTER_NY+ex] = + router_chan_out[0][0][ex][NORTH]; + assign endpoint_chan_out[CLUSTER_NX*CLUSTER_NY+CLUSTER_NX+ex] = + router_chan_out[0][CLUSTER_NY-1][ex][SOUTH]; + end + + // Connect the routers output connections on the edges of the mesh + // (west and east) to the corresponding endpoints (MCs) + for (ey = 0; ey < CLUSTER_NY; ey = ey + 1) begin: EY_ + // NOTE: Chipset is now connected to endpoint + // CLUSTER_NX * CLUSTER_NY + CLUSTER_NX * 2 + // NOTE: Must be kept in sync with CHIP_SET_ID in chip.sv.pyv + assign endpoint_chan_out[CLUSTER_NX*CLUSTER_NY+CLUSTER_NX*2+ey] = + router_chan_out[0][ey][0][WEST]; + assign endpoint_chan_out[CLUSTER_NX*CLUSTER_NY+CLUSTER_NX*2+CLUSTER_NY+ey] = + router_chan_out[0][ey][CLUSTER_NX-1][EAST]; + end + end + endgenerate +`endif // PITON_EXTRA_MEMS +endmodule + + +module mesh_cluster_route_xyz + import pronoc_pkg::*; +( + input multimesh_router_addr_t current_router_addr_i, + input multimesh_router_addr_t destination_router_addr_i, + output logic [DSTPw-1:0] router_port_out +); + + // State type + typedef enum logic [2:0] { + MASS = 3'b001, + LESS = 3'b010, + EQUAL = 3'b100 + } state_t; + + state_t Dx, Dy, Dz; + assign Dx = (destination_router_addr_i.x > current_router_addr_i.x) ? MASS : + (destination_router_addr_i.x == current_router_addr_i.x) ? EQUAL : + LESS; + assign Dy = (destination_router_addr_i.y > current_router_addr_i.y) ? MASS : + (destination_router_addr_i.y == current_router_addr_i.y) ? EQUAL : + LESS; + assign Dz = (destination_router_addr_i.z > current_router_addr_i.z) ? MASS : + (destination_router_addr_i.z == current_router_addr_i.z) ? EQUAL : + LESS; + + always_comb begin + router_port_out = 0; + if (Dx == MASS) router_port_out = EAST; + else if (Dx == LESS) router_port_out = WEST; + else if (Dy == MASS) router_port_out = SOUTH; + else if (Dy == LESS) router_port_out = NORTH; + else if (Dz == MASS) router_port_out = UP; + else if (Dz == LESS) router_port_out = DOWN; + else router_port_out = LOCAL; + end +endmodule + + +module multi_mesh_ovc_sel + import pronoc_pkg::*; +#( + // Input port number. Zero is LOCAL + parameter SW_LOC = 0 +)( + input multimesh_router_addr_t current_router_addr_i, + input multimesh_router_addr_t global_dst_i, + input logic up_dir_sel_i, + input logic [DSTPw-1:0] destport_out_i, + input logic [V-1:0] vc_num_i, + output logic [V-1:0] ovc_sel_o +); + + logic [V-1:0] pre_ovc_sel; + + typedef enum logic [1:0] { + VDIR_UP = 2'b01, + VDIR_DOWN = 2'b10, + VDIR_EQUAL = 2'b00 + } vdir_t; + + vdir_t vdir; + assign vdir = + (global_dst_i.c == current_router_addr_i.c) ? VDIR_EQUAL : + (up_dir_sel_i) ? VDIR_UP : VDIR_DOWN; + + logic dest_reached; + assign dest_reached = global_dst_i.c == current_router_addr_i.c && + global_dst_i.x == current_router_addr_i.x && + global_dst_i.y == current_router_addr_i.y && + global_dst_i.z == current_router_addr_i.z; + + always_comb begin + // NOTE: The memory controllers on the interposer will inject packets + // in the NoC using the N/S/W/E ports of the routers (localized on the + // edges of the 2D-mesh). The packets are injected by default on Z- + // and stay on this VC until taking an ascending VL or arriving to + // destination. Conversely, the packets emitted on the (Z-) local port + // on the interposer, will switch and stay on Z+. + + // Packets injected on local port + if (SW_LOC == LOCAL) begin + pre_ovc_sel = (vdir == VDIR_UP) ? Z_PLUS_VC : + (vdir == VDIR_DOWN) ? Z_MIN_VC : + Z_PLUS_VC; + end + // Z- to Z+ transition when going up + else if (destport_out_i == UP && vc_num_i == Z_MIN_VC) begin + pre_ovc_sel = Z_PLUS_VC; + end + else begin + // Stay on the same VC + pre_ovc_sel = vc_num_i; + end + end + + // If arrived, forward the packet to the local port (Z+) + assign ovc_sel_o = (dest_reached) ? Z_PLUS_VC : pre_ovc_sel; +endmodule + + +module multi_mesh_ovc_list_per_ivc + import pronoc_pkg::*; +#( + parameter IVC_NUM = 0, // Input port VC number + parameter P = 7 // Router IO number +)( + input logic [Cw-1:0] class_in, + input logic [P-1:0] destport_one_hot, + input ctrl_chanel_t ctrl_in[P-1:0], + input logic [V-1:0] ovc_sel, + output logic [V-1:0] ovcs_out +); + localparam Pw = $clog2(P); + localparam [V-1:0] ALL_VCS = {V{1'b1}}; + + logic [V-1:0] candidate_ovcs_message_class; + logic [V-1:0] ovc_out_general; + logic [V-1:0] ovc_presence; + logic [V-1:0] ovc_list; + logic [V-1:0] ovc_list_reverse; + + // Destination port decimal + logic [Pw-1:0] destp; + + ovc_list ovcList( + .class_in(class_in), + .ovcs_out(candidate_ovcs_message_class) + ); + + always_comb begin + destp = '0; + for (int i = 0; i < P; i++) begin + if (destport_one_hot[i]) + destp = i[Pw-1:0]; + end + end + + assign ovc_out_general = ovc_sel; + assign ovc_presence = (HETERO_VC > 0) ? ctrl_in[destp].hetero_ovc_presence : ALL_VCS; + assign ovc_list = ovc_out_general & candidate_ovcs_message_class & ovc_presence; + assign ovc_list_reverse = ~ovc_out_general & candidate_ovcs_message_class & ovc_presence; + // If the listed VCs are not present in the connected router port, we swap + // the listed VCs (for example, if the connected port has only one VC (Z-), + // and ovc_out_general is Z+). + assign ovcs_out = (ovc_list == {V{1'b0}}) ? ovc_list_reverse : ovc_list; +endmodule + + +module icr_modifier + import pronoc_pkg::*; +#( + parameter logic ICR_EN = 1 +`ifndef DYNAMIC_CLUSTER_INIT + , parameter CLUSTER_ID = 0, + parameter CLUSTER_RID = 0 +`endif +)( +`ifdef DYNAMIC_CLUSTER_INIT + input cluster_hid_entry_t address_table[DYN_ICRT_MAX_ENTRY], + input multimesh_router_addr_t local_cluster_endp_addr_down_dir, + input logic [CLUSTER_IDw-1:0] current_cluster_id, +`endif + input smartflit_chanel_t chan_in, + input multimesh_router_addr_t current_r_addr, + output smartflit_chanel_t chan_out +); + + hdr_flit_t hdr_flit_i; + // Global / Local / ICRT Destination fields + multimesh_router_addr_t global_dst, local_dst, local_dst_icr; + // Local destination port, computed to reach the local destination + logic [DSTPw-1:0] ldestport_o; + // Final destination port, accounts for ascending / descending vertically + // and FBITS + logic [DSTPw-1:0] fdestport_o; + // Take the FBITS into account (encoded with ProNoC's port) + logic [DSTPw-1:0] fbits_encoded; + // Depth-First Multi-mesh routing fields + logic local_routing_en; + logic next_chip_vdir; + logic curr_next_chip_vdir; + logic up_dir_sel; + + header_flit_info #( + .DATA_w(0) + ) extractor( + .flit(chan_in.flit_chanel.flit), + .hdr_flit(hdr_flit_i), + .data_o(/* unused */) + ); + + // Unpacket all the fields from the destination address + assign {local_routing_en, + curr_next_chip_vdir, + fbits_encoded, + local_dst, + global_dst} = hdr_flit_i.dest_e_addr[DAw-1:0]; + + // Next vertical direction is either the one from the Inter-Chiplet Routing + // Table, or the previously computed one (local routing) + assign next_chip_vdir = (ICR_EN && !local_routing_en) ? + up_dir_sel : curr_next_chip_vdir; + +`ifdef MULTI_MESH_ASSERTIONS + // synthesis translate_off + assert property (@(posedge chan_in.flit_chanel.flit.hdr_flag) + local_routing_en == 1'b0 |-> ICR_EN == 1) + else + $fatal("A flit was freshly injected in the NoC on a non-ICR port"); + // synthesis translate_on +`endif // MULTI_MESH_ASSERTIONS + + generate + if (ICR_EN) begin + global_id_to_local_cluster_endp #( +`ifndef DYNAMIC_CLUSTER_INIT + .CLUSTER_ID(CLUSTER_ID), + .RID(CLUSTER_RID) +`endif + ) global_to_local( +`ifdef DYNAMIC_CLUSTER_INIT + .address_table(address_table), + .local_cluster_endp_addr_down_dir(local_cluster_endp_addr_down_dir), + .current_cluster_id(current_cluster_id), +`endif + .dest_address(global_dst), + .local_cluster_endp_addr(local_dst_icr), + .up_dir_sel(up_dir_sel) + ); + + // Local routing decision + mesh_cluster_route_xyz dor( + .current_router_addr_i(current_r_addr), + .destination_router_addr_i((local_routing_en) ? + local_dst : local_dst_icr), + .router_port_out(ldestport_o) + ); + end else begin + // Retrieve previously computed local destination + assign local_dst_icr = local_dst; + + // Local routing decision + mesh_cluster_route_xyz dor( + .current_router_addr_i(current_r_addr), + .destination_router_addr_i(local_dst_icr), + .router_port_out(ldestport_o) + ); + end + endgenerate + + always_comb begin + chan_out = chan_in; + // Base value for the final destination port + fdestport_o = '0; + // Header flit + if (chan_in.flit_chanel.flit.hdr_flag == 1'b1) begin + // Override the endpoint destination address of the header + // with the new local routing data + if (ICR_EN && !local_routing_en) + chan_out.flit_chanel.flit[E_DST_MSB:E_DST_LSB] = { + 1'b1, // enable local routing + next_chip_vdir, + fbits_encoded, + local_dst_icr, + global_dst + }; + + // By default, the next hop is the computed DOR decision + fdestport_o = ldestport_o; + + // If arrived to a boundary router which is not the global + // destination, route vertically + if (ldestport_o == LOCAL && local_dst_icr.c != global_dst.c) begin + fdestport_o = (next_chip_vdir) ? UP : DOWN; + // Set to 0 the local_routing field + chan_out.flit_chanel.flit[E_DST_MSB:E_DST_MSB] = 1'b0; + end + + // When arrived to destination, route to the FBITS if present, + // otherwise route to the local port + chan_out.flit_chanel.flit[DST_P_MSB:DST_P_LSB] = + (fdestport_o == LOCAL && fbits_encoded != LOCAL) ? + fbits_encoded : fdestport_o; + end + end +endmodule + + +module depth_first_router + import pronoc_pkg::*; +#( + parameter logic LOCAL_ICR_EN = 1, + parameter logic UP_ICR_EN = 1, + parameter logic DOWN_ICR_EN = 1, + parameter logic NORTH_ICR_EN = 1, + parameter logic SOUTH_ICR_EN = 1, + parameter logic WEST_ICR_EN = 1, + parameter logic EAST_ICR_EN = 1, + + parameter ROUTER_ID = 0, +`ifndef DYNAMIC_CLUSTER_INIT + parameter CLUSTER_ID = 0, + parameter CLUSTER_RID = 0, +`endif + parameter P = 7 +)( + input logic clk, + input logic reset, +`ifdef DYNAMIC_CLUSTER_INIT + input program_port_t program_port, +`endif + input router_config_t router_config_in, + input smartflit_chanel_t chan_in [P-1:0], + output smartflit_chanel_t chan_out[P-1:0], + output router_event_t router_event[P-1:0] +); + + localparam [P-1:0] ICR_PORT_EN = + (LOCAL_ICR_EN << LOCAL) + + (UP_ICR_EN << UP) + + (DOWN_ICR_EN << DOWN) + + (SOUTH_ICR_EN << SOUTH) + + (NORTH_ICR_EN << NORTH) + + (WEST_ICR_EN << WEST) + + (EAST_ICR_EN << EAST); + + smartflit_chanel_t chan_in_wire[P-1:0]; + + // Instanciate the regular ProNoC router + router_top #( + .ROUTER_ID(ROUTER_ID), + .P(P) + ) the_router ( + .router_config_in(router_config_in), + .chan_in(chan_in_wire), + .chan_out(chan_out), + .router_event(router_event), + .clk(clk), + .reset(reset) + ); + +`ifdef DYNAMIC_CLUSTER_INIT + cluster_hid_entry_t address_table[DYN_ICRT_MAX_ENTRY]; + multimesh_router_addr_t local_cluster_endp_addr_down_dir; + logic [CLUSTER_IDw-1:0] current_cluster_id; + + dynamic_hids_per_router dynamic_hids( + .local_cluster_endp_addr_down_dir(local_cluster_endp_addr_down_dir), + .address_table(address_table), + .current_cluster_id(current_cluster_id), + .program_port(program_port), + .reset(reset), + .clk(clk) + ); +`endif + + genvar i; + generate + for(i = 0; i < P; i++) begin : P_ + icr_modifier #( +`ifndef DYNAMIC_CLUSTER_INIT + .CLUSTER_ID(CLUSTER_ID), + .CLUSTER_RID(CLUSTER_RID), +`endif + .ICR_EN(ICR_PORT_EN[i]) + ) icr( +`ifdef DYNAMIC_CLUSTER_INIT + .address_table(address_table), + .local_cluster_endp_addr_down_dir(local_cluster_endp_addr_down_dir), + .current_cluster_id(current_cluster_id), +`endif + .current_r_addr(router_config_in.router_addr), + .chan_in(chan_in[i]), + .chan_out(chan_in_wire[i]) + ); + end//P + endgenerate +endmodule diff --git a/mpsoc/rtl/src_multi_mesh/multi_mesh.flist b/mpsoc/rtl/src_multi_mesh/multi_mesh.flist new file mode 100644 index 0000000..629903a --- /dev/null +++ b/mpsoc/rtl/src_multi_mesh/multi_mesh.flist @@ -0,0 +1,5 @@ ++incdir+./build +./mesh_cluster.sv +./build/multi_mesh_icr.sv +./build/multi_mesh_routing.sv +./build/multi_mesh.sv diff --git a/mpsoc/rtl/src_multi_mesh/piton_wrapper.sv b/mpsoc/rtl/src_multi_mesh/piton_wrapper.sv new file mode 100644 index 0000000..6a3b98f --- /dev/null +++ b/mpsoc/rtl/src_multi_mesh/piton_wrapper.sv @@ -0,0 +1,627 @@ +/************************************************************** + * File : piton_wrapper.sv + * Description : Contains the necessary modules for adapting + * Depth-First ProNoC with OpenPiton's Endpoints + * + * Authors : Davy Million, Alireza Monemi + * Date : 2025 + **************************************************************/ +`include "define.tmp.h" +`include "jtag.vh" +`include "pronoc_def.v" + + +// The following modules allows the conversion of an OpenPiton Flit into a +// ProNoC Depth-First Flit, and the other way around. +// +// (A) Valid Flit, Additionnal Flags and Backpressure +// The OpenPiton valid flit signal is plugged directly into the ProNoC flit +// write signal. +// +// To keep track of the number of flits in a packet, OpenPiton has a dedicated +// LENGTH attributes in the header flit. This is not the case of ProNoC, which +// rely on explicit signals, which are asserted for the head and tail flits. +// The module piton_tail_hdr_detect (shared with the FMesh OpenPiton wrapper) +// is used to convert these two ways of managing the number of flits. +// +// As Depth-First relies on two VCs, and OpenPiton's endpoints only support a +// single source of credits, we modified the routing algorithm to only use VC0 +// (Z-) for packet injection, and the other one (Z+) for packet reception, +// leveraging the fact that the algorithm supports passing from Z- to Z+ (but +// not the other way around). Switching between these two VCs is necessary to +// support all "Multi-Mesh" routing paths, because some X-Y/Z turns are +// disabled for both VC to garantee deadlock-freeness. Hence, the OpenPiton +// backpressure signal (yummy) is connected directly to the Z- ProNoC credit +// signal. +// +// (B) Data Payload +// The conversion is almost straightforward: the ProNoC data payload is the +// same as the OpenPiton data payload, except when the OpenPiton flit present +// the 1st 64-bit Header word (which is the case for any 1st Header Flit of an +// OpenPiton packet). +// +// For this corner case, the conversion consists of the following: +// OpenPiton +// Fpay-1 ... 64-bit 30-bit 0 +// |____________|___________________________|______________________________| +// | | | | +// | ... | CHIPID, XPOS, YPOS, FBITS | LENGTH, TYPE, MSHR, OPTIONS1 | +// |____________|___________________________|______________________________| +// | | |<-------PRESERVED_DATw------->| +// | Word 2...n | (OpenPiton Header Flit Word 1) | +// |_____ _____|_________________________________________ _______________| +// || || +// || _________________________|| +// || MSB_BE + 1 + || +// FPAYw-1 || PRESERVED_DATw || pronoc_pkg::MSB_BE+1 0 +// |_____VV_____|_______________VV_____________|___________________________| +// | | | Depth-First ProNoC Header | +// | ... | LENGTH, TYPE, MSHR, OPTIONS1 | DST Addr | SRC Addr | +// |____________|______________________________|___________________________| +// |<-----------|------DATA_w----------------->| | +// | ProNoC Header Flit Payload | +// |_______________________________________________________________________| +// ProNoC +// +// Where: +// (*) Fpay, the size of the OpenPiton data flit +// --> Fpay NoC1: {64, 128, 256, 512} +// --> Fpay NoC2/3: {64, 128, 256, 512, 576, 704} +// +// (*) FPAYw, the size of the ProNoC data payload +// +// The size of FPAYw depends on the size of the Depth-First (DP) DST/SRC +// address fields. These fields are computed based on the original CHIPID, +// XPOS, YPOS and FBITS values. The width of the DP DST/SRC addresses can vary +// and depend primarily on the values of the CLUSTER_IDw, CLUSTER_Xw and +// CLUSTER_Yw parameters, which themselves depends on the max X/Y dimensions +// among all chips and the number of chips in the system. +// FPAYw will be larger than Fpay if: +// ==> size(DP DST Addr) + size(DP SRC Addr) > size(CHIPID, XPOS, YPOS, FBITS) +// which is likely the case for a large system. +// +// (C) Control Channels +// ProNoC has dedicated control channels to support different buffer depths +// (credit_init_val) and number of VCs between routers (hetero_ovc_presence). +// The credit_init_val signal is initialized with the same value as the buffer +// size in the OpenPiton endpoints. The hetero_ovc_presence is used to check if +// the Z+ VC exists on the interposer chip, and use Z- as a fallback VC for +// packet reception otherwise. + + +module piton_to_pronoc_multimesh_endp_src_addr_converter + import pronoc_pkg::*; +( + input logic [`NOC_CHIPID_WIDTH-1:0] piton_chipid_i, + input logic [`NOC_X_WIDTH-1:0] piton_coreid_x_i, + input logic [`NOC_Y_WIDTH-1:0] piton_coreid_y_i, + output logic [EAw-1:0] pronoc_endp_src_addr_o +); + // Encode endpoint source address + assign pronoc_endp_src_addr_o = { + piton_chipid_i[CLUSTER_IDw-1:0], + {CLUSTER_Zw{1'b0}}, + piton_coreid_y_i[CLUSTER_Yw-1:0], + piton_coreid_x_i[CLUSTER_Xw-1:0] + }; +endmodule + + +module piton_to_pronoc_multimesh_endp_dst_addr_converter + import pronoc_pkg::*; +( + input logic [`NOC_CHIPID_WIDTH-1:0] piton_chipid_i, + input logic [`NOC_X_WIDTH-1:0] piton_coreid_x_i, + input logic [`NOC_Y_WIDTH-1:0] piton_coreid_y_i, + input logic [`MSG_DST_FBITS_WIDTH-1:0] piton_fbits_i, + output logic [DAw-1:0] pronoc_endp_dst_addr_o +); + // Destination FBITS + logic [DSTPw-1:0] pronoc_dest_fbits; + // Global destination address + logic [RAw-1:0] global_dst_i; + + assign pronoc_dest_fbits = + (piton_fbits_i == `NOC_FBITS_NORTH) ? NORTH : + (piton_fbits_i == `NOC_FBITS_WEST ) ? WEST : + (piton_fbits_i == `NOC_FBITS_SOUTH) ? SOUTH : + (piton_fbits_i == `NOC_FBITS_EAST ) ? EAST : LOCAL; + + assign global_dst_i = {piton_chipid_i[CLUSTER_IDw-1:0], + {CLUSTER_Zw{1'b0}}, + piton_coreid_y_i[CLUSTER_Yw-1:0], + piton_coreid_x_i[CLUSTER_Xw-1:0]}; + + // Endpoint destination address encoding + assign pronoc_endp_dst_addr_o = { + 1'b0, // local_routing_en + 1'b0, // next_chip_vdir + pronoc_dest_fbits, + {RAw{1'b0}}, // local_dst + global_dst_i + }; +endmodule + + +module pronoc_to_piton_multimesh_endp_addr_converter + import pronoc_pkg::*; +( + input logic [DAw-1:0] piton_endp_dst_addr_i, + output logic [`NOC_CHIPID_WIDTH-1:0] piton_chipid_o, + output logic [`NOC_X_WIDTH-1:0] piton_coreid_x_o, + output logic [`NOC_Y_WIDTH-1:0] piton_coreid_y_o, + output logic [`MSG_DST_FBITS_WIDTH-1:0] piton_fbits_o +); + // Starting Position of the CLUSTER_ID field + localparam CLUSTER_ID_IDX = CLUSTER_Xw + CLUSTER_Yw + CLUSTER_Zw; + + // Destination FBITS encoded as a ProNoC port + logic [DSTPw-1:0] piton_dest_fbits_enc; + + always_comb begin + piton_coreid_x_o = {`MSG_DST_X_WIDTH{1'b0}}; + piton_coreid_y_o = {`MSG_DST_Y_WIDTH{1'b0}}; + piton_chipid_o = {`NOC_CHIPID_WIDTH{1'b0}}; + piton_dest_fbits_enc = {DSTPw{1'b0}}; + + // Extract x/y from the global destination + {piton_coreid_y_o[CLUSTER_Yw-1:0], + piton_coreid_x_o[CLUSTER_Xw-1:0]} = + piton_endp_dst_addr_i[CLUSTER_Yw + CLUSTER_Xw-1:0]; + + piton_chipid_o = piton_endp_dst_addr_i[CLUSTER_ID_IDX +: CLUSTER_IDw]; + piton_dest_fbits_enc = piton_endp_dst_addr_i[2*RAw +: DSTPw]; + end + + // Decode FBITS into OpenPiton format + assign piton_fbits_o = + (piton_dest_fbits_enc == EAST ) ? `NOC_FBITS_EAST : + (piton_dest_fbits_enc == NORTH) ? `NOC_FBITS_NORTH : + (piton_dest_fbits_enc == WEST ) ? `NOC_FBITS_WEST : + (piton_dest_fbits_enc == SOUTH) ? `NOC_FBITS_SOUTH : + `NOC_FBITS_PROCESSOR; +endmodule + + +module piton_to_pronoc_multimesh_wrapper + import pronoc_pkg::*; +#( + parameter TILE_NUM = 0, + parameter FLATID_WIDTH = 8, + parameter Z_MINUS_VC_INJECTION = 1, + parameter CONNECTED_TO_ENDP = 1 +)( + input logic clk, + input logic reset, + // OpenPiton + input logic [`NOC_CHIPID_WIDTH-1:0] default_chipid, + input logic [`NOC_X_WIDTH-1:0] default_coreid_x, + input logic [`NOC_Y_WIDTH-1:0] default_coreid_y, + input logic [FLATID_WIDTH-1:0] flat_tileid, + input logic [Fpay-1:0] dataIn, + input logic validIn, + input logic yummyIn, + // ProNoC + input logic [RAw-1:0] current_r_addr_i, + input logic [V-1:0] ovc_presence_i, + output smartflit_chanel_t chan_out +); + // Size of the OpenPiton header fields remaining in the ProNoC header + localparam PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH); + + // NOTE: the OpenPiton NoC protocol contains some packet fields that are + // not necessary for routing with ProNoC because they are either related to + // the decoding of the packet, or to give necessary information to the + // destination endpoint, so the destination can create a response. Also, + // when the Piton NoC > 64-bit, the endpoint packs multiple 64-bit words + // together in a single flit. If the message is a cache coherence request, + // the header flit will contain the targeted address (and also details + // about the source endpoint if Piton NoC > 128-bit), see Flit (2, 3) of + // Table 1 in OpenPiton Microarchitecture Specification. + // All these "non-necessary for routing" fields will be placed in the + // ProNoC packet header, as additional payload data, so they can be + // retrieved once the packet is arrived to the destination endpoint. + // DATA_w is the size of the additionnal payload data. + localparam DATA_w = Fpay - 64 + PRESERVED_DATw; + + logic [`MSG_DST_CHIPID_WIDTH-1:0] piton_dest_chipid; + logic [`MSG_DST_X_WIDTH-1:0] piton_dest_x; + logic [`MSG_DST_Y_WIDTH-1:0] piton_dest_y; + logic [`MSG_DST_FBITS_WIDTH-1:0] piton_dest_fbits; + logic [`MSG_LENGTH_WIDTH-1:0] piton_length; + logic [`MSG_TYPE_WIDTH-1:0] piton_msg_type; + logic [`MSG_MSHRID_WIDTH-1:0] piton_mshrid; + logic [`MSG_OPTIONS_1_WIDTH-1:0] piton_option1; + + logic [EAw-1:0] pronoc_src_endp_addr; + logic [DAw-1:0] pronoc_dest_endp_addr; + logic [DATA_w-1:0] pronoc_hdr_data; + + logic piton_is_tail; + logic piton_is_head; + + logic [Fw-1:0] pronoc_hdr_flit; + logic [WEIGHTw-1:0] pronoc_win; + logic [V-1:0] pronoc_vc_num_in; + + piton_tail_hdr_detect #( + .FLIT_WIDTH(Fpay) + ) piton_hdr( + .clk(clk), + .reset(reset), + .length_in(dataIn[`MSG_LENGTH]), + .valid(validIn), + .ready(1'b1), + .is_tail(piton_is_tail), + .is_header(piton_is_head) + ); + + piton_to_pronoc_multimesh_endp_src_addr_converter src_conv( + .piton_chipid_i(default_chipid), + .piton_coreid_x_i(default_coreid_x), + .piton_coreid_y_i(default_coreid_y), + .pronoc_endp_src_addr_o(pronoc_src_endp_addr) + ); + + assign piton_dest_chipid = dataIn[`MSG_DST_CHIPID]; + assign piton_dest_x = dataIn[`MSG_DST_X]; + assign piton_dest_y = dataIn[`MSG_DST_Y]; + assign piton_dest_fbits = dataIn[`MSG_DST_FBITS]; + assign piton_length = dataIn[`MSG_LENGTH]; + assign piton_msg_type = dataIn[`MSG_TYPE]; + assign piton_mshrid = dataIn[`MSG_MSHRID]; + assign piton_option1 = dataIn[`MSG_OPTIONS_1]; + + piton_to_pronoc_multimesh_endp_dst_addr_converter dst_conv( + .piton_chipid_i(piton_dest_chipid), + .piton_coreid_x_i(piton_dest_x), + .piton_coreid_y_i(piton_dest_y), + .piton_fbits_i(piton_dest_fbits), + .pronoc_endp_dst_addr_o(pronoc_dest_endp_addr) + ); + + generate + if (Fpay == 64) begin: F64 + assign pronoc_hdr_data = {piton_length, piton_msg_type, piton_mshrid, + piton_option1}; + end else begin: FL + assign pronoc_hdr_data = {dataIn[Fpay-1:64], piton_length, + piton_msg_type, piton_mshrid, piton_option1}; + end + endgenerate + + always_comb begin + pronoc_win = {WEIGHTw{1'b0}}; + pronoc_win[0] = 1'b1; + end + + generate + if (Z_MINUS_VC_INJECTION) begin + // Injection of the packet on Z- + assign pronoc_vc_num_in = Z_MIN_VC; + end else begin + // Injection of the packet on Z+ + // This is used to reconstruct a packet to cross a vertical link, + // between two NoC domains with different channel widths + assign pronoc_vc_num_in = Z_PLUS_VC; + end + endgenerate + + header_flit_generator #( + .DATA_w(DATA_w) + ) pronoc_hdr_gen( + .flit_out(pronoc_hdr_flit), + .src_e_addr_in(pronoc_src_endp_addr), + .dest_e_addr_in(pronoc_dest_endp_addr), + // NOTE: we do not really care about the destport here as the router + // will override it anyway + .destport_in({DSTPw{1'b0}}), + .class_in(1'b0), + .weight_in(pronoc_win), + .vc_num_in(pronoc_vc_num_in), + .be_in(1'b0), + .data_in(pronoc_hdr_data) + ); + + // ProNoC Control Channels + assign chan_out.ctrl_chanel.endp_port = CONNECTED_TO_ENDP; + assign chan_out.ctrl_chanel.endp_addr = + (CONNECTED_TO_ENDP) ? pronoc_src_endp_addr : '0; + assign chan_out.ctrl_chanel.router_addr = + (CONNECTED_TO_ENDP) ? pronoc_src_endp_addr : current_r_addr_i; + // By default, our implementation of Depth-First uses Z+ to place a packet + // in the destination router's ports. If this VC is not available (on the + // interposer, Z- could be the only VC), use Z- in this case. + assign chan_out.ctrl_chanel.credit_init_val = + // Select Z+ if it exists, otherwise Z- + ovc_presence_i[Z_PLUS_VC_IDX] ? + Z_PLUS_VC[0] ? {{CRDTw{1'b0}}, pronoc_pkg::B} : + {pronoc_pkg::B, {CRDTw{1'b0}}} + : Z_MIN_VC[0] ? {{CRDTw{1'b0}}, pronoc_pkg::B} : + {pronoc_pkg::B, {CRDTw{1'b0}}}; + assign chan_out.ctrl_chanel.credit_release_en = '0; + assign chan_out.ctrl_chanel.hetero_ovc_presence = ovc_presence_i; + + // ProNoC Flit Channels + assign chan_out.flit_chanel.flit.hdr_flag = piton_is_head; + assign chan_out.flit_chanel.flit.tail_flag = piton_is_tail; + assign chan_out.flit_chanel.flit.vc = pronoc_vc_num_in; + assign chan_out.flit_chanel.flit_wr = validIn; + // "Z+" credit, an endpoint consumed the flit (arrived to its destination) + assign chan_out.flit_chanel.credit = ovc_presence_i[Z_PLUS_VC_IDX] ? + Z_PLUS_VC & {yummyIn, yummyIn} : Z_MIN_VC & {yummyIn, yummyIn}; + assign chan_out.flit_chanel.flit.payload = (piton_is_head) ? + pronoc_hdr_flit[FPAYw-1:0] : dataIn; + assign chan_out.smart_chanel = {SMART_CHANEL_w{1'b0}}; + assign chan_out.flit_chanel.congestion = {CONGw{1'b0}}; + +`ifndef ASIC_SYNTH +`ifndef DISABLE_ALL_MONITORS +`ifndef MINIMAL_MONITORING + // synthesis translate_off + always @ (posedge clk) begin + if (CONNECTED_TO_ENDP && validIn == 1'b1 && piton_is_head) begin + $display("%t Pi2Pr * Chip %d/Tile %d * NoC %d * payload length %d", + $time, default_chipid, TILE_NUM, NOC_ID[1:0], piton_length); + $display("%t *** src (c=%d,x=%d,y=%d) sends to dst (c=%d,x=%d,y=%d chan_out=%x)", + $time, default_chipid, default_coreid_x, default_coreid_y, piton_dest_chipid, + piton_dest_x, piton_dest_y, chan_out); + end + end + // synthesis translate_on +`endif // MINIMAL_MONITORING +`endif // DISABLE_ALL_MONITORS +`endif // ASIC_SYNTH +endmodule + + +module pronoc_to_piton_multimesh_wrapper + import pronoc_pkg::*; +#( + parameter TILE_NUM = 0, + parameter FLATID_WIDTH = 8, + parameter CONNECTED_TO_ENDP = 1 +)( + input logic clk, + input logic reset, + // OpenPiton + input logic [`NOC_CHIPID_WIDTH-1:0] default_chipid, + input logic [`NOC_X_WIDTH-1:0] default_coreid_x, + input logic [`NOC_Y_WIDTH-1:0] default_coreid_y, + input logic [FLATID_WIDTH-1:0] flat_tileid, + output logic [Fpay-1:0] dataOut, + output logic validOut, + output logic yummyOut, + output logic [RAw-1:0] current_r_addr_o, + // ProNoC + input smartflit_chanel_t chan_in, + output multimesh_router_addr_t received_packet_src_addr_o, + output logic [V-1:0] ovc_presence_o +); + // Size of the OpenPiton header fields remaining in the ProNoC header + localparam + PRESERVED_DATw = (`MSG_LENGTH_WIDTH + `MSG_TYPE_WIDTH + + `MSG_MSHRID_WIDTH + `MSG_OPTIONS_1_WIDTH); + // Size of the OpenPiton payload remaining in the ProNoC header flit + localparam DATA_w = Fpay - 64 + PRESERVED_DATw; + + hdr_flit_t pronoc_hdr_flit; + logic pronoc_is_hdr; + logic [DATA_w-1:0] pronoc_hdr_data; + + logic [Fpay-1:0] piton_hdr_flit; + // Source FBITS encoded as a ProNoC port + logic [DSTPw-1:0] piton_src_fbits_enc; + + logic [`MSG_DST_CHIPID_WIDTH-1:0] piton_dest_chipid; + logic [`MSG_DST_X_WIDTH-1:0] piton_dest_x; + logic [`MSG_DST_Y_WIDTH-1:0] piton_dest_y; + logic [`MSG_DST_FBITS_WIDTH-1:0] piton_dest_fbits; + logic [`MSG_LENGTH_WIDTH-1:0] piton_length; + logic [`MSG_TYPE_WIDTH-1:0] piton_msg_type; + logic [`MSG_MSHRID_WIDTH-1:0] piton_mshrid; + logic [`MSG_OPTIONS_1_WIDTH-1:0] piton_option1; + + // Extract ProNoC header flit data + header_flit_info #( + .DATA_w(DATA_w) + ) extract( + .flit(chan_in.flit_chanel.flit), + .hdr_flit(pronoc_hdr_flit), + .data_o(pronoc_hdr_data) + ); + + pronoc_to_piton_multimesh_endp_addr_converter addr_conv( + .piton_endp_dst_addr_i(pronoc_hdr_flit.dest_e_addr), + .piton_chipid_o(piton_dest_chipid), + .piton_coreid_x_o(piton_dest_x), + .piton_coreid_y_o(piton_dest_y), + .piton_fbits_o(piton_dest_fbits) + ); + + assign {piton_length, piton_msg_type, piton_mshrid, piton_option1} = + pronoc_hdr_data[PRESERVED_DATw-1:0]; + + assign piton_hdr_flit[`MSG_DST_CHIPID] = piton_dest_chipid; + assign piton_hdr_flit[`MSG_DST_X] = piton_dest_x; + assign piton_hdr_flit[`MSG_DST_Y] = piton_dest_y; + assign piton_hdr_flit[`MSG_DST_FBITS] = piton_dest_fbits; + assign piton_hdr_flit[`MSG_LENGTH ] = piton_length; + assign piton_hdr_flit[`MSG_TYPE ] = piton_msg_type; + assign piton_hdr_flit[`MSG_MSHRID ] = piton_mshrid; + assign piton_hdr_flit[`MSG_OPTIONS_1] = piton_option1; + + generate + if (Fpay > 64) begin: R_ + assign piton_hdr_flit[Fpay-1:64] = + pronoc_hdr_data[DATA_w-1:PRESERVED_DATw]; + end + endgenerate + + assign validOut = chan_in.flit_chanel.flit_wr; + // "Z-" credit, a flit was removed from the router's internal port + assign yummyOut = chan_in.flit_chanel.credit[Z_MIN_VC_IDX]; + assign pronoc_is_hdr = chan_in.flit_chanel.flit.hdr_flag; + assign dataOut = (pronoc_is_hdr)? piton_hdr_flit[Fpay-1:0] : + chan_in.flit_chanel.flit.payload; + + // Signals used by the pronoc_to_piton endpointer encoder + assign current_r_addr_o = chan_in.ctrl_chanel.router_addr; + assign {piton_src_fbits_enc, received_packet_src_addr_o} + = pronoc_hdr_flit.src_e_addr; + assign ovc_presence_o = chan_in.ctrl_chanel.hetero_ovc_presence; + +`ifndef ASIC_SYNTH +`ifndef DISABLE_ALL_MONITORS +`ifndef MINIMAL_MONITORING + // synthesis translate_off + always @ (posedge clk) begin + if (CONNECTED_TO_ENDP && validOut==1'b1 && pronoc_is_hdr) begin + $display("%t Pr2Pi * Chip %d/Tile %d * NoC %d * payload length %d", + $time, default_chipid, TILE_NUM, NOC_ID[1:0], piton_length); + $display("%t *** Received Packet Header (chan_out=%x) from src (c=%d,x=%d,y=%d)", + $time, dataOut, received_packet_src_addr_o.c, received_packet_src_addr_o.x, + received_packet_src_addr_o.y); + end + end + // synthesis translate_on +`endif // MINIMAL_MONITORING +`endif // DISABLE_ALL_MONITORS +`endif // ASIC_SYNTH +endmodule + + +module pronoc_noc + import pronoc_pkg::*; +#( + parameter CHIP_ID = 0, + // Inherited from the base wrapper.sv file, kept for consistency + parameter CHIP_SET_PORT = 3, + parameter FLATID_WIDTH = `JTAG_FLATID_WIDTH, + parameter CLUSTER_NX = 1, + parameter CLUSTER_NY = 1, + parameter CLUSTER_NZ = 1, + parameter CLUSTER_ID_OFFSET = 0, +`ifndef PITON_EXTRA_MEMS +`ifdef PITON_PRONOC + localparam NE = (CHIP_ID == 0) ? CLUSTER_NX * CLUSTER_NY * CLUSTER_NZ + 1 : + CLUSTER_NX * CLUSTER_NY * CLUSTER_NZ +`else // PITON_PRONOC + localparam NE = CLUSTER_NX * CLUSTER_NY * CLUSTER_NZ +`endif // PITON_PRONOC +`else // PITON_EXTRA_MEMS + // For OpenPiton, the total number of available endpoints is one endpoint + // per tile + an endpoint on each edge of the 2D-Mesh to connect an MC and + // the chipset (only for the north-western one) + localparam NE = (CHIP_ID == 0) ? CLUSTER_NX * CLUSTER_NY * CLUSTER_NZ + + CLUSTER_NX * 2 + CLUSTER_NY * 2 : + CLUSTER_NX * CLUSTER_NY * CLUSTER_NZ +`endif // PITON_EXTRA_MEMS +)( + input logic clk, + input logic reset, + input logic [Fpay*NE-1:0] dataIn_flatten, + input logic [NE-1:0] validIn, + input logic [NE-1:0] yummyIn, + output logic [Fpay*NE-1:0] dataOut_flatten, + output logic [NE-1:0] validOut, + output logic [NE-1:0] yummyOut, + input logic [`NOC_X_WIDTH*NE-1:0] default_coreid_x_flatten, + input logic [`NOC_Y_WIDTH*NE-1:0] default_coreid_y_flatten, + input logic [FLATID_WIDTH*NE-1:0] flat_tileid_flatten +`ifdef PITON_MULTICHIP + , + // NoC Vertical Links + input smartflit_chanel_t pronoc_inter_chip_in [CLUSTER_NX*CLUSTER_NY*2-1:0], + output smartflit_chanel_t pronoc_inter_chip_out[CLUSTER_NX*CLUSTER_NY*2-1:0] +`endif // PITON_MULTICHIP +); + + logic [Fpay-1:0] dataIn[NE-1:0]; + logic [Fpay-1:0] dataOut[NE-1:0]; + logic [`NOC_X_WIDTH-1:0] default_coreid_x[NE-1:0]; + logic [`NOC_Y_WIDTH-1:0] default_coreid_y[NE-1:0]; + logic [FLATID_WIDTH-1:0] flat_tileid[NE-1:0]; + + smartflit_chanel_t pronoc_chan_in [NE-1:0]; + smartflit_chanel_t pronoc_chan_out[NE-1:0]; + logic [RAw-1:0] current_r_addr[NE-1:0]; + logic [V-1:0] ovc_presence[NE-1:0]; + + genvar i; + generate + for (i = 0; i < NE; i++) begin: E_ + assign dataIn[i] = dataIn_flatten[(i+1)*Fpay-1:i*Fpay]; + assign dataOut_flatten[(i+1)*Fpay-1:i*Fpay] = dataOut[i]; + assign default_coreid_x[i] = default_coreid_x_flatten[(i+1)*`NOC_X_WIDTH-1:i*`NOC_X_WIDTH]; + assign default_coreid_y[i] = default_coreid_y_flatten[(i+1)*`NOC_Y_WIDTH-1:i*`NOC_Y_WIDTH]; + assign flat_tileid[i] = flat_tileid_flatten[(i+1)*FLATID_WIDTH-1:i*FLATID_WIDTH]; + + pronoc_to_piton_multimesh_wrapper + #( + .TILE_NUM(i), + .FLATID_WIDTH(FLATID_WIDTH), + .CONNECTED_TO_ENDP(1) + ) pr2pi( + .default_chipid(CHIP_ID[`NOC_CHIPID_WIDTH-1:0]), + .default_coreid_x(default_coreid_x[i]), + .default_coreid_y(default_coreid_y[i]), + .flat_tileid(flat_tileid[i]), + .reset(reset), + .clk(clk), + .dataOut(dataOut[i]), + .validOut(validOut[i]), + .yummyOut(yummyOut[i]), + .current_r_addr_o(current_r_addr[i]), + .chan_in(pronoc_chan_out[i]), + .received_packet_src_addr_o(/* unused */), + .ovc_presence_o(ovc_presence[i]) + ); + + piton_to_pronoc_multimesh_wrapper + #( + .TILE_NUM(i), + .FLATID_WIDTH(FLATID_WIDTH), + .CONNECTED_TO_ENDP(1) + ) pi2pr( + .default_chipid(CHIP_ID[`NOC_CHIPID_WIDTH-1:0]), + .default_coreid_x(default_coreid_x[i]), + .default_coreid_y(default_coreid_y[i]), + .flat_tileid(flat_tileid[i]), + .reset(reset), + .clk(clk), + .dataIn(dataIn[i]), + .validIn(validIn[i]), + .yummyIn(yummyIn[i]), + .current_r_addr_i(current_r_addr[i]), + .chan_out(pronoc_chan_in[i]), + .ovc_presence_i(ovc_presence[i]) + ); + end + endgenerate + + // Instanciate directly the mesh_cluster + mesh_cluster #( + .CLUSTER_ID(CHIP_ID), + .RID_INIT(CLUSTER_ID_OFFSET), + .CLUSTER_NX(CLUSTER_NX), + .CLUSTER_NY(CLUSTER_NY), + .CLUSTER_NZ(CLUSTER_NZ), + .CLUSTER_NE(NE) + ) local_noc( + .reset(reset), + .clk(clk), + .cluster_id(CHIP_ID[CLUSTER_IDw-1:0]), + .endpoint_chan_in(pronoc_chan_in), + .endpoint_chan_out(pronoc_chan_out), +`ifdef PITON_MULTICHIP + .inter_cluster_chan_in(pronoc_inter_chip_in), + .inter_cluster_chan_out(pronoc_inter_chip_out), +`else + .inter_cluster_chan_in('{default: '{default: '0}}), + .inter_cluster_chan_out(/* unused */), +`endif // PITON_MULTICHIP + .router_event(/* unused */) + ); +endmodule diff --git a/mpsoc/rtl/src_noc/debug.sv b/mpsoc/rtl/src_noc/debug.sv index 18f97c5..818a9f1 100644 --- a/mpsoc/rtl/src_noc/debug.sv +++ b/mpsoc/rtl/src_noc/debug.sv @@ -285,12 +285,10 @@ module endp_addr_encoder ( .code(code_out) ); end else if ( IS_MULTI_MESH) begin :mmesh - /* multimesh_address_encoder addr_encoder ( .rid_in(id_in), .addr_st_o(code_out) ); - */ end else begin :custom assign code_out =id_in; end @@ -326,12 +324,10 @@ module endp_addr_decoder ( .code(code_in) ); end else if ( IS_MULTI_MESH) begin - /* multimesh_address_decoder addr_coder ( .rid_out(id_out), .addr_st_i(code_in) ); - */ end else begin :custom assign id_out = code_in; end diff --git a/mpsoc/rtl/src_noc/flit_buffer.sv b/mpsoc/rtl/src_noc/flit_buffer.sv index e3abbd3..0d948f6 100755 --- a/mpsoc/rtl/src_noc/flit_buffer.sv +++ b/mpsoc/rtl/src_noc/flit_buffer.sv @@ -54,10 +54,10 @@ module flit_buffer #( BVw = log2(BV), PORT_Vw = (PORT_IVC==1)? 1 : log2(PORT_IVC), DEPTHw = log2(PORT_B+1), - RESTw = Fw -2-PORT_IVC , + RESTw = Fw - 2 - V, PTRw = ((2**PORT_Bw)==PORT_B)? PORT_Bw : BVw, // if B is power of 2 PTRw is Bw else is BVw ARRAYw = PTRw * PORT_IVC, - RAM_DATA_WIDTH = (IS_MULTI_FLIT)? Fw - PORT_IVC : Fw - PORT_IVC -2; + RAM_DATA_WIDTH = (IS_MULTI_FLIT)? Fw - V : Fw - V - 2; input [Fw-1 :0] din; // Data in input [PORT_IVC-1 :0] vc_num_wr;//write virtual chanel @@ -92,7 +92,7 @@ module flit_buffer #( reg [PORT_B-1 : 0] tail_fifo [PORT_IVC-1 : 0]; wire [1 : 0] flgs_in, flgs_out; - wire [PORT_IVC-1: 0] vc_in; + wire [V-1: 0] vc_in; wire [RESTw-1 :0 ] flit_rest_in,flit_rest_out; wire [PORT_IVC-1 : 0] sub_rd; wire [PORT_IVC-1 : 0] sub_restore; @@ -189,7 +189,7 @@ module flit_buffer #( vc_rd_addr = '0; wr_select_addr = '0; rd_select_addr = '0; - for (int k = 0; k < V; k++) begin + for (int k = 0; k < PORT_IVC; k++) begin //One-hot_mux vc_wr_addr |= (vc_num_wr[k]) ? wr_ptr[k] : '0; if (IS_UNICAST) vc_rd_addr |= (vc_num_rd[k]) ? rd_ptr[k] : '0; diff --git a/mpsoc/rtl/src_noc/header_flit.sv b/mpsoc/rtl/src_noc/header_flit.sv index 0119721..f237b3a 100644 --- a/mpsoc/rtl/src_noc/header_flit.sv +++ b/mpsoc/rtl/src_noc/header_flit.sv @@ -83,6 +83,9 @@ module header_flit_generator #( assign flit_out [FPAYw-1 : DATA_LSB] = {(FPAYw-DATA_LSB){1'b0}}; end end else begin :have_data + if (FPAYw > DATA_MSB+1) begin + assign flit_out [FPAYw-1 : DATA_MSB+1] = {(FPAYw-DATA_MSB-1){1'b0}}; + end assign flit_out [DATA_MSB : DATA_LSB] = data_in[DATA_MSB-DATA_LSB : 0]; // we have enough space for adding whole of the data end endgenerate diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index 8d2284f..a28c7c4 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -396,6 +396,8 @@ module output_vc_status #( always_comb begin cand_vc_ld_next = cand_vc; if(cand_wr_vc_en) cand_vc_ld_next = cand_vc_next; + // For Depth-First, only inject on VC0 (Z-) + if (IS_MULTI_MESH) cand_vc_ld_next = 2'd1; end endmodule diff --git a/mpsoc/rtl/src_noc/input_ports.sv b/mpsoc/rtl/src_noc/input_ports.sv index 49baaad..0c81d1e 100755 --- a/mpsoc/rtl/src_noc/input_ports.sv +++ b/mpsoc/rtl/src_noc/input_ports.sv @@ -388,16 +388,16 @@ module input_queue_per_port #( logic [1:0] ovc_sel_i; logic [1:0] ovc_sel_ivc [V-1 : 0]; if(IS_MULTI_MESH) begin : mmesh_ - /* multi_mesh_ovc_sel #( - .SW_LOC(SW_LOC), - .LOCAL_ADAPT(0) - )ovc_sel( - .local_dst_icr(hdr_flit_i.dest_e_addr[DAw-1 : DAw/2]),// hdr_flit_i.dest_e_addr = {local_dst_icr,global_dst} + .SW_LOC(SW_LOC) + ) ovc_sel( + .global_dst_i(hdr_flit_i.dest_e_addr[RAw-1:0]), .current_router_addr_i(router_info.router_addr), - .ovc_sel(ovc_sel_i) + .up_dir_sel_i(hdr_flit_i.dest_e_addr[DAw-2:DAw-2]), + .destport_out_i(hdr_flit_i.destport), + .vc_num_i(flit_in.vc), + .ovc_sel_o(ovc_sel_i) ); - */ end // "MULTI_MESH" always_comb begin @@ -419,6 +419,18 @@ module input_queue_per_port #( ivc_info[k].destport_one_hot[P-1 : 0] = destport_one_hot[k]; ivc_info[k].assigned_ovc_bin = assigned_onc_bin[k]; ivc_info[k].dest_e_addr = dest_e_addr_out[k]; +`ifdef MULTI_MESH_ASSERTIONS + // synthesis translate_off + if (IS_MULTI_MESH) begin + assert property (@(posedge clk) + ovc_is_assigned[k] |-> + k != Z_PLUS_VC_IDX || + assigned_ovc_one_hot[k] != Z_MIN_VC) + else + $fatal("Z- OVC assigned to a Z+ IVC"); + end + // synthesis translate_on +`endif // MULTI_MESH_ASSERTIONS end //for k for (int k=PORT_IVC; k PITON_DESTw) ? + Fpay + MSB_BE + 1 - PITON_DESTw : + (PCK_TYPE == "SINGLE_FLIT")? + Fpay + MSB_BE : + Fpay; +`else localparam FPAYw = (IS_SINGLE_FLIT)? Fpay + MSB_BE: Fpay; - +`endif + typedef struct packed { bit hdr_flag; bit tail_flag; @@ -302,7 +320,8 @@ package pronoc_pkg; function automatic logic [V-1 : 0] hetero_ovc_unary; input integer router_id; input integer router_port_num; //router port num - integer vc_num, i; + integer i; + logic [V-1:0] vc_num; begin vc_num = (HETERO_VC == 0) ? V : diff --git a/mpsoc/rtl/src_noc/router_two_stage.sv b/mpsoc/rtl/src_noc/router_two_stage.sv index d0daaaa..8aeb1fa 100644 --- a/mpsoc/rtl/src_noc/router_two_stage.sv +++ b/mpsoc/rtl/src_noc/router_two_stage.sv @@ -167,8 +167,6 @@ module router_two_stage #( return (i > SOUTH) ? i - SOUTH : LOCAL; end else if(IS_3D_TOPO) begin return (i > DOWN) ? i - DOWN : LOCAL; - end else if (IS_MULTI_MESH) begin - return LOCAL; end else return 0; //TODO complete it for fattree and bin tree endfunction @@ -217,9 +215,11 @@ module router_two_stage #( end end - if(IS_UNICAST & IS_LOOKAHEAD) begin : lk_route - // we are using lookahead routing. So, the destination port is already computed - // in the previous router and is available in the lookahead routing field of the flit. + if(IS_UNICAST & (IS_LOOKAHEAD | IS_MULTI_MESH)) begin : lk_dp_route + // we are using lookahead routing or depth-first (DP) routing. So, the destination + // port is already computed in the previous router (computed externally in the + // same router for DP) and is available in the lookahead routing field of the flit + // (destport field for DP). assign chan_in_tmp[i] = chan_in[i]; end else begin : conv_route local_route_computation #( diff --git a/mpsoc/rtl/src_noc/routing.sv b/mpsoc/rtl/src_noc/routing.sv index e8332d1..455ea2c 100755 --- a/mpsoc/rtl/src_noc/routing.sv +++ b/mpsoc/rtl/src_noc/routing.sv @@ -100,13 +100,11 @@ module conventional_routing #( .destport(destport) ); end else if (IS_MULTI_MESH) begin : multimesh - /* mesh_cluster_route_xyz the_conventional_routing ( .current_router_addr_i(current_r_addr), .destination_router_addr_i(dest_e_addr[EAw-1:0]), .router_port_out(destport) ); - */ end else begin :custom custom_conv_routing #( .TOPOLOGY(TOPOLOGY), diff --git a/mpsoc/rtl/src_noc/topology_localparam.v b/mpsoc/rtl/src_noc/topology_localparam.v index 6b03106..c6edc46 100644 --- a/mpsoc/rtl/src_noc/topology_localparam.v +++ b/mpsoc/rtl/src_noc/topology_localparam.v @@ -139,7 +139,7 @@ if (router_port_num == 0 || router_port_num > BACKWARD ) port_buffer_size = LB; end else if (IS_2D_TOPO) begin if (router_port_num == 0 || router_port_num > SOUTH ) port_buffer_size = LB; - end else if (IS_3D_TOPO) begin + end else if (IS_3D_TOPO && !IS_MULTI_MESH) begin if (router_port_num == 0 || router_port_num > DOWN) port_buffer_size = LB; end end @@ -248,10 +248,15 @@ NE_MULTI_MESH = T1, // total number of endpoints NR_MULTI_MESH = T1, // total number of routers RAw_MULTI_MESH = T2, - DAw_MULTI_MESH = 2*T2, // destination address width + // Endpoint (source) Address width + // global_src EAw_MULTI_MESH = T2, MAX_P_MULTI_MESH = 7, - DSTPw_MULTI_MESH = log2(MAX_P_MULTI_MESH); + DSTPw_MULTI_MESH = log2(MAX_P_MULTI_MESH), + // Destination Address width + // local_routing_en / next_chip_vdir / destfbits / local_dst / global_dst + DAw_MULTI_MESH = 2*T2+log2(MAX_P_MULTI_MESH)+2; + /************************* * regular_topo address struct **************************/ diff --git a/mpsoc/rtl/src_openpiton/piton_tail_hdr_detect.sv b/mpsoc/rtl/src_openpiton/piton_tail_hdr_detect.sv new file mode 100644 index 0000000..d0a38b5 --- /dev/null +++ b/mpsoc/rtl/src_openpiton/piton_tail_hdr_detect.sv @@ -0,0 +1,68 @@ +/************************************************************** + * File : piton_tail_hdr_detect.sv + * Description : Detect if an OpenPiton flit is a tail or a header + * + * Author : Alireza Monemi + * Date : 2025 + **************************************************************/ +`include "define.tmp.h" + +module piton_tail_hdr_detect #( + parameter FLIT_WIDTH=64 +)( + reset, + clk, + length_in, + valid, + ready, + is_tail, + is_header +); + input wire reset,clk; + input wire valid,ready; + input wire [`MSG_LENGTH_WIDTH-1 : 0] length_in; + output wire is_tail, is_header; + + localparam + CHANEL_WORLD_NUM = FLIT_WIDTH/64; + localparam [1:0] + HEADER = 1, + BODY = 2; + reg [1:0] flit_type,flit_type_next; + reg [`MSG_LENGTH_WIDTH-1 : 0] remain, remain_next; + + always_comb begin + remain_next = remain; + flit_type_next = flit_type; + if(valid & ready) begin + case(flit_type) + HEADER: begin + if (length_in >= CHANEL_WORLD_NUM ) begin + flit_type_next = BODY; + remain_next = length_in - CHANEL_WORLD_NUM; + end + end //HEADER + BODY: begin + if(remain < CHANEL_WORLD_NUM) begin + flit_type_next = HEADER; + end else if (remain >= CHANEL_WORLD_NUM ) begin + remain_next = remain - CHANEL_WORLD_NUM; + end + end //BODY + endcase + end + end//always + + always @ (posedge clk) begin + if (reset) begin + remain <= {`MSG_LENGTH_WIDTH{1'b0}}; + flit_type <=HEADER; + end else begin + remain <= remain_next; + flit_type <= flit_type_next; + end + end + + assign is_tail = (flit_type == HEADER)? (length_in < CHANEL_WORLD_NUM) : (remain < CHANEL_WORLD_NUM); + assign is_header = (flit_type == HEADER); +endmodule diff --git a/mpsoc/rtl/src_openpiton/piton_wrapper.sv b/mpsoc/rtl/src_openpiton/piton_wrapper.sv index fc321f7..70d5d5b 100644 --- a/mpsoc/rtl/src_openpiton/piton_wrapper.sv +++ b/mpsoc/rtl/src_openpiton/piton_wrapper.sv @@ -740,64 +740,3 @@ module pronoc_noc .router_event( ) ); endmodule - - -module piton_tail_hdr_detect #( - parameter FLIT_WIDTH=64 -)( - reset, - clk, - length_in, - valid, - ready, - is_tail, - is_header -); - input wire reset,clk; - input wire valid,ready; - input wire [`MSG_LENGTH_WIDTH-1 : 0] length_in; - output wire is_tail, is_header; - - localparam - CHANEL_WORLD_NUM = FLIT_WIDTH/64; - localparam [1:0] - HEADER = 1, - BODY = 2; - reg [1:0] flit_type,flit_type_next; - reg [`MSG_LENGTH_WIDTH-1 : 0] remain, remain_next; - - always_comb begin - remain_next = remain; - flit_type_next = flit_type; - if(valid & ready) begin - case(flit_type) - HEADER: begin - if (length_in >= CHANEL_WORLD_NUM ) begin - flit_type_next = BODY; - remain_next = length_in - CHANEL_WORLD_NUM; - end - end //HEADER - BODY: begin - if(remain < CHANEL_WORLD_NUM) begin - flit_type_next = HEADER; - end else if (remain >= CHANEL_WORLD_NUM ) begin - remain_next = remain - CHANEL_WORLD_NUM; - end - end //BODY - endcase - end - end//always - - always @ (posedge clk) begin - if (reset) begin - remain <= {`MSG_LENGTH_WIDTH{1'b0}}; - flit_type <=HEADER; - end else begin - remain <= remain_next; - flit_type <= flit_type_next; - end - end - - assign is_tail = (flit_type == HEADER)? (length_in < CHANEL_WORLD_NUM) : (remain < CHANEL_WORLD_NUM); - assign is_header = (flit_type == HEADER); -endmodule \ No newline at end of file diff --git a/mpsoc/script/multimesh/deprecated/Readme b/mpsoc/script/multimesh/deprecated/Readme new file mode 100644 index 0000000..804a9ec --- /dev/null +++ b/mpsoc/script/multimesh/deprecated/Readme @@ -0,0 +1,18 @@ +### **Generating Multi-Mesh Configuration** + +To generate a multi-mesh configuration, follow these steps: + +1. **Open a terminal.** +2. **Run the following command:** + + ```bash + bash [ProNoC_dir]/mpsoc/script/yaml_noc_gen/yaml_noc_gen.pl [ProNoC_dir]/mpsoc/noc_configs/[config_file_name].yml + ``` + + - Replace **`[ProNoC_dir]`** with the path to your **ProNoC** installation directory. + - Replace **`[config_file_name]`** with the **YAML configuration file** that defines your multi-mesh network settings. + + +This script will generate the required multi-mesh NoC configuration based on the settings defined in the YAML file. + + diff --git a/mpsoc/script/multimesh/deprecated/channel_size_extractor.py b/mpsoc/script/multimesh/deprecated/channel_size_extractor.py new file mode 100755 index 0000000..ee5650b --- /dev/null +++ b/mpsoc/script/multimesh/deprecated/channel_size_extractor.py @@ -0,0 +1,41 @@ +import argparse +import subprocess +import os + +from pyslang import ScriptSession + + +PRONOC_CHANNEL_WIDTH_NAME = "SMARTFLIT_CHANEL_w" + +def preprocess_pronoc_pkg(pyslang_opts): + result = subprocess.run(['python', os.path.join(os.environ["DV_ROOT"], + "tools/bin/", + 'pyslang_preprocess.py')] \ + + pyslang_opts, capture_output=True, text=True) + return result.stdout + +def evaluate_pronoc_channel_size(noc_pkg, noc_id): + session = ScriptSession() + # Seg-fault turnaround: add a final ";" right after package definition + session.eval(noc_pkg + ";") + look_for = f"pronoc_pkg_N{noc_id}::{PRONOC_CHANNEL_WIDTH_NAME}_N{noc_id}" + result = session.eval(f"{look_for}") + if str(result) == "": + raise Exception(f"Error: cannot retrieve {look_for}") + print(result, end='') + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=f"Retrieve the channel" + \ + f" size ({PRONOC_CHANNEL_WIDTH_NAME})"+ \ + " of a ProNoC SystemVerilog Package") + parser.add_argument('noc_id', type=int, help='Network-on-Chip ID') + parser.add_argument('pyslang_params', nargs=argparse.REMAINDER, + help='A series of parameters passed to pyslang for' + \ + ' pre-processing') + args = parser.parse_args() + + # Call Pyslang pre-processor on ProNoC NoC PKG + preprocessed_src = preprocess_pronoc_pkg(args.pyslang_params) + # Evaluate the ProNoC channel size of the PKG + evaluate_pronoc_channel_size(preprocessed_src, args.noc_id) + diff --git a/mpsoc/script/multimesh/deprecated/multi_mesh.pl b/mpsoc/script/multimesh/deprecated/multi_mesh.pl new file mode 100644 index 0000000..fba1424 --- /dev/null +++ b/mpsoc/script/multimesh/deprecated/multi_mesh.pl @@ -0,0 +1,101 @@ +#add home dir in perl 5.6 +use FindBin; +use lib $FindBin::Bin; +use constant::boolean; + +use strict; +use warnings; + +# Function to add an edge with separate parent and child nodes +sub add_edge_old { + my ($graph,$parent_cluster, $parent_node, $child_cluster, $child_node, $dir) = @_; + # Initialize clusters if not present + $graph->{$parent_cluster} //= { parents => [], children => [] }; + $graph->{$child_cluster} //= { parents => [], children => [] }; + # Add child connection to parent + push @{$graph->{$parent_cluster}{children}}, { cluster => $child_cluster, parent_node => $parent_node, child_node => $child_node, dir=>$dir}; + # Add parent connection to child + push @{$graph->{$child_cluster}{parents}}, { cluster => $parent_cluster, parent_node => $parent_node, child_node => $child_node, dir=>$dir}; +} + +# Function to add an edge with separate parent and child nodes +sub add_edge { + my ($graph,$src_cluster, $src_node, $dest_cluster, $dest_node, $dir) = @_; + # Initialize clusters if not present + $graph->{$src_cluster} //= { $dir => [] }; + # Add child connection to parent + push @{$graph->{$src_cluster}{$dir}}, { cluster => $dest_cluster, src_node => $src_node, dest_node => $dest_node}; +} + +sub get_clusters_in_dir { + my ($graph, $cluster,$dir) = @_; + my @childs = exists $graph->{$cluster} ? map { $_->{cluster} } @{$graph->{$cluster}{$dir}} : (); + return unify (@childs); +} + +sub dfs_assign_ids { + my ($graph, $global_id, $cluster, $visited, $current_id) = @_; + return $current_id if exists $visited->{$cluster}; # Skip if already visited + $visited->{$cluster} = 1; + $global_id->{$cluster} = $current_id++; # Assign and increment ID + foreach my $child (get_clusters_in_dir($graph, $cluster, 'up')) { + $current_id = dfs_assign_ids($graph, $global_id, $child, $visited, $current_id); + } + return $current_id; +} + +sub find_interpose{ + my $config = shift; + my @f= keys %{$config->{multi_mesh}}; + return $f[0]; +} + +# Function to start DFS traversal from a root cluster +sub assign_global_ids { + my ($graph, $global_id, $root_cluster) = @_; + my %visited; + dfs_assign_ids($graph, $global_id, $root_cluster, \%visited, 0); # Start ID from 0 +} + +# Function to get cluster IDs with DFS ordering +sub get_cluster_ids { + my ($config,$graph) = @_; + my %global_id; # Stores assigned IDs + my $I = find_interpose($config); # Find the root cluster + assign_global_ids($graph, \%global_id, $I); # Start DFS from root + return %global_id; +} + +sub unify { + my %seen; + return grep { !$seen{$_}++ } @_; +} + +sub get_all_connection_nodes_to_a_cluster { + my ($graph, $cluster_key, $direction, $target_cluster) = @_; + return unless exists $graph->{$cluster_key}{$direction}; # Ensure the path exists + my @src_nodes = map { $_->{src_node} } + grep { $_->{cluster} eq $target_cluster } + @{ $graph->{$cluster_key}{$direction} }; + return @src_nodes; # Return as an array +} + +sub get_clusters_up_to_leaf { + my ($tree, $cluster)=@_; + my %visited; + return get_clusters_up_to_leaf_unique($tree, $cluster, \%visited); +} + +sub get_clusters_up_to_leaf_unique { + my ($tree, $cluster, $visited) = @_; + return if exists $visited->{$cluster}; # Avoid duplicates + $visited->{$cluster} = 1; + return ($cluster) unless exists $tree->{$cluster}{'up'}; + my @leaves = ($cluster); + foreach my $child (@{$tree->{$cluster}{'up'}}) { + push @leaves, get_clusters_up_to_leaf_unique($tree, $child->{cluster}, $visited); + } + return @leaves; +} + +return 1; diff --git a/mpsoc/script/multimesh/deprecated/yaml_noc_gen.pl b/mpsoc/script/multimesh/deprecated/yaml_noc_gen.pl new file mode 100644 index 0000000..e3cb196 --- /dev/null +++ b/mpsoc/script/multimesh/deprecated/yaml_noc_gen.pl @@ -0,0 +1,1141 @@ +#add home dir in perl 5.6 +use FindBin; +use lib $FindBin::Bin; +use constant::boolean; + +use strict; +use warnings; +#use YAML::XS qw(LoadFile); +use Data::Dumper; +use List::MoreUtils qw(uniq); +use File::Basename; +use File::Copy; +use File::Path qw(make_path); +use List::Util qw(min max); +use YAML::PP; +use YAML::PP::Common; +my $yp = YAML::PP->new( preserve => YAML::PP::Common->PRESERVE_ORDER ); + +require "src/multi_mesh.pl"; + + +my $dirname = dirname(__FILE__); +my $noc_dir = "$dirname/../../rtl/src_noc"; +my $noc_param_object_file="$dirname/../../Integration_test/synthetic_sim/src/deafult_noc_param"; + +my $yaml_file = $ARGV[0]; +my $out_dir= "$dirname/../../rtl/src_multi_mesh/build"; + +if (!defined $yaml_file) { + print "Error: + usage: perl yaml_noc_gen.pl yamal_file target_dir\n"; + exit 1; +} + +my $config = $yp->load_file( $yaml_file ); +my %cluster_tree; # a Tree struct saving cluster connections in parent child format +my %cluster_ids; #keep cluster ids based on dfs + +#my $config = LoadFile($yaml_file); +my $topology = $config->{'topology'}; +my $buffer_depth=$config->{'buffer_depth'}; +my $flit_size=$config->{'flit_size'}; + + +# Create directory with -p equivalent +make_path($out_dir) or die "Failed to create directory '$out_dir': $!" unless(-d $out_dir); + +generate_pronoc_multimesh() if(exists $config->{'multi_mesh'}); + + +sub connect_nodes{ + my ($self,$node1,$port1,$node2,$port2)=@_; + $self->{'PCONNECT'}{$node1}{"Port[$port1]"}="$node2,$port2"; + # $self->{$node2}{'PCONNECT'}{$port2}="$node1,$port1"; +} + + +sub connect_nodes_local{ + my ($self,$mesh1,$x1,$y1,$z1,$port1,$mesh2,$x2,$y2,$z2,$port2,$dim_x,$dim_y,$dim_z)=@_; + my $id1=$x1 + $y1*$dim_x+ $z1*$dim_x*$dim_y; + my $node1=$mesh1."_".$id1; + my $id2=$x2+ $y2*$dim_x+ $z2*$dim_x*$dim_y; + my $node2=$mesh2."_".$id2; + connect_nodes($self,$node1,$port1,$node2,$port2); +} + +sub update_multimesh_config { + my ($mesh,$config,$vcs)=@_; + my $dim_x = $config->{'multi_mesh'}{$mesh}{'dim_x'}; + my $dim_y = $config->{'multi_mesh'}{$mesh}{'dim_y'}; + my $dim_z = $config->{'multi_mesh'}{$mesh}{'dim_z'}; + my $vc = $config->{'multi_mesh'}{$mesh}{'n_virtual_channels'}; + my $first_router_id = $config->{'router_counter'}//0; + my $cluster_counter = $config->{'cluster_counter'}//0; + $config->{'max_x'} = max($config->{'max_x'} // 0, $dim_x); + $config->{'max_y'} = max($config->{'max_y'} // 0, $dim_y); + $config->{'max_z'} = max($config->{'max_z'} // 0, $dim_z); + $config->{'cluster_counter'} = $cluster_counter+1; + $vcs->{$mesh}=$vc; + my $nodes_num = $dim_x * $dim_y * $dim_z; + my $max_port=7; + $config->{'multi_mesh'}{$mesh}{'MAX_P'}=$max_port; + $config->{'multi_mesh'}{$mesh}{'RID_INT'}=$first_router_id; + $config->{'multi_mesh'}{$mesh}{'NR'}=$nodes_num; + $first_router_id+=$nodes_num; + $config->{'router_counter'}=$first_router_id; + $config->{'endp_counter'}=$first_router_id; + my ($LOCAL, $EAST, $NORTH, $WEST, $SOUTH, $UP, $DOWN) = (0..6); + my $CLUSTER = ($dim_z==1)? 5 : 7; + # for my $x (0..$dim_x-1) { + # for my $y (0..$dim_y-1) { + # for my $z (0..$dim_z-1) { + # connect_nodes_local($config,$mesh,$x,$y,$z,$EAST,$mesh,($x+1),$y,$z,$WEST,$dim_x,$dim_y,$dim_z) if ($x < $dim_x-1); + # connect_nodes_local($config,$mesh,$x,$y,$z,$NORTH,$mesh,$x,$y-1,$z,$SOUTH,$dim_x,$dim_y,$dim_z) if ($y > 0 ); + # connect_nodes_local($config,$mesh,$x,$y,$z,$WEST,$mesh,$x-1,$y,$z,$EAST,$dim_x,$dim_y,$dim_z) if ($x > 0); + # connect_nodes_local($config,$mesh,$x,$y,$z,$SOUTH,$mesh,$x,$y+1,$z,$NORTH,$dim_x,$dim_y,$dim_z) if ($y<$dim_y-1); + # if($dim_z>1){ + # connect_nodes_local($config,$mesh,$x,$y,$z,$UP,$mesh,$x,$y,$z+1,$DOWN,$dim_x,$dim_y,$dim_z) if($z<$dim_z-1); + # connect_nodes_local($config,$mesh,$x,$y,$z,$DOWN,$mesh,$x,$y,$z-1,$UP,$dim_x,$dim_y,$dim_z) if($z>0 ); + # } + # } + # } + # } +} + +#sub get_all_minimal_paths_between_two_endps{ +# my ($self,$src, $dst)=@_; +# my @proceed_nodes; +# my @head_nodes; +# my $offset = 1; # this make sure a minimal path selection. +# my $max_len = 1000; +# push (@head_nodes,$src); +# push (@proceed_nodes,$src); +# my @paths; +# my @ports; +# my @paths_to_dst; +# my @ports_to_dst; +# my @first_path=($src); +# my @first_port=(0); +# $paths[0]=\@first_path; +# $ports[0]=\@first_port; +# # select one path +# my $n=0; +# my $min_dist=1000000; +# do{ +# my @current_path= @{$paths[$n]}; +# my @current_port= @{$ports[$n]}; +# # get head node +# my $head_node = $current_path[-1]; +# if(defined $head_node){ +# # get connected nodes for all ports +# #print "hn=$head_node\n"; +# my $pnum = 7; +# for (my $i=0;$i<$pnum; $i++){ +# my @new_path=@current_path; +# my @new_ports=@current_port; +# my $src_port = "Port[${i}]"; +# my $connect = $self->{'PCONNECT'}{$head_node}{$src_port}; +# if(defined $connect){ +# my ($node,$pnode)=split(/\s*,\s*/,$connect); +# #add connected nodes to head_nodes if they are not in path before +# if(!defined get_scolar_pos($node,@new_path)){ +# my $size=scalar @new_path; +# #if ($min_dist > $size){ +# if( ($min_dist+$offset) > $size && $max_len>=$size){ +# push (@new_path,$node); +# push (@new_ports,$pnode); +# push (@paths,\@new_path); +# push (@ports,\@new_ports); +# if($node eq $dst){ +# push(@paths_to_dst,\@new_path); +# push(@ports_to_dst,\@new_ports); +# $min_dist=$size+1 if ($min_dist > $size); +# } +# } +# } #if +# } +# }#for +# } +# $n++; +# # print "******$n, @{$paths[$n]}\n" if defined $paths[$n]; +# }while( defined $paths[$n]); +# #print "\@paths_to_dst". Dumper(@paths_to_dst). "\n \@ports_to_dst". Dumper(@ports_to_dst) . "\n" ; +# return (\@paths_to_dst,\@ports_to_dst); +#} + + +sub gen_multi_mesh_io_assign { + my $mesh=shift; + return + " + for(int i=0;i{'multi_mesh'}{$mesh}{'EID_INT'} = $config->{'multi_mesh'}{$mesh}{'RID_INT'}; + my $opt_nr = "-1"; + my $opt_ne = "+1"; + # Not interposer case + if ($config->{'multi_mesh'}{$mesh}{'RID_INT'}) { + $opt_ne = ""; + $opt_nr = ""; + $config->{'multi_mesh'}{$mesh}{'EID_INT'} = $config->{'multi_mesh'}{$mesh}{'RID_INT'}+1; + } + + return" + /**************** + * CLUSTER_${mesh} localparams + ****************/ + localparam + CLUSTER_${mesh}_NX = $config->{'multi_mesh'}{$mesh}{'dim_x'}, + CLUSTER_${mesh}_NY = $config->{'multi_mesh'}{$mesh}{'dim_y'}, + CLUSTER_${mesh}_NZ = $config->{'multi_mesh'}{$mesh}{'dim_z'}, + CLUSTER_${mesh}_MAX_P = $config->{'multi_mesh'}{$mesh}{'MAX_P'}, + CLUSTER_${mesh}_RID_INIT = $config->{'multi_mesh'}{$mesh}{'RID_INT'}, + CLUSTER_${mesh}_EID_INIT = $config->{'multi_mesh'}{$mesh}{'EID_INT'}, + CLUSTER_${mesh}_NE = CLUSTER_${mesh}_NX * CLUSTER_${mesh}_NY * CLUSTER_${mesh}_NZ${opt_ne}, + CLUSTER_${mesh}_NR = CLUSTER_${mesh}_NE${opt_nr}, + CLUSTER_${mesh}_NVP = 2 * (CLUSTER_${mesh}_NX * CLUSTER_${mesh}_NY); +"; +} + + +sub gen_multi_mesh_cluster_instant { + my $mesh=shift; + return " + `ifdef IO_PER_CLUSTER + input smartflit_chanel_t CLUSTER_${mesh}_endpoint_chan_in [CLUSTER_${mesh}_NE-1:0]; + output smartflit_chanel_t CLUSTER_${mesh}_endpoint_chan_out[CLUSTER_${mesh}_NE-1:0]; + `else + smartflit_chanel_t CLUSTER_${mesh}_endpoint_chan_in [CLUSTER_${mesh}_NE-1:0]; + smartflit_chanel_t CLUSTER_${mesh}_endpoint_chan_out[CLUSTER_${mesh}_NE-1:0]; + `endif + smartflit_chanel_t CLUSTER_${mesh}_inter_cluster_chan_in[CLUSTER_${mesh}_NVP-1:0]; + smartflit_chanel_t CLUSTER_${mesh}_inter_cluster_chan_out[CLUSTER_${mesh}_NVP-1:0]; + router_event_t CLUSTER_${mesh}_router_event [CLUSTER_${mesh}_NR-1:0][CLUSTER_${mesh}_MAX_P-1:0]; + + mesh_cluster #( + .NOC_ID(NOC_ID), + .CLUSTER_ID(${mesh}_ID), + .RID_INIT(CLUSTER_${mesh}_RID_INIT), + .CLUSTER_NX(CLUSTER_${mesh}_NX), + .CLUSTER_NY(CLUSTER_${mesh}_NY), + .CLUSTER_NZ(CLUSTER_${mesh}_NZ), + .CLUSTER_NE(CLUSTER_${mesh}_NE) + )the_${mesh}( + .reset(reset), + .clk(clk), + .cluster_id(${mesh}_ID), + .endpoint_chan_in(CLUSTER_${mesh}_endpoint_chan_in), + .endpoint_chan_out(CLUSTER_${mesh}_endpoint_chan_out), + .inter_cluster_chan_in(CLUSTER_${mesh}_inter_cluster_chan_in), + .inter_cluster_chan_out(CLUSTER_${mesh}_inter_cluster_chan_out), + .router_event(CLUSTER_${mesh}_router_event) + );\n "; +} + +sub get_xyz { + my ($config, $mesh, $id) = @_; + my $dim_x = $config->{'multi_mesh'}{$mesh}{'dim_x'}; + my $dim_y = $config->{'multi_mesh'}{$mesh}{'dim_y'}; + my $dim_z = $config->{'multi_mesh'}{$mesh}{'dim_z'}; + my $z = int($id / ($dim_x * $dim_y)); # Compute Z index + my $l = $id % ($dim_x * $dim_y); # Remaining index in the XY plane + my $x = $l % $dim_x; # Compute X index + my $y = int($l / $dim_x); # Compute Y index + return ($x, $y, $z); +} + +sub process_vertival_link_placement{ + my ($ref,$src,$dst,$dir,$verticals)=@_; + my @links=@{$ref}; + foreach my $link (@links){ + my ($src_endp,$dst_endp)=@$link; + #print "$dir link : $src $src_endp $dst $dst_endp \n"; + $verticals->{$dir}=()if (! exists $verticals->{$dir}); + push @{$verticals->{$dir}}, "$src:$src_endp:$dst:$dst_endp"; + my $node1=$src."_".$src_endp; + my $node2=$dst."_".$dst_endp; + my $port1 = 7; + my $port2 = 7; + connect_nodes($config,$node1,$port1,$node2,$port2); + add_edge(\%cluster_tree,$src,$src_endp,$dst,$dst_endp,$dir); + } +} + +sub vertical_links_placement{ + my ($mesh,$config,$vref,$I)=@_; + foreach my $direction (keys %{ $config->{'multi_mesh'}{$mesh}{'vertical_links_placement'} }) { + my $ref1=$config->{'multi_mesh'}{$mesh}{'vertical_links_placement'}{$direction}; + if (ref($ref1) eq 'HASH'){ + foreach my $dst_mesh (sort keys %{$ref1}){ + process_vertival_link_placement(@{$ref1}{$dst_mesh},$mesh,$dst_mesh,$direction,$vref); + } + }else{ + process_vertival_link_placement($ref1,$mesh,$I,$direction,$vref); + } + } +} + +sub process_vertival_link_selection{ + my ($ref,$src,$dst,$dir,$verticals)=@_; + my @links=@{$ref}; + foreach my $link (@links){ + my ($src_endp,$dst_endp)=@$link; + #print "$dir link : $src $src_endp $dst $dst_endp \n"; + $verticals->{$dir}{$src}{$dst}{$src_endp}=$dst_endp; + } +} +sub vertical_links_selection{ + my ($mesh,$config,$vref,$I)=@_; + foreach my $direction (keys %{ $config->{'multi_mesh'}{$mesh}{'vertical_links_selection'} }) { + my $ref1=$config->{'multi_mesh'}{$mesh}{'vertical_links_selection'}{$direction}; + if (ref($ref1) eq 'HASH'){ + foreach my $dst_mesh (sort keys %{$ref1}){ + process_vertival_link_selection(@{$ref1}{$dst_mesh},$mesh,$dst_mesh,$direction,$vref); + } + }else{ + process_vertival_link_selection($ref1,$mesh,$I,$direction,$vref); + } + } +} + +sub get_vp_id{ + my ($config,$mesh, $node,$dir)=@_; + my ($x, $y, $z) = get_xyz($config, $mesh, $node); + my $dimx = $config->{'multi_mesh'}{$mesh}{'dim_x'}; + my $dimy = $config->{'multi_mesh'}{$mesh}{'dim_y'}; + my $dimz = $config->{'multi_mesh'}{$mesh}{'dim_z'}; + # Ensure inter-cluster connections are only at the first (0) or last ($dimz-1) position in the Z dimension + if ($z != 0 && $z != $dimz - 1) { + die "Error: Inter-cluster connection at Z=$z is invalid. It must be at either the first (0) or last ($dimz-1) position in the Z dimension."; + } + # If the router is at the first Z-dimension layer (Z=0) and not the only layer, + # it must only have a 'down' connection. + if ($z == 0 && $dimz > 1 && $dir ne 'down') { + die "Error: Routers at the first Z layer (Z=0) can only have a 'down' connection."; + } + # If the router is at the last Z-dimension layer (Z=$dimz-1) and not the only layer, + # it must only have an 'up' connection. + if ($z == $dimz - 1 && $dimz > 1 && $dir ne 'up') { + die "Error: Routers at the last Z layer (Z=$dimz-1) can only have an 'up' connection."; + } + my $vp= ($dir eq 'down')? ($y * $dimx) + $x : ($dimx * $dimy) + ($y * $dimx) + $x; + return $vp; +} + +sub gen_multi_mesh_vertical_link_assign{ + my ($vref,$is_connected,$connections_hash)=@_; + my %verticals=%{$vref}; + my $links_assign=""; + my $unconnected_err=""; + foreach my $dir (sort keys %verticals){ + #get number of up/down links + my @connections = @{$verticals{$dir}}; + my $link_num=scalar @connections; + my $DIR = uc $dir; + #$rtl_cluster_instant.=" localparam ${DIR}_LINK_NUM=$link_num;\n"; + $links_assign.=" //cluster_to_cluster $dir connections\n"; + foreach my $c (@connections){ + my ($src,$src_endp,$dst,$dst_endp) = split ":", $c; + #print "($src:$src_endp:$dst:$dst_endp)\n"; + my $src_dir=$dir; + my $src_vp = get_vp_id($config,$src,$src_endp,$src_dir); + my $dst_dir= ($src_dir eq 'up')? 'down' : 'up'; + my $dst_vp = get_vp_id($config,$dst,$dst_endp,$dst_dir); + $links_assign.=" CLUSTER_${dst}_inter_cluster_chan_in[$dst_vp] = CLUSTER_${src}_inter_cluster_chan_out[$src_vp]; // ${src}[$src_endp] dir $src_dir to ${dst}[$dst_endp] dir $dst_dir\n"; + $is_connected->{'IN'}{$dst}{$dst_vp}=1; + $is_connected->{'OUT'}{$src}{$src_vp}=1; + # Store the connection in a hash + $connections_hash->{"$src,$src_vp"}{"$dst,$dst_vp"} = 1; + } + }#$direction + $links_assign.=" //Unconnected cluster connections are grounded\n"; + my %connected = %{$is_connected->{'IN'}}; + foreach my $m (sort keys %connected){ + foreach my $p (sort { $a <=> $b } keys %{$connected{$m}}){ + if ($connected{$m}{$p}==0){ + $links_assign.=" CLUSTER_${m}_inter_cluster_chan_in[$p] = is_grounded;\n"; + } + } + } + %connected = %{$is_connected->{'OUT'}}; + foreach my $m (sort keys %connected){ + foreach my $p (sort { $a <=> $b } keys %{$connected{$m}}){ + if ($connected{$m}{$p}==0){ + $unconnected_err.=" if( CLUSTER_${m}_inter_cluster_chan_out[$p].flit_chanel.flit_wr) begin `ERROR_UNCNT(\"${m}\",$p) end\n"; + } + } + } + return ($links_assign,$unconnected_err); +} + +sub gen_multimesh_unidir_vlinks{ + my ($vref,$connections_hash)=@_; + my %verticals=%{$vref}; + my $uni_dir=""; + foreach my $dir (sort keys %verticals){ + my @connections = @{$verticals{$dir}}; + foreach my $c (@connections) { + my ($src, $src_endp, $dst, $dst_endp) = split ":", $c; + my $src_dir=$dir; + my $src_vp = get_vp_id($config,$src,$src_endp,$src_dir); + my $dst_dir= ($src_dir eq 'up')? 'down' : 'up'; + my $dst_vp = get_vp_id($config,$dst,$dst_endp,$dst_dir); + + # Check if the reverse connection exists + if (!exists $connections_hash->{"$dst,$dst_vp"}{"$src,$src_vp"}) { + #push @unidirectional_channels, "$src:$src_endp:$dst:$dst_endp"; + print "[info]: Unidirectional chanel is detected $src,$src_endp -> $dst,$dst_endp\n"; + $uni_dir.= +" CLUSTER_${src}_inter_cluster_chan_in[$src_vp].flit_chanel.credit = CLUSTER_${dst}_inter_cluster_chan_out[$dst_vp].flit_chanel.credit; + CLUSTER_${src}_inter_cluster_chan_in[$src_vp].ctrl_chanel = CLUSTER_${dst}_inter_cluster_chan_out[$dst_vp].ctrl_chanel;\n" + } + } + }#$direction + return $uni_dir; +} + +sub gen_noc_localparam { + my ($vcs,$config)=@_; + my $rtl=""; + #Create Noc configuration file + my @values = values %$vcs; + # Compute min and max + my $min_vc = min(@values); + my $max_vc = max(@values); + my $pp; + $pp= do "$noc_param_object_file"; + die "Error reading: $@" if $@; + $pp->{'noc_param'}{"TOPOLOGY"}="\"$topology\""; + $pp->{'noc_param'}{"T1"}=$config->{'router_counter'}; + $pp->{'noc_param'}{"MIN_PCK_SIZE"}= 1; + #$pp->{'noc_param'}{"T2"}=$config->{'endp_counter'}; + $pp->{'noc_param'}{"T3"}=1; + $pp->{'noc_param'}{"V"}=$max_vc; + $pp->{'noc_param'}{"B"}=$config->{'buffer_depth'}; + $pp->{'noc_param'}{"Fpay"}=64; + $pp->{'noc_param'}{"ROUTE_NAME"}="\"$config->{'routing_algorithm'}\""; + $pp->{'noc_param'}{"SELF_LOOP_EN"} = '"YES"'; + + if($min_vc !=$max_vc ){ + $pp->{'noc_param'}{'HETERO_VC'} = 1; + $pp->{'noc_param'}{'MAX_ROUTER'} = $config->{'router_counter'}; ; + $pp->{'noc_param'}{'MAX_PORT'} = 1; + my $hetero_vc="'{\n //VC cluster local_id global_id\n"; + my $coma=""; + foreach my $mesh (keys %{$config->{multi_mesh}}) { + my $nr =$config->{'multi_mesh'}{$mesh}{'NR'}; + my $rid_int= $config->{'multi_mesh'}{$mesh}{'RID_INT'}; + my $r=0; + my $v=$vcs->{$mesh}; + for (my $n=$rid_int; $n < $rid_int + $nr;$n++){ + $hetero_vc.= " $coma'{$v} // $mesh: r$r R$n \n"; + $coma=","; + $r++; + } + } + $hetero_vc.="} "; + $pp->{'noc_param'}{'int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]'} = "$hetero_vc"; + } else { + $pp->{'noc_param'}{'HETERO_VC'} = 0; + my $homogeneous_vc = "'{'{0}};"; + $pp->{'noc_param'}{'int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]'} = "$homogeneous_vc"; + } + + my $param = $pp->{'noc_param'}; + my %default_noc_param=%{$param}; + my @params_order=@{$pp->{'parameters_order'}{'noc_param'}}; + $rtl.=" + `ifdef NOC_LOCAL_PARAM + /************************************* + * ProNoC localparams + *************************************/\n + `include \"define.tmp.h\"\n"; + foreach my $p (@params_order){ + next if ($p eq "T2"); + $rtl.=" localparam $p = $default_noc_param{$p};\n"; + } + + my $count = 0; + my @lines; + foreach my $mesh (keys %{$config->{multi_mesh}}) { + push @lines, sprintf(" %s_ID = %d,", uc $mesh , $cluster_ids{$mesh}); + } + $rtl.=" + /************************************* + * multimesh localparams + *************************************/ + localparam\n".join("\n", @lines)." + MAX_RID= T1, + RIDw = \$clog2(MAX_RID), + CLUSTER_NUM = $config->{'cluster_counter'}, + CLUSTER_IDw= (CLUSTER_NUM==1) ? 1 : \$clog2(CLUSTER_NUM), + CLUSTER_MAX_X=$config->{'max_x'}, + CLUSTER_Xw = (CLUSTER_MAX_X==1)? 1 : \$clog2(CLUSTER_MAX_X), + CLUSTER_MAX_Y=$config->{'max_y'}, + CLUSTER_Yw = (CLUSTER_MAX_Y==1)? 1 : \$clog2(CLUSTER_MAX_Y), + CLUSTER_MAX_Z=$config->{'max_z'}, + CLUSTER_Zw = (CLUSTER_MAX_Z==1)? 1 : \$clog2(CLUSTER_MAX_Z); + + typedef struct packed { + logic [CLUSTER_IDw-1: 0] c; + logic [CLUSTER_Zw-1 : 0] z; + logic [CLUSTER_Yw-1 : 0] y; + logic [CLUSTER_Xw-1 : 0] x; + } multimesh_router_addr_t; + localparam T2= \$bits(multimesh_router_addr_t); + "; + + return $rtl; +} +sub gen_muli_mesh_topology_rtl{ + my ($rtl_io_per_cluster,$rtl_cluster_instant,$rtl_io_assign, $rtl_vertical_links_assign ,$v_err ) = @_; + return + " +`include \"pronoc_def.v\" +module multi_mesh #( + parameter NOC_ID=0 + )( + `ifndef IO_PER_CLUSTER + chan_in_all, + chan_out_all, + router_event, + `else +$rtl_io_per_cluster + `endif + reset, + clk +); + + `NOC_CONF + `ifndef IO_PER_CLUSTER + input smartflit_chanel_t chan_in_all [NE-1 : 0]; + output smartflit_chanel_t chan_out_all [NE-1 : 0]; + //Events + output router_event_t router_event [NR-1 : 0][MAX_P-1 : 0]; + `endif + + input reset,clk; + + //Unused Input channels are connected to ground + smartflit_chanel_t is_grounded = {SMARTFLIT_CHANEL_w{1'b0}}; + +$rtl_cluster_instant + + //chiplet interconnect + always_comb begin + `ifndef IO_PER_CLUSTER +$rtl_io_assign + `endif +$rtl_vertical_links_assign end + +`define ERROR_UNCNT(cluster, port) \\ + \$display(\"Error: A flit was injected into an unconnected NoC router port.\"); \\ + \$display(\"Cluster: \%s, Port: %0d\", cluster, port); \\ + \$display(\"Simulation will terminate due to this unexpected behavior.\"); \\ + \$finish; + + +`ifdef SIMULATION + always \@ ( posedge clk ) begin +$v_err + end +`endif + +endmodule +"; +} +sub get_rtl_hdr_file{ + my $file_name=shift; + return +"//Autogen warning for $file_name .... +//lisence +"; +} +########### +# functions +########### +sub gen_noc_cluster_id_func{ + my $config=shift; + my $lines1=""; + my $lines2=""; + my $if="if"; + my $addr_id_rtl=""; + my $lines3=""; + foreach my $mesh (keys %{$config->{multi_mesh}}) { + my $MESH=uc $mesh; + $lines1.=" $if (rid < CLUSTER_${MESH}_RID_INIT + CLUSTER_${MESH}_NR) router_id_to_cluster_id =${MESH}_ID;\n"; + $lines2.=" $if (rid < CLUSTER_${MESH}_RID_INIT + CLUSTER_${MESH}_NR) router_id_to_cluster_router_id = rid - CLUSTER_${MESH}_RID_INIT;\n"; + $if="else if"; + } + return" + function automatic [CLUSTER_IDw-1:0] router_id_to_cluster_id ; + input [RIDw-1 : 0] rid; + begin +$lines1 end + endfunction + + //This function get the global unique router id and return the router local id in cluster + function automatic [RIDw-1 : 0] router_id_to_cluster_router_id ; + input [RIDw-1 : 0] rid; + begin +$lines2 end + endfunction +"; +} + +sub find_nearest_vlink { + my ($config, $mesh, $up, $dir, $rid) = @_; + my @nodes = get_all_connection_nodes_to_a_cluster(\%cluster_tree, $mesh, $dir, $up); + my $min; + my $nearest_node; + foreach my $node (@nodes) { + my ($x1, $y1, $z1) = get_xyz($config, $mesh, $node); + my ($x2, $y2, $z2) = get_xyz($config, $mesh, $rid); + my $manhattan_dist = abs($x1 - $x2) + abs($y1 - $y2) + abs($z1 - $z2); + if (!defined $min || $manhattan_dist < $min) { + $min = $manhattan_dist; + $nearest_node = $node; + } + } + return $nearest_node; +} + +sub get_cmin_cmax{ + my($tree,$mesh)=@_; + my @up_leaf = get_clusters_up_to_leaf ($tree, $mesh); + # Get the IDs of all leaf clusters + my @ids = sort { $a <=> $b } map { $cluster_ids{$_} } @up_leaf; + # Ensure the IDs are continuous + for my $i (0 .. $#ids - 1) { + die "Error: Cluster IDs are not continuous!: @ids \n" if $ids[$i] + 1 != $ids[$i + 1]; + } + # Return the min and max ID + return ($ids[0], $ids[-1]); +} + +sub create_inter_cluster_routing { + my ($config,$Vlinks_sel)=@_; + my $not_dynamic=""; + my $not_dynamic_modules=""; + my $if="if"; + foreach my $mesh (keys %{$config->{multi_mesh}}) { + my $MESH=uc $mesh; + my $nr =$config->{'multi_mesh'}{$mesh}{'NR'}; + $not_dynamic .=" $if ( CLUSTER_ID == ${MESH}_ID ) begin + hard_coded_icr_${MESH} #( + .CLUSTER_ID(CLUSTER_ID), + .RID(RID) + )icr_comb ( + .dest_address(dest_address), + .local_cluster_endp_addr(local_cluster_endp_addr), + .up_dir_sel(up_dir_sel) + );\n"; + $if="else if"; + $not_dynamic_modules .= + "module hard_coded_icr_${MESH} #( + parameter CLUSTER_ID=0, + parameter RID=0\n)( + dest_address, + local_cluster_endp_addr, + up_dir_sel\n); + `NOC_CONF + input multimesh_router_addr_t dest_address; + output multimesh_router_addr_t local_cluster_endp_addr; + output logic up_dir_sel; + localparam unsigned [CLUSTER_IDw-1 : 0] current_cluster_id = CLUSTER_ID; + typedef struct packed { + logic [CLUSTER_IDw-1 : 0] Cmin,Cmax; + multimesh_router_addr_t endp_addr; + bit valid; + } cluster_hid_entry_t; + multimesh_router_addr_t + local_cluster_endp_addr_up_dir, + local_cluster_endp_addr_down_dir; + "; + my @up_clusters = get_clusters_in_dir (\%cluster_tree,$mesh,'up'); + my @down_clusters = get_clusters_in_dir (\%cluster_tree,$mesh,'down'); + if(scalar @down_clusters>1){ + die "Error: multiple Cluster @down_clusters are detected for $mesh chiplet which is not supported by 2.5 D mesh \n"; + } + my $no_down=((scalar @down_clusters)==0)? 1 : 0; + $not_dynamic_modules .= " " x 8 . "localparam NO_DOWNLINK = $no_down;\n"; + if(scalar @up_clusters){ + my $s=scalar @up_clusters; + $not_dynamic_modules .= " " x 8 . "localparam MAX_ENTRY_${MESH} = $s;\n"; + $not_dynamic_modules .= " " x 8 . "cluster_hid_entry_t address_table [MAX_ENTRY_${MESH}];\n"; + $not_dynamic_modules .= " " x 8 . "multimesh_router_addr_t endp_addr_array [MAX_ENTRY_${MESH}];\n"; + $not_dynamic_modules .= " " x 8 . "wire [CLUSTER_IDw-1 : 0] Cmax_array_${MESH} [MAX_ENTRY_${MESH}];\n"; + $not_dynamic_modules .= " " x 8 . "wire [CLUSTER_IDw-1 : 0] Cmin_array_${MESH} [MAX_ENTRY_${MESH}];\n"; + my $i=0; + foreach my $up (@up_clusters){ + my ($cmin,$cmax) = get_cmin_cmax(\%cluster_tree,$up); + $not_dynamic_modules .= " " x 8 . "assign Cmax_array_${MESH} [$i]= $cmax;\n"; + $not_dynamic_modules .= " " x 8 . "assign Cmin_array_${MESH} [$i]= $cmin;\n"; + $i++; + } + }else { + $not_dynamic_modules .=" " x 8 ."//There are no upper chiplet. Select between local and down chiplet\n"; + } + $not_dynamic_modules .=" " x 8 ."generate \n case (RID)\n"; + for (my $rid=0;$rid<$nr;$rid++){ + $not_dynamic_modules .=" " x 8 . "$rid: begin \n"; + my $i=0; + my $coma=""; + foreach my $up (@up_clusters){ + #check if vertical link connection exsited in yaml file + my $local_dst=$Vlinks_sel->{'up'}{$mesh}{$up}{$rid}; + my $via_yml = (defined $local_dst)? 1:0; + $local_dst= ($via_yml==1)? $local_dst : find_nearest_vlink($config,$mesh,$up,"up",$rid); + my ($x,$y,$z)=get_xyz($config,$mesh,$local_dst); + my $comment =($via_yml ==1)? + "S:Yaml,T:$up,R:$local_dst": + "S:Auto,T:$up,R:$local_dst"; + $not_dynamic_modules .=" " x 12 . "assign endp_addr_array[$i]='{x:$x, y:$y, z:$z, c:${mesh}_ID};/*$comment*/\n"; + $i++; + $coma=","; + } + unless($no_down){ + my $local_dst=find_nearest_vlink($config,$mesh,$down_clusters[0],"down",$rid); + my ($x,$y,$z)=get_xyz($config,$mesh,$local_dst); + my $comment ="S:Auto,T:$down_clusters[0],R:$local_dst"; + $not_dynamic_modules .=" " x 12 . "assign local_cluster_endp_addr_down_dir ='{x:$x, y:$y, z:$z, c:${mesh}_ID};/*$comment*/\n"; + } + $not_dynamic_modules .=" " x 8 ."end //$rid\n"; + } + $not_dynamic_modules .=" " x 8 . "endcase\n endgenerate\n"; + if(scalar @up_clusters){ + $not_dynamic_modules .=" " x 8 . "always_comb begin + local_cluster_endp_addr_up_dir=0; + up_dir_sel=1'b0; + for (int i=0;i< MAX_ENTRY_${MESH};i++) begin + if(Cmin_array_${MESH}[i] <= dest_address.c && dest_address.c <= Cmax_array_${MESH}[i]) begin + local_cluster_endp_addr_up_dir = endp_addr_array[i]; + up_dir_sel=1'b1; + end + end + end\n"; + }else{ + $not_dynamic_modules .=" " x 8 . "always_comb begin + local_cluster_endp_addr_up_dir=0; + up_dir_sel=1'b0; + end\n"; + } + $not_dynamic .=" end\n"; + $not_dynamic_modules .=" + assign local_cluster_endp_addr = + ( dest_address.c == current_cluster_id )? dest_address: + ( up_dir_sel) ? local_cluster_endp_addr_up_dir: + local_cluster_endp_addr_down_dir; +endmodule\n\n"; + } + +my $rtl=" +`include \"pronoc_def.v\" +module global_id_to_local_cluster_endp #( + parameter NOC_ID=0 + `ifndef DYNAMIC_CLUSTER_INIT + ,parameter CLUSTER_ID=0, + parameter RID=0 + `endif +)( + `ifdef DYNAMIC_CLUSTER_INIT + address_table, + local_cluster_endp_addr_down_dir, + current_cluster_id, + `endif + dest_address, + local_cluster_endp_addr, + up_dir_sel +); + `NOC_CONF + input multimesh_router_addr_t dest_address; + output multimesh_router_addr_t local_cluster_endp_addr; + output logic up_dir_sel; + + `ifdef DYNAMIC_CLUSTER_INIT + input cluster_hid_entry_t address_table [MAX_ENTRY]; + input multimesh_router_addr_t local_cluster_endp_addr_down_dir; + input [CLUSTER_IDw-1 : 0] current_cluster_id; + `endif + + `ifndef DYNAMIC_CLUSTER_INIT + generate +$not_dynamic + endgenerate + `else + dynamic_icr icr ( + .dest_address(dest_address), + .local_cluster_endp_addr(local_cluster_endp_addr), + .local_cluster_endp_addr_down_dir(local_cluster_endp_addr_down_dir), + .current_cluster_id(current_cluster_id), + .address_table(address_table), + up_dir_sel(up_dir_sel) + ); + `endif +endmodule + +`ifdef DYNAMIC_CLUSTER_INIT +module dynamic_icr ( + dest_address, + local_cluster_endp_addr, + local_cluster_endp_addr_down_dir, + current_cluster_id, + address_table, + up_dir_sel +); + `NOC_CONF + input multimesh_router_addr_t dest_address; + output multimesh_router_addr_t local_cluster_endp_addr; + input multimesh_router_addr_t local_cluster_endp_addr_down_dir; + input [CLUSTER_IDw-1 : 0] current_cluster_id; + input cluster_hid_entry_t address_table [MAX_ENTRY]; + output logic up_dir_sel; + + multimesh_router_addr_t local_cluster_endp_addr_up_dir; + + always_comb begin + local_cluster_endp_addr_up_dir=0; + up_dir_sel=1'b0; + for (int i=0;i< MAX_ENTRY;i++) begin + if(address_table[i].valid) begin + if(address_table[i].Cmin <= dest_address.c && dest_address.c < address_table[i].Cmax) begin + local_cluster_endp_addr_up_dir = address_table[i].endp_addr; + up_dir_sel=1'b1; + end + end + end + end + + assign local_cluster_endp_addr = + ( dest_address.c == current_cluster_id )? dest_address: + ( up_dir_sel) ? local_cluster_endp_addr_up_dir: + local_cluster_endp_addr_down_dir; +endmodule + +module dynamic_hids_per_router ( + local_cluster_endp_addr_down_dir, + current_cluster_id, + address_table, + program_port, + reset, + clk +); + `NOC_CONF + output cluster_hid_entry_t address_table [MAX_ENTRY]; + input clk,reset; + input program_port_t program_port; + output multimesh_router_addr_t local_cluster_endp_addr_down_dir; + output logic [CLUSTER_IDw-1 : 0] current_cluster_id; + + always_ff @(posedge clk or posedge reset) begin + if(reset) begin + local_cluster_endp_addr_down_dir=0; + foreach (address_table[i]) begin + address_table[i].valid <= 1'b0; + current_cluster_id<=0; + end + end else begin + if(program_port.data.valid) begin + if( !program_port.down_sel ) begin + address_table[program_port.addr] <= program_port.data; + current_cluster_id <= program_port.current_cluster_id; + end else local_cluster_endp_addr_down_dir=program_port.data.endp_addr; + end + end + end +endmodule + +`else +$not_dynamic_modules +`endif + +"; +return $rtl; + + +} +########### +# modules +######### + +sub create_routing_modules{ + my $rtl = multimesh_address_encoder(@_); + $rtl.= multimesh_address_decoder(@_); + return $rtl; +} + +sub multimesh_address_decoder{ + my $config=shift; + my $lines=""; + foreach my $mesh (keys %{$config->{multi_mesh}}) { + my $MESH=uc $mesh; + $lines.=" + for (int z=0; z{multi_mesh}}) { + my $MESH=uc $mesh; + $lines.=" + for (z=0; z', $rtl_file) or die "Could not create file '$rtl_file' $!"; + print $output_fh $header.$rtl_code; + close($output_fh); + print"[info:] Create $rtl_file\n"; +} + +sub generate_pronoc_multimesh{ + my %verticals; + my %Vlinks_sel; + my %is_connected; + my %connections_hash; + my %vcs; + #generate routers_global_ids + my $I=find_interpose($config); + my %router_ids; + my $multimesh_rtl_file="$out_dir/".lc $topology.".sv"; + my $noc_param_file="$out_dir/noc_localparam.v"; + my $multimesh_routing_file="$out_dir/". lc ${topology}."_routing.sv"; + my $intercluster_routing_table="$out_dir/". lc ${topology}."_icr.sv"; + my $rtl_io_per_cluster =""; + my $rtl_cluster_instant=""; + my $rtl_io_assign=""; + my $rtl_cluster_localparam=""; + my $rtl_noc_localparam=""; + my $rtl_vertical_links_assign=""; + + print"[info:]generating $topology topology file in $multimesh_rtl_file\n"; + foreach my $mesh (keys %{$config->{multi_mesh}}) { + print "\t[info:] Add CLUSTER_${mesh} instantiation \n"; + update_multimesh_config($mesh,$config,\%vcs); + $rtl_io_assign.=gen_multi_mesh_io_assign($mesh); + $rtl_io_per_cluster.=gen_io_name_per_cluster($mesh); + $rtl_cluster_localparam.=gen_multi_mesh_cluster_localparam($mesh,$config); + $rtl_cluster_instant.=gen_multi_mesh_cluster_instant($mesh); + my $nodes_num = $config->{'multi_mesh'}{$mesh}{'NR'}; + for( my $i=0; $i<$nodes_num; $i++) { + $is_connected{'IN'}{$mesh}{$i}=0; + $is_connected{'OUT'}{$mesh}{$i}=0; + } + if (exists $config->{'multi_mesh'}{$mesh}{'vertical_links_placement'}) { + vertical_links_placement($mesh,$config,\%verticals,$I); + } + if (exists $config->{'multi_mesh'}{$mesh}{'vertical_links_selection'}){ + vertical_links_selection($mesh,$config,\%Vlinks_sel,$I); + } + } + %cluster_ids=get_cluster_ids($config,\%cluster_tree); + my ($v_links,$v_err)=gen_multi_mesh_vertical_link_assign(\%verticals,\%is_connected,\%connections_hash); + $rtl_vertical_links_assign.=$v_links; + #Uni directional channels + my $uni_dir=gen_multimesh_unidir_vlinks(\%verticals,\%connections_hash); + if (length ($uni_dir) >3){ + $rtl_vertical_links_assign.= + "//fix credit/ctrl chanel connection for unidirectional channels\n$uni_dir"; + } + + my $rtl_code=gen_muli_mesh_topology_rtl ($rtl_io_per_cluster,$rtl_cluster_instant,$rtl_io_assign, $rtl_vertical_links_assign, $v_err ) ; + create_rtl_file( $multimesh_rtl_file,$rtl_code); + + $rtl_code=gen_noc_localparam(\%vcs,$config); + $rtl_code.=$rtl_cluster_localparam; + $rtl_code.=gen_noc_cluster_id_func($config); + $rtl_code.=" typedef struct packed { + logic [CLUSTER_IDw-1 : 0] Cmin,Cmax; + multimesh_router_addr_t endp_addr; + bit valid; + } cluster_hid_entry_t; + + localparam [1:0] + Z_PLUS_SEL=2'b00, + Z_MIN_SEL=2'b01, + BOTH_SEL=2'b10, + SAME_SEL=2'b11; + + + `ifdef DYNAMIC_CLUSTER_INIT + localparam MAX_ENTRY=10; + typedef struct packed { + cluster_hid_entry_t data; + logic [\$clog2(MAX_ENTRY)-1 : 0] addr; + logic [CLUSTER_IDw-1 : 0] current_cluster_id; + bit down_sel; + } program_port_t; + `endif + `endif\n"; + create_rtl_file($noc_param_file,$rtl_code); + $rtl_code=create_routing_modules($config); + create_rtl_file($multimesh_routing_file,$rtl_code); + $rtl_code= create_inter_cluster_routing($config,\%Vlinks_sel); + create_rtl_file($intercluster_routing_table,$rtl_code); + +#my @children = get_clusters_in_dir (\%cluster_tree,'C1','down'); +#print "'C1 down: @children\n"; +#@children = get_clusters_in_dir (\%cluster_tree,'C1','up'); +#print "'C1 up: @children\n"; +#@children = get_clusters_in_dir (\%cluster_tree,'I','down'); +#print "'I down: @children\n"; +#@children = get_clusters_in_dir (\%cluster_tree,'I','up'); +#print "'I up: @children\n"; +#print Dumper(\%cluster_ids); + +} + +#sub get_nearest_vlink{ +# my ($config,$mesh1,$id1,$mesh2,$id2)=@_; +# print "$mesh1,$id1,$mesh2,$id2\n"; +# return undef if($mesh1 eq $mesh2); +# my ($paths_to_dst,$ports_to_dst) = get_all_minimal_paths_between_two_endps($config,$mesh1."_".$id1,$mesh2."_".$id2); +# my $min_index=100000; +# my $i=0; +# my @a; +# foreach my $path (@{$ports_to_dst}) { +# if (defined $path){ +# my @ports=@{$path}; +# my $p= get_scolar_pos(7,@ports) // get_scolar_pos(5,@ports); +# if($min_index>$p){ +# $min_index=$p; +# @a= @{$paths_to_dst->[$i]}; +# } +# } +# $i++; +# } +# +# my @l=split ("_", $a[$min_index-1]); +# #print "** @a : $min_index\n"; +# print "local selection $a[$min_index-1]\n mesh is $l[0], id is $l[1]\n"; +# return $l[1]; +#} + +1; + diff --git a/mpsoc/script/multimesh/pronoc_dp_gen.py b/mpsoc/script/multimesh/pronoc_dp_gen.py new file mode 100755 index 0000000..c60a527 --- /dev/null +++ b/mpsoc/script/multimesh/pronoc_dp_gen.py @@ -0,0 +1,862 @@ +from collections import defaultdict +import os +import sys + +piton_dir = os.environ.get('PITON_ROOT', "") +if piton_dir == "": + raise Exception("PITON_ROOT must be defined") + +sys.path.append(os.path.join(piton_dir, + "piton/tools/bin")) + +from piton_common import * + +# Number of ports necessary for Depth-First +MAX_PORT = 7 + +# Indentation size +TAB = " "*4 + +# System Configuration +chip_infos = {} + +# Define Virtual Channels Constants +# NOTE: The values should not be modified for now as the ProNoC router does not +# support that Z_MIN_VC = 2 when using a single VC on the interposer. Z- must +# have the VC index 0 (i.e. a one-hot encoded value of 1). +Z_MIN_VC = 1 # 2'd01 +Z_PLUS_VC = 2 # 2'd10 +Z_MIN_VC_IDX = Z_MIN_VC - 1 +Z_PLUS_VC_IDX = Z_PLUS_VC - 1 + + +# Load system configuration from the caller +def load_chip_infos(piton_chip_infos): + global chip_infos + chip_infos = piton_chip_infos + + +# Open and write the code in a specific file +def write_in_file(path_to_file, content): + filename, ext = os.path.splitext(os.path.basename(path_to_file)) + header = f"// {filename}{ext} -- auto-generated\n" + + with open(path_to_file, 'w') as output_fh: + output_fh.write(header + content) + print(f"[info] Create {path_to_file}") + + +# Bulk generation of all multimesh files +def generate_pronoc_multimesh(out_dir): + multimesh_rtl_file = os.path.join(out_dir, "multi_mesh.sv") + noc_param_file = os.path.join(out_dir, "noc_localparam.v") + multimesh_routing_file = os.path.join(out_dir, "multi_mesh_routing.sv") + intercluster_routing_table = os.path.join(out_dir, "multi_mesh_icr.sv") + rtl_intercluster_channels = "" + rtl_cluster_instant = "" + rtl_io_assign = "" + rtl_cluster_localparam = "" + rtl_vertical_links_assign = "" + + print(f"[info] Generating topology file in {multimesh_rtl_file}") + + for chip_name, chip_info in chip_infos.items(): + print(f"\t[info] Add CLUSTER_{chip_name} instantiation") + rtl_io_assign += gen_multi_mesh_io_assign(chip_name) + rtl_intercluster_channels += gen_io_name_per_cluster(chip_name) + rtl_cluster_localparam += gen_multi_mesh_cluster_localparam(chip_info) + rtl_cluster_instant += gen_multi_mesh_cluster_instant(chip_name) + + v_links, _, v_err, grounded_signals = gen_multi_mesh_vertical_link_assign() + rtl_vertical_links_assign += v_links + + rtl_code = gen_multi_mesh_topology_rtl(rtl_cluster_instant, rtl_io_assign, + rtl_vertical_links_assign, v_err, + grounded_signals) + write_in_file(multimesh_rtl_file, rtl_code) + + rtl_code = gen_noc_localparam() + rtl_code += rtl_cluster_localparam + rtl_code += f""" +{TAB}typedef struct packed {{ +{TAB}{TAB}logic [CLUSTER_IDw-1:0] Cmin, Cmax; +{TAB}{TAB}multimesh_router_addr_t endp_addr; +{TAB}{TAB}bit valid; +{TAB}}} cluster_hid_entry_t; + +{TAB}localparam [V-1:0] +{TAB}{TAB}Z_PLUS_VC = {Z_PLUS_VC}, +{TAB}{TAB}Z_MIN_VC = {Z_MIN_VC}; + +{TAB}localparam +{TAB}{TAB}Z_PLUS_VC_IDX = {Z_PLUS_VC_IDX}, +{TAB}{TAB}Z_MIN_VC_IDX = {Z_MIN_VC_IDX}; + +`ifdef DYNAMIC_CLUSTER_INIT +{TAB}localparam DYN_ICRT_MAX_ENTRY = 10; +{TAB}typedef struct packed {{ +{TAB}{TAB}cluster_hid_entry_t data; +{TAB}{TAB}logic [$clog2(DYN_ICRT_MAX_ENTRY)-1:0] addr; +{TAB}{TAB}logic [CLUSTER_IDw-1:0] current_cluster_id; +{TAB}{TAB}bit down_sel; +{TAB}}} program_port_t; +`endif // DYNAMIC_CLUSTER_INIT +""" + rtl_code += "`endif // NOC_LOCAL_PARAM\n" + write_in_file(noc_param_file, rtl_code) + rtl_code = create_routing_modules() + write_in_file(multimesh_routing_file, rtl_code) + rtl_code = create_inter_cluster_routing() + write_in_file(intercluster_routing_table, rtl_code) + + +def gen_multi_mesh_io_assign(chip_name): + CHIP = chip_name.upper() + return f""" +{TAB}{TAB}for (int i = 0; i < CLUSTER_{CHIP}_NE; i++) begin +{TAB}{TAB}{TAB}CLUSTER_{chip_name}_endpoint_chan_in[i] = chan_in_all[CLUSTER_{CHIP}_EID_INIT+i]; +{TAB}{TAB}{TAB}chan_out_all[CLUSTER_{CHIP}_EID_INIT+i]= CLUSTER_{chip_name}_endpoint_chan_out[i]; +{TAB}{TAB}end +""" + + +def gen_io_name_per_cluster(chip_name): + return f""" +{TAB}CLUSTER_{chip_name}_endpoint_chan_in, +{TAB}CLUSTER_{chip_name}_endpoint_chan_out, +""" + + +def gen_multi_mesh_cluster_localparam(chip_info): + CHIP = chip_info._name.upper() + return f""" +{TAB}/**************** +{TAB}* CLUSTER_{CHIP} localparams +{TAB}****************/ +{TAB}localparam +{TAB}{TAB}CLUSTER_{CHIP}_NX = {chip_info._dim_x}, +{TAB}{TAB}CLUSTER_{CHIP}_NY = {chip_info._dim_y}, +{TAB}{TAB}CLUSTER_{CHIP}_NZ = {chip_info._dim_z}, +{TAB}{TAB}CLUSTER_{CHIP}_MAX_P = {MAX_PORT}, +{TAB}{TAB}// Only used in standalone mode (w/o OpenPiton) +{TAB}{TAB}CLUSTER_{CHIP}_RID_INIT = {chip_info._chip_offset_id}, +{TAB}{TAB}// Only used in standalone mode (w/o OpenPiton) +{TAB}{TAB}CLUSTER_{CHIP}_EID_INIT = {chip_info._chip_offset_id}, +{TAB}{TAB}// Only used in standalone mode (w/o OpenPiton) +{TAB}{TAB}CLUSTER_{CHIP}_NE = CLUSTER_{CHIP}_NX * CLUSTER_{CHIP}_NY * CLUSTER_{CHIP}_NZ, +{TAB}{TAB}// Only used in standalone mode (w/o OpenPiton) +{TAB}{TAB}CLUSTER_{CHIP}_NR = CLUSTER_{CHIP}_NE, +{TAB}{TAB}CLUSTER_{CHIP}_NVP = 2 * (CLUSTER_{CHIP}_NX * CLUSTER_{CHIP}_NY); +""" + + +def gen_multi_mesh_cluster_instant(chip_name): + CHIP = chip_name.upper() + return f""" +{TAB}smartflit_chanel_t CLUSTER_{chip_name}_endpoint_chan_in [CLUSTER_{CHIP}_NE-1:0]; +{TAB}smartflit_chanel_t CLUSTER_{chip_name}_endpoint_chan_out[CLUSTER_{CHIP}_NE-1:0]; +{TAB}smartflit_chanel_t CLUSTER_{chip_name}_inter_cluster_chan_in[CLUSTER_{CHIP}_NVP-1:0]; +{TAB}smartflit_chanel_t CLUSTER_{chip_name}_inter_cluster_chan_out[CLUSTER_{CHIP}_NVP-1:0]; +{TAB}router_event_t CLUSTER_{chip_name}_router_event[CLUSTER_{CHIP}_NR-1:0][CLUSTER_{CHIP}_MAX_P-1:0]; + +{TAB}mesh_cluster #( +{TAB}{TAB}.CLUSTER_ID({CHIP}_ID), +{TAB}{TAB}.RID_INIT(CLUSTER_{CHIP}_RID_INIT), +{TAB}{TAB}.CLUSTER_NX(CLUSTER_{CHIP}_NX), +{TAB}{TAB}.CLUSTER_NY(CLUSTER_{CHIP}_NY), +{TAB}{TAB}.CLUSTER_NZ(CLUSTER_{CHIP}_NZ), +{TAB}{TAB}.CLUSTER_NE(CLUSTER_{CHIP}_NE) +{TAB}) noc_{chip_name}( +{TAB}{TAB}.reset(reset), +{TAB}{TAB}.clk(clk), +{TAB}{TAB}.cluster_id({CHIP}_ID[CLUSTER_IDw-1:0]), +{TAB}{TAB}.endpoint_chan_in(CLUSTER_{chip_name}_endpoint_chan_in), +{TAB}{TAB}.endpoint_chan_out(CLUSTER_{chip_name}_endpoint_chan_out), +{TAB}{TAB}.inter_cluster_chan_in(CLUSTER_{chip_name}_inter_cluster_chan_in), +{TAB}{TAB}.inter_cluster_chan_out(CLUSTER_{chip_name}_inter_cluster_chan_out), +{TAB}{TAB}.router_event(CLUSTER_{chip_name}_router_event) +{TAB}); + +{TAB}assign router_event[CLUSTER_{CHIP}_RID_INIT +: CLUSTER_{CHIP}_NR] = CLUSTER_{chip_name}_router_event; +""" + + +def compute_vlink_idx(chip_info, lid, vdir_is_down): + x, y, z = convert_local_id_to_xyz(chip_info, lid) + dimx = chip_info._dim_x + dimy = chip_info._dim_y + dimz = chip_info._dim_z + + if z != 0 and z != dimz - 1: + raise ValueError(f"Error: Inter-cluster connection at Z={z} is " + \ + "invalid. It must be at either the first (0) " + \ + f"or last ({dimz-1}) position in the Z dimension.") + if z == 0 and dimz > 1 and not(vdir_is_down): + raise ValueError("Error: Routers at the first Z layer (Z=0) can" + \ + " only have a 'down' connection.") + if z == dimz - 1 and dimz > 1 and vdir_is_down: + raise ValueError(f"Error: Routers at the last Z layer (Z={dimz-1})" + \ + "can only have an 'up' connection.") + + vp = (y * dimx) + x if vdir_is_down else \ + (dimx * dimy) + (y * dimx) + x + return vp + + +def gen_multi_mesh_vertical_link_assign(noc_id=0): + is_connected = defaultdict(lambda: defaultdict(dict)) + + for chip_name, chip_info in chip_infos.items(): + # Up and Down connections account for 2 * number of routers + connections_num = chip_info.get_number_of_routers() * 2 + # Initialize the base 'connection' dictionary + for i in range(connections_num): + is_connected['OUT'][chip_name][i] = 0 + is_connected['IN'][chip_name][i] = 0 + + noc_adapters = "`ifdef PITON_MULTICHIP\n" + links_assign = "`ifndef PITON_MULTICHIP\n" + unconnected_err = "" + + for connections in iter_on_vertical_connections(chip_infos): + (src_chip, src_endp, dst_chip, dst_endp, src_dir_is_down) = connections + src_chip_info = chip_infos[src_chip] + # Compute the src vlink idx in the bunch of wires + src_vp = compute_vlink_idx(src_chip_info, int(src_endp), + src_dir_is_down) + # "Z+" credits are released on index Z_PLUS_VC_IDX + # "Z-" credits are released on Z_MIN_VC_IDX + credit_idx = Z_MIN_VC_IDX if src_dir_is_down else Z_PLUS_VC_IDX + + dst_dir_is_down = not src_dir_is_down + dst_chip_info = chip_infos[dst_chip] + # Compute the dst vlink idx in the bunch of wires + dst_vp = compute_vlink_idx(dst_chip_info, int(dst_endp), + dst_dir_is_down) + + src_dir = "down" if src_dir_is_down else "up" + dst_dir = "down" if dst_dir_is_down else "up" + + # Used with OpenPiton + noc_adapters += f"""\ +{TAB}{TAB}noc{noc_id}_inter_chip_adapter_{src_chip}_{dst_chip} {src_chip}_{dst_chip}_noc_adapter_{src_endp}_{dst_endp}( +{TAB}{TAB}{TAB}.clk(clk), +{TAB}{TAB}{TAB}.rst_n(rst_n), + +{TAB}{TAB}{TAB}.flit_wr_i(CLUSTER_{src_chip}_inter_cluster_chan_out[{src_vp}].flit_chanel.flit_wr), +{TAB}{TAB}{TAB}.flit_data_i(CLUSTER_{src_chip}_inter_cluster_chan_out[{src_vp}].flit_chanel.flit), +{TAB}{TAB}{TAB}.flit_wr_o(CLUSTER_{dst_chip}_inter_cluster_chan_in[{dst_vp}].flit_chanel.flit_wr), +{TAB}{TAB}{TAB}.flit_data_o(CLUSTER_{dst_chip}_inter_cluster_chan_in[{dst_vp}].flit_chanel.flit), + +{TAB}{TAB}{TAB}.downstream_credit_i(CLUSTER_{dst_chip}_inter_cluster_chan_out[{dst_vp}].flit_chanel.credit[{credit_idx}]), +{TAB}{TAB}{TAB}.upstream_credit_o(CLUSTER_{src_chip}_inter_cluster_chan_in[{src_vp}].flit_chanel.credit[{credit_idx}]), + +{TAB}{TAB}{TAB}.downstream_ctrl_i(CLUSTER_{dst_chip}_inter_cluster_chan_out[{dst_vp}].ctrl_chanel), +{TAB}{TAB}{TAB}.upstream_ctrl_o(CLUSTER_{src_chip}_inter_cluster_chan_in[{src_vp}].ctrl_chanel) +{TAB}{TAB}); +{TAB}{TAB}assign CLUSTER_{src_chip}_inter_cluster_chan_in[{src_vp}].flit_chanel.credit[{int(not(credit_idx))}] = 1'b0;\n +""" + # Used in standalone mode + links_assign += f"""\ +{TAB}{TAB}// {src_chip}[{src_endp}] dir {src_dir} to {dst_chip}[{dst_endp}] dir {dst_dir} +{TAB}{TAB}CLUSTER_{dst_chip}_inter_cluster_chan_in[{dst_vp}].flit_chanel.flit_wr = CLUSTER_{src_chip}_inter_cluster_chan_out[{src_vp}].flit_chanel.flit_wr; +{TAB}{TAB}CLUSTER_{dst_chip}_inter_cluster_chan_in[{dst_vp}].flit_chanel.flit = CLUSTER_{src_chip}_inter_cluster_chan_out[{src_vp}].flit_chanel.flit; +{TAB}{TAB}CLUSTER_{src_chip}_inter_cluster_chan_in[{src_vp}].flit_chanel.credit = CLUSTER_{dst_chip}_inter_cluster_chan_out[{dst_vp}].flit_chanel.credit; +{TAB}{TAB}CLUSTER_{src_chip}_inter_cluster_chan_in[{src_vp}].ctrl_chanel = CLUSTER_{dst_chip}_inter_cluster_chan_out[{dst_vp}].ctrl_chanel; +""" + is_connected['OUT'][dst_chip][dst_vp] = 1 + is_connected['IN'][src_chip][src_vp] = 1 + + noc_adapters += "`endif // PITON_MULTICHIP\n" + links_assign += "`endif // PITON_MULTICHIP\n" + + links_assign += f"\n{TAB}{TAB}// Tie to the ground unconnected vertical ports\n" + + out_connections = is_connected['OUT'] + in_connections = is_connected['IN'] + # NOTE: Veloce place and route doesn't like the grounding... + links_assign += "`ifndef VELOCE_EMULATION\n" + for dst_chip in sorted(out_connections.keys()): + for dst_vp in sorted(out_connections[dst_chip].keys()): + # Output vertical links are not assigned and their associated input + # control channel is not used + if out_connections[dst_chip][dst_vp] == 0 and \ + in_connections[dst_chip][dst_vp] == 0: + links_assign += f"""\ +{TAB}{TAB}CLUSTER_{dst_chip}_inter_cluster_chan_in[{dst_vp}] = is_grounded_{dst_chip}; +""" + links_assign += "`endif // VELOCE_EMULATION\n" + + for src_chip in sorted(in_connections.keys()): + for src_vp in sorted(in_connections[src_chip].keys()): + # Output vertical links are not assigned + if in_connections[src_chip][src_vp] == 0: + unconnected_err += f"""\ +{TAB}{TAB}if (CLUSTER_{src_chip}_inter_cluster_chan_out[{src_vp}].flit_chanel.flit_wr) begin +{TAB}{TAB}{TAB}`ERROR_UNCNT(\"{src_chip}\",{src_vp}) +{TAB}{TAB}end +""" + + grounded_signals = "" + for dst_chip in sorted(out_connections.keys()): + grounded_signals += f"{TAB}smartflit_chanel_t is_grounded_{dst_chip} = {{SMARTFLIT_CHANEL_w{{1'b0}}}};\n" + + return (links_assign, noc_adapters, unconnected_err, grounded_signals) + + +def gen_noc_localparam(): + rtl = "" + + # Generate both Buffer Depth and Payload Size Selection + # + # The goal is to generate a Verilog-string like this: + # (NOC_CHIP_ID == 0) ? + # (NOC_ID == "N1") ? `PITON_CHIPA_NOC1_BUFFER_SIZE : + # (NOC_ID == "N2") ? `PITON_CHIPA_NOC2_BUFFER_SIZE : + # `PITON_CHIPA_NOC3_BUFFER_SIZE + # : (NOC_CHIP_ID == 1) ? + # (NOC_ID == "N1") ? `PITON_CHIPB_NOC1_BUFFER_SIZE : + # (NOC_ID == "N2") ? `PITON_CHIPB_NOC2_BUFFER_SIZE : + # `PITON_CHIPA_NOC3_BUFFER_SIZE + # : (NOC_CHIP_ID == 2) ? + # ... + # so the NoC select the appropriate buffer depth (B) and payload size + # (Fpay) + + template_buffer_sel = \ + '(NOC_ID == "N1") ? `PITON__CHIP__NOC1_BUFFER_SIZE : ' + \ + '(NOC_ID == "N2") ? `PITON__CHIP__NOC2_BUFFER_SIZE : ' + \ + '`PITON__CHIP__NOC3_BUFFER_SIZE' + + template_width_sel = \ + '(NOC_ID == "N1") ? `PITON__CHIP__NOC1_WIDTH : ' + \ + '(NOC_ID == "N2") ? `PITON__CHIP__NOC2_WIDTH : ' + \ + '`PITON__CHIP__NOC3_WIDTH' + + buffer_sel = "" + width_sel = "" + noc1_buffer_depths = [] + noc2_buffer_depths = [] + noc3_buffer_depths = [] + nb_routers = 0 + min_vc = None + max_vc = None + + for i, (chip_name, chip_info) in enumerate(chip_infos.items()): + CHIPID = chip_info._chipid + CHIPNAME = chip_name.upper() + + # Not the last chip + if i < len(chip_infos.items()) - 1: + buffer_sel += f"(NOC_CHIP_ID == {CHIPID}) ? " + width_sel += f"(NOC_CHIP_ID == {CHIPID}) ? " + + buffer_sel += template_buffer_sel.replace("_CHIP_", CHIPNAME) + width_sel += template_width_sel.replace("_CHIP_", CHIPNAME) + + if i < len(chip_infos.items()) - 1: + buffer_sel += " : " + width_sel += " : " + + noc1_buffer_depths.append(chip_info.retrieve_noc_buffers_depth()[0]) + noc2_buffer_depths.append(chip_info.retrieve_noc_buffers_depth()[1]) + noc3_buffer_depths.append(chip_info.retrieve_noc_buffers_depth()[2]) + + nb_routers += chip_info.get_number_of_routers() + + min_vc = chip_info._nb_virtual_channels if min_vc is None else \ + min(min_vc, chip_info._nb_virtual_channels) + max_vc = chip_info._nb_virtual_channels if max_vc is None else \ + max(max_vc, chip_info._nb_virtual_channels) + + # Use ProNoC's LB parameter as the maximal buffer value in the 3.5D + # topology for a given physical NoC. + # Compute the maximal buffer depth across all chips for any NoC channel. + # This is used to compute the width of both the credit and credit + # initialization channels, for the whole system. + LB = \ + f'(NOC_ID == "N1") ? {max(noc1_buffer_depths)} : ' + \ + f'(NOC_ID == "N2") ? {max(noc2_buffer_depths)} : ' + \ + f'{max(noc3_buffer_depths)}' + + # Name of the ProNoC multi-chip topology + # This topology supports multiple clusters of 2D-meshes, interconnected + # vertically + topology = "MULTI_MESH" + + # Dictionary representing the main noc_localparam attributes + param_attribs = { + 'TOPOLOGY': f'"{topology}"', + 'T1': nb_routers, + 'T3': 1, + 'T4': 1, + 'V' : 2, + 'ROUTE_MODE': '\"CONVENTIONAL\"', + 'B': "PRESEL_B", + 'LB': "PRESEL_LB", + 'Fpay': "PRESEL_Fpay", + 'ROUTE_NAME': '\"DEPTH_FIRST\"', + 'PCK_TYPE': '\"MULTI_FLIT\"', + 'MIN_PCK_SIZE': 1, + 'BYTE_EN': 0, + 'SSA_EN': '\"NO\"', + "SMART_MAX": 0, + "CONGESTION_INDEX": 3, + "ESCAP_VC_MASK": "2'b01", + "VC_REALLOCATION_TYPE": '\"NONATOMIC\"', + "COMBINATION_TYPE": '\"COMB_NONSPEC\"', + "MUX_TYPE": '\"BINARY\"', + "C": 0, + "CLASS_SETTING": "{V{1'b1}}", + "DEBUG_EN": 1, + "ADD_PIPREG_AFTER_CROSSBAR": "1'b0", + "FIRST_ARBITER_EXT_P_EN": 1, + "SWA_ARBITER_TYPE": '\"RRA\"', + "WEIGHTw": 4, + 'SELF_LOOP_EN': 1, + "AVC_ATOMIC_EN": 0, + "MAX_PCK_NUM": 1000000000, + "MAX_PCK_SIZ": 16383, + "MAX_SIM_CLKs": 1000000000, + "TIMSTMP_FIFO_NUM": 16, + "CVw": "(C==0)? V : C * V", + "CAST_TYPE": '\"UNICAST\"', + "MCAST_ENDP_LIST": "'b1111" + } + + param_attribs['MAX_ROUTER'] = nb_routers + param_attribs['MAX_PORT'] = MAX_PORT + + hetero_vc_enabled = min_vc != max_vc or max_vc < 2 + param_attribs['HETERO_VC'] = int(hetero_vc_enabled) + hetero_vc = f"""'{{ +{TAB}{TAB}// VC chip local_id global_id +""" + for chip_name, chip_info in chip_infos.items(): + nr = chip_info.get_number_of_routers() + rid_int = chip_info._chip_offset_id + r = 0 + v = chip_info._nb_virtual_channels + for n in range(rid_int, rid_int + nr): + ports = range(int(param_attribs['MAX_PORT'])) + hetero_vc += f"{TAB}{TAB}// {chip_name}: r{r} R{n}\n" + hetero_vc += TAB*2 + "'{" + for port in ports: + if hetero_vc_enabled: + hetero_vc += str(v) + else: + hetero_vc += "0" + if port != ports[-1]: + hetero_vc += ", " + if n < nb_routers-1: + hetero_vc += "},\n" + else: + hetero_vc += "}\n" + r += 1 + hetero_vc += f"{TAB}}}" + param_attribs['int VC_CONFIG_TABLE[MAX_ROUTER][MAX_PORT]'] = hetero_vc + + rtl +=f""" +`ifdef NOC_LOCAL_PARAM + +{TAB}/************************************* +{TAB}* ProNoC localparams +{TAB}*************************************/ + +{TAB}// NOTE: values modified automatically by phy_noc.pl +{TAB}localparam NOC_ID = 0; +{TAB}localparam NOC_CHIP_ID = 0; + +`ifdef PITON_PRONOC +{TAB}// OpenPiton header +{TAB}`include "define.tmp.h" + +{TAB}localparam PRESEL_B = {buffer_sel}; +{TAB}localparam PRESEL_LB = {LB}; +{TAB}localparam PRESEL_Fpay = {width_sel}; +`else +{TAB}// ProNoC Standalone settings +{TAB}localparam PRESEL_B = 4; +{TAB}localparam PRESEL_LB = 4; +{TAB}localparam PRESEL_Fpay = 64; +`endif // PITON_PRONOC +""" + # Generate the list of localparam attributes + for p in param_attribs.keys(): + rtl += f"{TAB}localparam {p} = {param_attribs[p]};\n" + + lines = [] + MAX_CHIP_X = 0 + MAX_CHIP_Y = 0 + MAX_CHIP_Z = 0 + for chip_name, chip_info in chip_infos.items(): + lines.append(f"{TAB}{TAB}{chip_name.upper()}_ID = {chip_info._chipid},\n") + MAX_CHIP_X = max(MAX_CHIP_X, chip_info._dim_x) + MAX_CHIP_Y = max(MAX_CHIP_Y, chip_info._dim_y) + MAX_CHIP_Z = max(MAX_CHIP_Z, chip_info._dim_z) + + rtl += f""" +{TAB}/************************************* +{TAB}* multimesh localparams +{TAB}*************************************/ +{TAB}localparam +{"".join(lines)} +{TAB}{TAB}MAX_RID = T1, +{TAB}{TAB}RIDw = $clog2(MAX_RID), +{TAB}{TAB}CLUSTER_NUM = {len(chip_infos.items())}, +{TAB}{TAB}CLUSTER_IDw = (CLUSTER_NUM == 1) ? 1 : $clog2(CLUSTER_NUM), +{TAB}{TAB}CLUSTER_MAX_X = {str(MAX_CHIP_X)}, +{TAB}{TAB}CLUSTER_Xw = (CLUSTER_MAX_X == 1)? 1 : $clog2(CLUSTER_MAX_X), +{TAB}{TAB}CLUSTER_MAX_Y = {str(MAX_CHIP_Y)}, +{TAB}{TAB}CLUSTER_Yw = (CLUSTER_MAX_Y == 1)? 1 : $clog2(CLUSTER_MAX_Y), +{TAB}{TAB}CLUSTER_MAX_Z = {str(MAX_CHIP_Z)}, +{TAB}{TAB}CLUSTER_Zw = (CLUSTER_MAX_Z == 1)? 1 : $clog2(CLUSTER_MAX_Z); + +{TAB}typedef struct packed {{ +{TAB}{TAB}logic [CLUSTER_IDw-1:0] c; +{TAB}{TAB}logic [CLUSTER_Zw-1 :0] z; +{TAB}{TAB}logic [CLUSTER_Yw-1 :0] y; +{TAB}{TAB}logic [CLUSTER_Xw-1 :0] x; +{TAB}}} multimesh_router_addr_t; +{TAB}localparam T2 = $bits(multimesh_router_addr_t); +""" + return rtl + + +def gen_multi_mesh_topology_rtl(rtl_cluster_instant, rtl_io_assign, + rtl_vertical_links_assign, v_err, + grounded_signals): + return f""" +`include "pronoc_def.v" + +module multi_mesh +{TAB}import pronoc_pkg::*; +( +{TAB}input logic clk, +{TAB}input logic reset, +{TAB}input smartflit_chanel_t chan_in_all[NE-1:0], +{TAB}output smartflit_chanel_t chan_out_all[NE-1:0], +{TAB}output router_event_t router_event[NR-1:0][MAX_P-1:0] +); + +{TAB}// Unused Input channels are connected to ground +{grounded_signals} +{rtl_cluster_instant} + +{TAB}// Chiplet interconnect +{TAB}always_comb begin +{rtl_io_assign} +{rtl_vertical_links_assign} +{TAB}end + +`define ERROR_UNCNT(cluster, port) \\ +{TAB}$display("Error: A flit was injected into an unconnected NoC router port."); \\ +{TAB}$display("Cluster: %s, Port: %0d", cluster, port); \\ +{TAB}$display("Simulation will terminate due to this unexpected behavior."); \\ +{TAB}$finish; + +`ifdef SIMULATION +{TAB}always @(posedge clk) begin +{v_err} +{TAB}end +`endif + +endmodule +""" + + +def create_routing_modules(): + rtl = multimesh_address_encoder() + rtl += multimesh_address_decoder() + return rtl + + +def multimesh_address_decoder(): + lines = "" + for chip_name, _ in chip_infos.items(): + CHIP = chip_name.upper() + lines += f""" +{TAB}{TAB}for (int z=0; z 0: + static_icr_modules += f"{TAB}localparam MAX_ENTRY_{CHIP} = {len(up_clusters)};\n" + static_icr_modules += f"{TAB}cluster_hid_entry_t address_table[MAX_ENTRY_{CHIP}];\n" + static_icr_modules += f"{TAB}multimesh_router_addr_t endp_addr_array[MAX_ENTRY_{CHIP}];\n" + static_icr_modules += f"{TAB}wire [CLUSTER_IDw-1:0] Cmax_array_{chip_name}[MAX_ENTRY_{CHIP}];\n" + static_icr_modules += f"{TAB}wire [CLUSTER_IDw-1:0] Cmin_array_{chip_name}[MAX_ENTRY_{CHIP}];\n" + i = 0 + for c_min_id, c_max_id in up_clusters: + static_icr_modules += f"{TAB}assign Cmax_array_{chip_name}[{i}] = {c_max_id};\n" + static_icr_modules += f"{TAB}assign Cmin_array_{chip_name}[{i}] = {c_min_id};\n" + i += 1 + else: + static_icr_modules += f"{TAB}{TAB}// There are no upper chiplet. Select between local and down chiplet\n" + static_icr_modules += f"{TAB}generate \n{TAB}{TAB}case (RID)\n" + + for rid in range(chip_info.get_number_of_routers()): + static_icr_modules += f"{TAB}{TAB}{rid}: begin\n" + i = 0 + for (_, _), upper_chip in chip_info._chipid_up_to_destchip.items(): + ldest = chip_info._destchip_up_to_ldst[upper_chip, rid] + x, y, z = convert_local_id_to_xyz(chip_info, ldest) + static_icr_modules += f"{TAB}{TAB}{TAB}/* T:{upper_chip}, R:{ldest} */\n" + static_icr_modules += f"{TAB}{TAB}{TAB}assign endp_addr_array[{i}] = '{{x:{x}, y:{y}, z:{z}, c:{CHIP}_ID}};\n" + i += 1 + if not no_down_chip: + ldest = chip_info._destchip_down_to_ldst[rid] + x, y, z = convert_local_id_to_xyz(chip_info, ldest) + down_cluster = chip_info._destchip_down + static_icr_modules += f"{TAB}{TAB}{TAB}/* T:{down_cluster}, R:{ldest} */\n" + static_icr_modules += f"{TAB}{TAB}{TAB}assign local_cluster_endp_addr_down_dir = '{{x:{x}, y:{y}, z:{z}, c:{CHIP}_ID}};\n" + static_icr_modules += f"{TAB}{TAB}end //{rid}\n" + static_icr_modules += f"{TAB}{TAB}endcase\n{TAB}endgenerate\n" + + if len(up_clusters) > 0: + static_icr_modules += f""" +{TAB}always_comb begin +{TAB}{TAB}local_cluster_endp_addr_up_dir = 0; +{TAB}{TAB}up_dir_sel = 1'b0; +{TAB}{TAB}for (int i = 0; i < MAX_ENTRY_{CHIP}; i++) begin +{TAB}{TAB}{TAB}if (Cmin_array_{chip_name}[i] <= dest_address.c && +{TAB}{TAB}{TAB} dest_address.c <= Cmax_array_{chip_name}[i]) begin +{TAB}{TAB}{TAB}{TAB}local_cluster_endp_addr_up_dir = endp_addr_array[i]; +{TAB}{TAB}{TAB}{TAB}up_dir_sel = 1'b1; +{TAB}{TAB}{TAB}end +{TAB}{TAB}end +{TAB}end +""" + else: + static_icr_modules += f""" +{TAB}always_comb begin +{TAB}{TAB}local_cluster_endp_addr_up_dir = 0; +{TAB}{TAB}up_dir_sel = 1'b0; +{TAB}end +""" + not_dynamic += f"{TAB}end\n" + static_icr_modules += f""" +{TAB}assign local_cluster_endp_addr = +{TAB}{TAB}(dest_address.c == current_cluster_id) ? dest_address : +{TAB}{TAB}(up_dir_sel) ? local_cluster_endp_addr_up_dir : +{TAB}{TAB}local_cluster_endp_addr_down_dir; +endmodule +""" + rtl = f""" +`include "pronoc_def.v" +module global_id_to_local_cluster_endp +{TAB}import pronoc_pkg::*; +#( +`ifndef DYNAMIC_CLUSTER_INIT +{TAB}parameter CLUSTER_ID = 0, +{TAB}parameter RID = 0 +`endif +)( +`ifdef DYNAMIC_CLUSTER_INIT +{TAB}input cluster_hid_entry_t address_table[DYN_ICRT_MAX_ENTRY], +{TAB}input multimesh_router_addr_t local_cluster_endp_addr_down_dir, +{TAB}input logic [CLUSTER_IDw-1:0] current_cluster_id, +`endif +{TAB}input multimesh_router_addr_t dest_address, +{TAB}output multimesh_router_addr_t local_cluster_endp_addr, +{TAB}output logic up_dir_sel +); + +`ifndef DYNAMIC_CLUSTER_INIT +{TAB}generate +{not_dynamic} +{TAB}endgenerate +`else +{TAB}dynamic_icr icr( +{TAB}{TAB}.dest_address(dest_address), +{TAB}{TAB}.local_cluster_endp_addr(local_cluster_endp_addr), +{TAB}{TAB}.local_cluster_endp_addr_down_dir(local_cluster_endp_addr_down_dir), +{TAB}{TAB}.current_cluster_id(current_cluster_id), +{TAB}{TAB}.address_table(address_table), +{TAB}{TAB}.up_dir_sel(up_dir_sel) +{TAB}); +`endif +endmodule + +`ifdef DYNAMIC_CLUSTER_INIT +module dynamic_icr +{TAB}import pronoc_pkg::*; +( +{TAB}input multimesh_router_addr_t dest_address, +{TAB}output multimesh_router_addr_t local_cluster_endp_addr, +{TAB}input multimesh_router_addr_t local_cluster_endp_addr_down_dir, +{TAB}input logic [CLUSTER_IDw-1:0] current_cluster_id, +{TAB}input cluster_hid_entry_t address_table[DYN_ICRT_MAX_ENTRY], +{TAB}output logic up_dir_sel +); + +{TAB}multimesh_router_addr_t local_cluster_endp_addr_up_dir; + +{TAB}always_comb begin +{TAB}{TAB}local_cluster_endp_addr_up_dir = 0; +{TAB}{TAB}up_dir_sel = 1'b0; +{TAB}{TAB}for (int i = 0; i < DYN_ICRT_MAX_ENTRY; i++) begin +{TAB}{TAB}{TAB}if (address_table[i].valid) begin +{TAB}{TAB}{TAB}{TAB}if (address_table[i].Cmin <= dest_address.c && +{TAB}{TAB}{TAB}{TAB} dest_address.c < address_table[i].Cmax) begin +{TAB}{TAB}{TAB}{TAB}{TAB}local_cluster_endp_addr_up_dir = address_table[i].endp_addr; +{TAB}{TAB}{TAB}{TAB}{TAB}up_dir_sel = 1'b1; +{TAB}{TAB}{TAB}{TAB}end +{TAB}{TAB}{TAB}end +{TAB}{TAB}end +{TAB}end + +{TAB}assign local_cluster_endp_addr = +{TAB}{TAB}(dest_address.c == current_cluster_id) ? dest_address : +{TAB}{TAB}(up_dir_sel) ? local_cluster_endp_addr_up_dir : +{TAB}{TAB}local_cluster_endp_addr_down_dir; +endmodule + +module dynamic_hids_per_router +{TAB}import pronoc_pkg::*; +( +{TAB}input logic clk, +{TAB}input logic reset, +{TAB}output multimesh_router_addr_t local_cluster_endp_addr_down_dir, +{TAB}output logic [CLUSTER_IDw-1:0] current_cluster_id, +{TAB}output cluster_hid_entry_t address_table[DYN_ICRT_MAX_ENTRY], +{TAB}input program_port_t program_port +); + +{TAB}always_ff @(posedge clk or posedge reset) begin +{TAB}{TAB}if (reset) begin +{TAB}{TAB}{TAB}local_cluster_endp_addr_down_dir = 0; +{TAB}{TAB}{TAB}foreach (address_table[i]) begin +{TAB}{TAB}{TAB}{TAB}address_table[i].valid <= 1'b0; +{TAB}{TAB}{TAB}{TAB}current_cluster_id <= 0; +{TAB}{TAB}{TAB}end +{TAB}{TAB}end else begin +{TAB}{TAB}{TAB}if (program_port.data.valid) begin +{TAB}{TAB}{TAB}{TAB}if (!program_port.down_sel) begin +{TAB}{TAB}{TAB}{TAB}{TAB}address_table[program_port.addr] <= program_port.data; +{TAB}{TAB}{TAB}{TAB}{TAB}current_cluster_id <= program_port.current_cluster_id; +{TAB}{TAB}{TAB}{TAB}end else begin +{TAB}{TAB}{TAB}{TAB}{TAB}local_cluster_endp_addr_down_dir = program_port.data.endp_addr; +{TAB}{TAB}{TAB}{TAB}end +{TAB}{TAB}{TAB}end +{TAB}{TAB}end +{TAB}end +endmodule + +`else +{static_icr_modules} +`endif +""" + return rtl diff --git a/mpsoc/script/multimesh/run_test.sh b/mpsoc/script/multimesh/run_test.sh new file mode 100755 index 0000000..31a3ec8 --- /dev/null +++ b/mpsoc/script/multimesh/run_test.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# Enable strict mode +set -euo pipefail + +# Get the script's full and directory path +SCRPT_FULL_PATH=$(realpath "${BASH_SOURCE[0]}") +SCRPT_DIR_PATH=$(dirname "$SCRPT_FULL_PATH") + +# Define root and work directories +root=$(realpath "$SCRPT_DIR_PATH/../..") +work="$root/../mpsoc_work/multi_mesh" + +# Generate NoC configuration from YAML +CONFIG_FILE="$PITON_ROOT/configs/multi_chip/2d5_36cores.yaml" + +echo "[INFO] This script generates a MultiMesh NoC using the configuration file: $CONFIG_FILE." +echo "[INFO] It then runs a Random Uniform traffic test on the generated NoC." +echo "[INFO] To test a different NoC configuration, modify the CONFIG_FILE variable in this script." +echo "[INFO] To adjust synthetic traffic settings (e.g., traffic pattern, number of injected packets, packet size, etc ..), modify the parameters in src/sim_param.sv. +" + +echo "work: $work" +echo "SCRIPT_DIR_PATH: $SCRPT_DIR_PATH" + +# Export necessary environment variables +export WORK_MMESH="$work" +export SOURCE_DIR="$SCRPT_DIR_PATH/src" + +# Ensure required tools exist +command -v realpath >/dev/null 2>&1 || { echo "Error: realpath is required but not installed." >&2; exit 1; } +command -v perl >/dev/null 2>&1 || { echo "Error: perl is required but not installed." >&2; exit 1; } + + +# Change to script directory +cd "$SCRPT_DIR_PATH" + + +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "Error: NoC config file not found at $CONFIG_FILE" + exit 1 +fi + +# NOTE: This generates by default the multi-mesh modules in $root/rtl/src_multi_mesh/build +python3 $PITON_ROOT/piton/tools/bin/piton_arch.py --filename "$CONFIG_FILE" --gen_sv + +# Copy generated parameter file, ensuring the source exists +SRC_FILE="$root/rtl/src_multi_mesh/build/noc_localparam.v" +DEST_FILE="$root/rtl/src_noc/noc_localparam.v" +if [[ -f "$SRC_FILE" ]]; then + cp "$SRC_FILE" "$DEST_FILE" +else + echo "Error: Source file $SRC_FILE not found." + exit 1 +fi + +# Create working directory if it does not exist +mkdir -p "$work" + +# Source QuestaSim environment script +QUESTA_ENV_SCRIPT="$work/../Questa_20.4.sh" +if [[ -f "$QUESTA_ENV_SCRIPT" ]]; then + source "$QUESTA_ENV_SCRIPT" +else + echo "Warning: QuestaSim environment script not found at $QUESTA_ENV_SCRIPT. Simulation may fail." +fi + +# Move to working directory and run ModelSim script +cd "$work" +if [[ ! -f "$SCRPT_DIR_PATH/src/model.tcl" ]]; then + echo "Error: ModelSim script not found at $SCRPT_DIR_PATH/src/model.tcl" + exit 1 +fi + +command -v vsim >/dev/null 2>&1 || { echo "Error: vsim (QuestaSim) is required but not installed." >&2; exit 1; } + +vsim -do "$SCRPT_DIR_PATH/src/model.tcl" + +# Return to original directory +cd - + diff --git a/mpsoc/script/multimesh/src/file_list.f b/mpsoc/script/multimesh/src/file_list.f new file mode 100644 index 0000000..0e60bd1 --- /dev/null +++ b/mpsoc/script/multimesh/src/file_list.f @@ -0,0 +1,6 @@ ++incdir+./ ++incdir+./../../../rtl/src_noc/ +-F ../../../rtl/src_noc/noc_filelist.f +-F ../../../rtl/src_multi_mesh/multi_mesh.flist +-F ../../../rtl/src_modelsim/filelist.f +-sv ../../../rtl/src_modelsim/testbench_noc.sv diff --git a/mpsoc/script/multimesh/src/model.tcl b/mpsoc/script/multimesh/src/model.tcl new file mode 100644 index 0000000..25f1e97 --- /dev/null +++ b/mpsoc/script/multimesh/src/model.tcl @@ -0,0 +1,33 @@ +#!/usr/bin/tclsh + +transcript on + +if {![info exists env(WORK_MMESH)]} { + puts "Error: WORK environment variable is not set." + exit 1 +} + +if {![info exists env(SOURCE_DIR)]} { + puts "Error: SOURCE_DIR environment variable is not set." + exit 1 +} + +set rtl_work $env(WORK_MMESH)/rtl_work +set src_dir $env(SOURCE_DIR) + +if {[file exists $rtl_work]} { + vdel -lib $rtl_work -all +} +vlib $rtl_work +vmap work $rtl_work + + +vlog +define+SIMULATION+MULTI_MESH_ASSERTIONS +acc=rn -F $src_dir/file_list.f + +vsim -t 1ps -L $rtl_work -L work -voptargs="+acc" testbench_noc + +add wave * +view structure +view signals +run -all +quit diff --git a/mpsoc/script/multimesh/src/sim_param.sv b/mpsoc/script/multimesh/src/sim_param.sv new file mode 100644 index 0000000..92a5673 --- /dev/null +++ b/mpsoc/script/multimesh/src/sim_param.sv @@ -0,0 +1,34 @@ + +// simulation parameter setting + +`ifdef INCLUDE_SIM_PARAM + localparam + TRAFFIC="RANDOM", // "NEIGHBOR", "BIT_COMPLEMENT", "TRANSPOSE2", "RANDOM", "CUSTOM", "HOTSPOT" + PCK_SIZ_SEL="random-range", + AVG_LATENCY_METRIC= "HEAD_2_TAIL", + // Simulation min/max packet size + // NOTE: The injected packet take a size randomly selected between min and max values + MIN_PACKET_SIZE=5, + MAX_PACKET_SIZE=5, + STOP_PCK_NUM=2000, // simulation stops when #STOP_PCK_NUM packets are injected in the NoC + STOP_SIM_CLK=1000; // simulation stops when #STOP_SIM_CLK cycles are passed + + // parameters for setting hotspot traffic pattern + localparam HOTSPOT_NODE_NUM = 0; + hotspot_t hotspot_info [0:0]; + + // parameters for setting point-to-point custom traffic pattern + localparam CUSTOM_NODE_NUM = 0; + wire [NEw-1:0] custom_traffic_t[NE-1:0]; + wire [NE-1:0] custom_traffic_en; + + localparam MCAST_TRAFFIC_RATIO = 0; + localparam MCAST_PCK_SIZ_MAX = 0; + localparam MCAST_PCK_SIZ_MIN = 0; + + localparam DISCRETE_PCK_SIZ_NUM = 1; + rnd_discrete_t rnd_discrete [DISCRETE_PCK_SIZ_NUM-1:0]; + + // flit injection ratio in % + parameter INJRATIO=50; +`endif diff --git a/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh b/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh old mode 100644 new mode 100755 index 246e0f1..4b4b0dc --- a/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh +++ b/mpsoc/script/phy_noc_gen/OpenPiton_nocs_gen.sh @@ -1,8 +1,11 @@ #!/bin/bash # This script generates three physical NoCs for OpenPiton using ProNoC RTL code. +# Depending on the arguments given, the script will either use the Fmesh or the +# Multi-mesh topology. # Each physical NoC (phynoc) is configured with unified module and parameter names. -# The NoC number is appended to parameters, functions, and module names to ensure uniqueness. +# The NoC number and the chip name are appended to parameters, functions, and +# module names to ensure uniqueness. # Get the full path of the script SCRIPT_FULL_PATH=$(realpath "${BASH_SOURCE[0]}") @@ -10,6 +13,8 @@ SCRIPT_DIR_PATH=$(dirname "$SCRIPT_FULL_PATH") # OpenPiton target NoC directory op_nocs_dir="$SCRIPT_DIR_PATH/../../rtl/src_openpiton" +multimesh_nocs_dir="$SCRIPT_DIR_PATH/../../rtl/src_multi_mesh" +build_multimesh_nocs_dir="$SCRIPT_DIR_PATH/../../rtl/src_multi_mesh/build" # ProNoC RTL dir pronoc_dir="$SCRIPT_DIR_PATH/../../rtl/src_noc" @@ -17,24 +22,127 @@ pronoc_dir="$SCRIPT_DIR_PATH/../../rtl/src_noc" # Script to create physical NoCs phy_noc_gen="$SCRIPT_DIR_PATH/phy_noc.pl" -cp "$op_nocs_dir/piton_wrapper.sv" "$pronoc_dir/piton_wrapper.sv" -mv "$pronoc_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v.tmp" -cp "$op_nocs_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v" +# Build directory +phy_nocs_out_dir="$op_nocs_dir/nocs" + +# Depth-First NoC Config File +dp_config_file="" + +# Optional path pointing on an intermediate ProNoC source directory +intermediate_pronoc_dir="$pronoc_dir" + +# Parse script options +while [[ $# -gt 0 ]]; do + case "$1" in + --custom_phy_nocs_out_dir) + phy_nocs_out_dir="$2" + shift 2 + ;; + --config-file) + dp_config_file="$2" + shift 2 + ;; + --intermediate-dir) + intermediate_pronoc_dir="$2" + build_multimesh_nocs_dir="$intermediate_pronoc_dir/../src_multi_mesh/build" + shift 2 + ;; + *) + echo "Invalid Option: $1" >&2 + exit 1 + ;; + esac +done + +# Check if intermediate_pronoc_dir and pronoc_dir points to different paths +# If that is the case, copy all necessary files to compile the design in this +# intermediate directory +if [ ! "$intermediate_pronoc_dir" -ef "$pronoc_dir" ]; then + mkdir -p "$intermediate_pronoc_dir" + cp -r "$pronoc_dir/"* "$intermediate_pronoc_dir" + cp "$pronoc_dir/../pronoc_def.v" "$intermediate_pronoc_dir/../" + cp "$pronoc_dir/../arbiter.v" "$intermediate_pronoc_dir/../" + cp "$pronoc_dir/../main_comp.v" "$intermediate_pronoc_dir/../" +fi + +# If Multi-mesh is used, launch the generation of the sources +if [ -n "$dp_config_file" ]; then + python3 $PITON_ROOT/piton/tools/bin/piton_arch.py --filename "$dp_config_file" --gen_sv --build_dir "$build_multimesh_nocs_dir" + if [ $? -ne 0 ]; then + echo "NoC generation from $dp_config_file failed" + exit 1 + fi +fi + +# If Multi-mesh is used, copy the related sources in the main source directory +if [ -n "$dp_config_file" ]; then + cp "$multimesh_nocs_dir/mesh_cluster.sv" "$intermediate_pronoc_dir/mesh_cluster.sv" + cp "$build_multimesh_nocs_dir/multi_mesh_icr.sv" "$intermediate_pronoc_dir/multi_mesh_icr.sv" + cp "$build_multimesh_nocs_dir/multi_mesh_routing.sv" "$intermediate_pronoc_dir/multi_mesh_routing.sv" +fi + +# If the ProNoC sources are compiled in-place, save the previous noc_localparam file +if [ "$intermediate_pronoc_dir" -ef "$pronoc_dir" ]; then + mv "$pronoc_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v.tmp" +fi + +# Copy this module, needed for both Fmesh/Multi-mesh wrapper +cp "$op_nocs_dir/piton_tail_hdr_detect.sv" "$intermediate_pronoc_dir/piton_tail_hdr_detect.sv" + +# Copy either the Multi-mesh or the Fmesh wrapper/noc_localparam, depending on the option given +if [ -n "$dp_config_file" ]; then + cp "$multimesh_nocs_dir/piton_wrapper.sv" "$intermediate_pronoc_dir/piton_wrapper.sv" + cp "$build_multimesh_nocs_dir/noc_localparam.v" "$intermediate_pronoc_dir/noc_localparam.v" +else + cp "$op_nocs_dir/piton_wrapper.sv" "$intermediate_pronoc_dir/piton_wrapper.sv" + cp "$op_nocs_dir/noc_localparam.v" "$intermediate_pronoc_dir/noc_localparam.v" +fi + +# Base values for Fmesh topology +chips_name=('base') +chips_id=('0') + +if [ -n "$dp_config_file" ]; then + # Retrieve the list of chips name and chipid + list_chips_name=$(python3 $PITON_ROOT/piton/tools/bin/piton_arch.py --filename "$dp_config_file" --list_chips_name) + list_chips_id=$(python3 $PITON_ROOT/piton/tools/bin/piton_arch.py --filename "$dp_config_file" --list_chips_id) + # Convert bash strings into arrays + read -ra chips_name <<< "$list_chips_name" + read -ra chips_id <<< "$list_chips_id" +fi # Loop to generate three physical NoCs IN="" LIST="" -for i in {1..3}; do - mkdir -p "$op_nocs_dir/nocs/noc$i" - perl "$phy_noc_gen" "N$i" "$op_nocs_dir/nocs/noc$i" - IN+="+incdir+./noc${i}\n" - LIST+="-F ./noc${i}/noc_filelist_N${i}.f\n" - LIST+="./noc${i}/piton_wrapper_N${i}.sv\n" +for i in "${!chips_name[@]}"; do + chip_name="${chips_name[i]}" + chip_id="${chips_id[i]}" + for i in {1..3}; do + mkdir -p "$phy_nocs_out_dir/${chip_name}/noc$i" + perl "$phy_noc_gen" "N${i}" "$phy_nocs_out_dir/$chip_name/noc$i" "$intermediate_pronoc_dir" "${chip_name}" "${chip_id}" + IN+="+incdir+./$chip_name/noc${i}\n" + LIST+="-F ./$chip_name/noc${i}/noc_filelist_${chip_name}_N${i}.f\n" + LIST+="./$chip_name/noc${i}/piton_wrapper_${chip_name}_N${i}.sv\n" + LIST+="./$chip_name/noc${i}/piton_tail_hdr_detect_${chip_name}_N${i}.sv\n" + if [ -n "$dp_config_file" ]; then + LIST+="./$chip_name/noc${i}/mesh_cluster_${chip_name}_N${i}.sv\n" + LIST+="./$chip_name/noc${i}/multi_mesh_icr_${chip_name}_N${i}.sv\n" + LIST+="./$chip_name/noc${i}/multi_mesh_routing_${chip_name}_N${i}.sv\n" + fi + done done # Clean up and restore the original file -rm "$pronoc_dir/piton_wrapper.sv" -mv "$pronoc_dir/noc_localparam.v.tmp" "$pronoc_dir/noc_localparam.v" +if [ "$intermediate_pronoc_dir" -ef "$pronoc_dir" ]; then + rm "$pronoc_dir/piton_wrapper.sv" + rm "$pronoc_dir/piton_tail_hdr_detect.sv" + if [ -n "$dp_config_file" ]; then + rm "$pronoc_dir/mesh_cluster.sv" + rm "$pronoc_dir/multi_mesh_icr.sv" + rm "$pronoc_dir/multi_mesh_routing.sv" + fi + mv "$pronoc_dir/noc_localparam.v.tmp" "$pronoc_dir/noc_localparam.v" +fi # Generate the file list for physical NoCs -printf "${IN}$LIST" > "$op_nocs_dir/nocs/Flist.pronoc" +printf "${IN}$LIST" > "$phy_nocs_out_dir/Flist.pronoc" diff --git a/mpsoc/script/phy_noc_gen/phy_noc.pl b/mpsoc/script/phy_noc_gen/phy_noc.pl index 90a0a62..f156ff9 100644 --- a/mpsoc/script/phy_noc_gen/phy_noc.pl +++ b/mpsoc/script/phy_noc_gen/phy_noc.pl @@ -23,10 +23,12 @@ use Cwd 'realpath'; my $dirname = dirname(__FILE__); -my $noc_dir = realpath("$dirname/../../rtl/src_noc"); my $noc_id = $ARGV[0]; -my $out_dir= $ARGV[1]; +my $out_dir = $ARGV[1]; +my $noc_dir = $ARGV[2]; +my $chip_name = $ARGV[3]; +my $chip_id = $ARGV[4]; if (!defined $noc_id) { print "Error: No NoC_ID is given. You need to give the NoC ID as input. All RTL modules names and parameters are appended with [NOC_ID]. @@ -35,6 +37,14 @@ } $out_dir = "./$noc_id" if(!defined $out_dir); +if (!defined $noc_dir) { + $noc_dir = realpath("$dirname/../../rtl/src_noc"); +} + +# Build suffix for replacements +my $suffix = "${noc_id}"; +$suffix = "${chip_name}_" . $suffix if defined $chip_name; + #check that NoC ID is valid verilog syntac #Identifiers may contain alphabetic characters, numeric characters, the underscore, and the dollar sign (a-z A-Z 0-9 _ $ ) if ($noc_id =~ /[^a-zA-Z0-9_\$]+/){ @@ -47,11 +57,10 @@ #Note that white spaces in replace keys are autumatically translated to \s* my %replace = ( - 'import pronoc_pkg::*;' => "import pronoc_pkg_${noc_id}::*;", - 'noc_localparam.v' => "noc_localparam_${noc_id}.v", - 'topology_localparam.v' => "topology_localparam_${noc_id}.v", - 'pronoc_pkg' => "pronoc_pkg_${noc_id}", - 'NOC_ID = 0' => "NOC_ID=\"$ARGV[0]\"", + 'import pronoc_pkg::*;' => "import pronoc_pkg_${suffix}::*;", + 'noc_localparam.v' => "noc_localparam_${suffix}.v", + 'topology_localparam.v' => "topology_localparam_${suffix}.v", + 'pronoc_pkg' => "pronoc_pkg_${suffix}" ); @@ -108,17 +117,9 @@ my @params = split /,\s*/, $declaration; foreach my $param (@params) { # Extract the parameter name while skipping 'int', 'signed', 'unsigned' - if ($param =~ /^\s*(?:int|signed|unsigned)?\s*(\w+)/) { - my $param_name = $1; - $param_name =~ s/^\s+|\s+$//g; # Trim spaces - $param_name =~ s/[,;)\]\s]+$//g; # Strip trailing punctuation/whitespace - # Check if valid identifier (standard or escaped) - if ($param_name =~ /^(?:[a-zA-Z_]\w*$|\\\S+)$/) { - push @param_list, $param_name; - } else { - #print "Ignore: \"$param_name\"\n"; - } - } + if ($param =~ /^\s*(?:int|signed|unsigned)?\s*([a-zA-Z_]\w*)/) { + push @param_list, $1; + } } } } @@ -136,8 +137,22 @@ $file_content =~ s/"(?:[^"\\]|\\.)*"//g; # Find all structs while ($file_content =~ /typedef\s+struct\s+packed\s*{.*?}\s*(\w+)\s*;/sg) { - my $struct_name = $1; - push @replaces, $struct_name; + my $struct_name = $1; + push @replaces, $struct_name; + } + + open $fh, '<', "$noc_dir/noc_localparam.v" or die "Cannot open file noc_localparam.v: $!\n"; + $file_content = do { local $/; <$fh> }; + close $fh; + # Remove single-line and multi-line comments + $file_content =~ s{//.*$}{}mg; # Remove single-line comments + $file_content =~ s{/\*.*?\*/}{}sg; # Remove multi-line comments + # Remove content within quotes + $file_content =~ s/"(?:[^"\\]|\\.)*"//g; + # Find all structs + while ($file_content =~ /typedef\s+struct\s+packed\s*{.*?}\s*(\w+)\s*;/sg) { + my $struct_name = $1; + push @replaces, $struct_name; } @@ -165,18 +180,18 @@ my $after = qr/[%!~,=><:\/\s;\[\]\(\)\{\}\+\-\*\\\^']/; # Compile module replacement regex -my %module_replacements = map { $_ => "${_}_$noc_id" } @module_names; +my %module_replacements = map { $_ => "${_}_${suffix}" } @module_names; my $module_regex = join '|', map { quotemeta } @module_names; # Compile file replacement regex my %file_replacements = map { my ($file_name, $extension) = /^(.+)\.(\w+)$/; - $_ => "${file_name}_${noc_id}.$extension" + $_ => "${file_name}_${suffix}.$extension" } @files; my $file_regex = join '|', map { quotemeta } @files; # Compile key replacement regex -my %key_replacements = map { $_ => "${_}_${noc_id}" } @replaces; +my %key_replacements = map { $_ => "${_}_${suffix}" } @replaces; my $key_regex = join '|', map { quotemeta } @replaces; # Compile replace hash regex (spaces become \s*) @@ -197,7 +212,7 @@ foreach my $file (@files) { #print "$file\n"; my ($file_name, $extension) = $file =~ /^(.+)\.(\w+)$/; - my $output_filename = "$out_dir/${file_name}_${noc_id}.$extension"; + my $output_filename = "$out_dir/${file_name}_${suffix}.$extension"; open(my $input_fh, '<', "$noc_dir/$file") or die "Could not open file '$file' $!"; @@ -219,6 +234,13 @@ # Replace file names $line =~ s/($file_regex)/$file_replacements{$1}/g; + # Replace NOC_ID (handle space around '=') + $line =~ s/NOC_ID\s*=\s*0/NOC_ID = "$ARGV[0]"/g; + + if (defined $chip_id) { + $line =~ s/NOC_CHIP_ID\s*=\s*0/NOC_CHIP_ID = $chip_id/g; + } + # Replace keys with boundary checks #$line =~ s/($before)($key_regex)($after)/$1$key_replacements{$2}$3/g; while ($line =~ s/($before)($key_regex)($after)/$1$key_replacements{$2}$3/g) {} From 1fd0c193249cdf894d83f92687021fcc5d045826 Mon Sep 17 00:00:00 2001 From: amonemi Date: Sun, 30 Nov 2025 01:39:50 +0100 Subject: [PATCH 102/107] fix verilator width missmatch warning --- mpsoc/perl_gui/lib/perl/widget3.pl | 9 +++++++-- mpsoc/rtl/src_noc/inout_ports.sv | 2 +- mpsoc/rtl/src_noc/pronoc_pkg.sv | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mpsoc/perl_gui/lib/perl/widget3.pl b/mpsoc/perl_gui/lib/perl/widget3.pl index daa322f..03a7b79 100755 --- a/mpsoc/perl_gui/lib/perl/widget3.pl +++ b/mpsoc/perl_gui/lib/perl/widget3.pl @@ -1748,8 +1748,13 @@ sub file_edit_tree { sub run_cmd_in_back_ground { my ($command, $stdout_file, $stderr_file) = @_; chomp $command; #remove newline - my $cmd =(defined $stdout_file) ? "$command 1>$stdout_file 2>$stderr_file" : "$command"; - my $proc = Proc::Background->new($cmd); + + my $proc = (defined $stdout_file)? + Proc::Background->new({ + stdout => $stdout_file, + stderr => $stderr_file, + },$command) : Proc::Background->new($command); + while ($proc->alive) { while (Gtk3::events_pending) { Gtk3::main_iteration; diff --git a/mpsoc/rtl/src_noc/inout_ports.sv b/mpsoc/rtl/src_noc/inout_ports.sv index a28c7c4..4b4a6f3 100755 --- a/mpsoc/rtl/src_noc/inout_ports.sv +++ b/mpsoc/rtl/src_noc/inout_ports.sv @@ -397,7 +397,7 @@ module output_vc_status #( cand_vc_ld_next = cand_vc; if(cand_wr_vc_en) cand_vc_ld_next = cand_vc_next; // For Depth-First, only inject on VC0 (Z-) - if (IS_MULTI_MESH) cand_vc_ld_next = 2'd1; + if (IS_MULTI_MESH) cand_vc_ld_next = 'd1; end endmodule diff --git a/mpsoc/rtl/src_noc/pronoc_pkg.sv b/mpsoc/rtl/src_noc/pronoc_pkg.sv index 9f2d24f..4243e4c 100644 --- a/mpsoc/rtl/src_noc/pronoc_pkg.sv +++ b/mpsoc/rtl/src_noc/pronoc_pkg.sv @@ -324,9 +324,9 @@ package pronoc_pkg; logic [V-1:0] vc_num; begin vc_num = - (HETERO_VC == 0) ? V : - (HETERO_VC == 1) ? VC_CONFIG_TABLE [router_id][0] : - VC_CONFIG_TABLE [router_id][router_port_num]; + (HETERO_VC == 0) ? V'(V) : + (HETERO_VC == 1) ? V'(VC_CONFIG_TABLE [router_id][0]) : + V'(VC_CONFIG_TABLE [router_id][router_port_num]); hetero_ovc_unary = '0; // initialize to zero for (i = 0; i < vc_num; i = i + 1) begin hetero_ovc_unary[i] = 1'b1; From 46ecfc392dc2eb72965326df4e772f6e04a7a2de Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 11 Dec 2025 19:02:35 +0100 Subject: [PATCH 103/107] change pronoc icon --- ProNoC.png | Bin 0 -> 821835 bytes mpsoc/perl_gui/icons/ProNoC.png | Bin 8509 -> 27461 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 ProNoC.png mode change 100755 => 100644 mpsoc/perl_gui/icons/ProNoC.png diff --git a/ProNoC.png b/ProNoC.png new file mode 100644 index 0000000000000000000000000000000000000000..61295d52f8232d93d12f1b1a9275471d49259cb7 GIT binary patch literal 821835 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

mgm>*qP^2{H>5y`anZm7nc!UGD4tae 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≠Xnd+2#rrXSICi0o; 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

j^$l=n=<{9HDDBl6}r-|@$P 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⋙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Ⓢ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

-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 rFSQA Date: Mon, 15 Dec 2025 18:10:13 +0100 Subject: [PATCH 104/107] add missing parameter in openpiton NoC gen --- mpsoc/rtl/src_openpiton/noc_localparam.v | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mpsoc/rtl/src_openpiton/noc_localparam.v b/mpsoc/rtl/src_openpiton/noc_localparam.v index a286697..3d959d3 100644 --- a/mpsoc/rtl/src_openpiton/noc_localparam.v +++ b/mpsoc/rtl/src_openpiton/noc_localparam.v @@ -16,6 +16,7 @@ localparam LB=16; localparam ROUTE_NAME="DOR"; + localparam ROUTE_MODE="LOOKAHEAD"; localparam PCK_TYPE="MULTI_FLIT"; localparam MIN_PCK_SIZE=1; localparam BYTE_EN=0; @@ -36,11 +37,11 @@ localparam SELF_LOOP_EN=1; localparam AVC_ATOMIC_EN=0; localparam CLASS_SETTING={V{1'b1}}; - localparam CVw=(C==0)? V : C * V; - localparam HETERO_VC=0; - localparam MAX_ROUTER=1; - localparam MAX_PORT=1; - localparam int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]='{'{0}}; + localparam CVw=(C==0)? V : C * V; + localparam HETERO_VC=0; + localparam MAX_ROUTER=1; + localparam MAX_PORT=1; + localparam int VC_CONFIG_TABLE [MAX_ROUTER][MAX_PORT]='{'{0}}; localparam Fpay= (NOC_ID=="N1") ? `PITON_NOC1_WIDTH : From dbf195abc118af7efc91192753c1eeb43737a402 Mon Sep 17 00:00:00 2001 From: amonemi Date: Fri, 13 Mar 2026 16:16:07 +0100 Subject: [PATCH 105/107] Remove duplicate common files from filelist in PhyNoC generation --- mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh b/mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh index e660b58..e8ec66d 100644 --- a/mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh +++ b/mpsoc/script/phy_noc_gen/Ambachi_nocs_gen.sh @@ -18,7 +18,7 @@ pronoc_dir="$SCRIPT_DIR_PATH/../../rtl/src_noc" phy_noc_gen="$SCRIPT_DIR_PATH/phy_noc.pl" cp "$op_nocs_dir/chi_wrapper.sv" "$pronoc_dir/chi_wrapper.sv" -mv "$pronoc_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v.tmp" +mv -f "$pronoc_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v.tmp" cp "$op_nocs_dir/noc_localparam.v" "$pronoc_dir/noc_localparam.v" # Loop to generate three physical NoCs @@ -32,8 +32,15 @@ for i in "${arr[@]}"; do IN+="+incdir+./noc_${i}\n" LIST+="-F ./noc_${i}/noc_filelist_${i}.f\n" LIST+="./noc_${i}/chi_wrapper_${i}.sv\n" + #remove common files from noc_filelist_${i}.f + sed -i '/arbiter.v/d' "$op_nocs_dir/nocs/noc_$i/noc_filelist_${i}.f" + sed -i '/main_comp.v/d' "$op_nocs_dir/nocs/noc_$i/noc_filelist_${i}.f" done +# Add common files to the file list +LIST+="./arbiter.v\n" +LIST+="./main_comp.v\n" + # Clean up and restore the original file rm "$pronoc_dir/chi_wrapper.sv" mv "$pronoc_dir/noc_localparam.v.tmp" "$pronoc_dir/noc_localparam.v" From 8106ed020c7557e4a7f9a416e2ae57d89fde4603 Mon Sep 17 00:00:00 2001 From: amonemi Date: Thu, 23 Apr 2026 17:53:18 +0200 Subject: [PATCH 106/107] fix verialtor bug in chi_wrapper --- mpsoc/rtl/src_ambachi/chi_wrapper.sv | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mpsoc/rtl/src_ambachi/chi_wrapper.sv b/mpsoc/rtl/src_ambachi/chi_wrapper.sv index 8d4f819..60aee8b 100644 --- a/mpsoc/rtl/src_ambachi/chi_wrapper.sv +++ b/mpsoc/rtl/src_ambachi/chi_wrapper.sv @@ -89,16 +89,16 @@ module chi_to_pronoc_wrapper ( //credit release should be asserted externaly via register. For simulation we just use a counter to set it few cycles after reset reg [3:0] counter; always @(posedge clk or posedge reset)begin - if(reset) counter<=0; - else if(counter<4) counter=counter+1'b1; + if(reset) counter<=0; + else if(counter<4) counter<=counter+1'b1; end - + wire credit_release = counter==4; genvar i; generate for (i=0; i Date: Fri, 22 May 2026 12:40:46 +0200 Subject: [PATCH 107/107] change chi_interface package name --- mpsoc/rtl/src_ambachi/chi_wrapper.sv | 6 +++--- mpsoc/rtl/src_ambachi/noc_localparam.v | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mpsoc/rtl/src_ambachi/chi_wrapper.sv b/mpsoc/rtl/src_ambachi/chi_wrapper.sv index 60aee8b..085a4ac 100644 --- a/mpsoc/rtl/src_ambachi/chi_wrapper.sv +++ b/mpsoc/rtl/src_ambachi/chi_wrapper.sv @@ -20,7 +20,7 @@ module chi_to_pronoc_wrapper ( reset ); import pronoc_pkg::*; - import amba_5_chi_c_pkg::*; + import amba_5_chi_pkg::*; input chi_flitpend_i, chi_flitv_i, chi_lcrdv_i, clk,reset; input [Fpay-1 : 0] chi_flit_i; @@ -126,7 +126,7 @@ module snp_chi_to_pronoc_wrapper ( reset ); import pronoc_pkg::*; - import amba_5_chi_c_pkg::*; + import amba_5_chi_pkg::*; input chi_flitpend_i, chi_flitv_i, chi_lcrdv_i, clk, reset; input [Fpay-1 : 0] chi_flit_i; @@ -267,7 +267,7 @@ module chi_noc ( ); import pronoc_pkg::*; - import amba_5_chi_c_pkg::*; + import amba_5_chi_pkg::*; // Clock and Reset input clk,reset; diff --git a/mpsoc/rtl/src_ambachi/noc_localparam.v b/mpsoc/rtl/src_ambachi/noc_localparam.v index 4e04e61..0a413eb 100644 --- a/mpsoc/rtl/src_ambachi/noc_localparam.v +++ b/mpsoc/rtl/src_ambachi/noc_localparam.v @@ -29,7 +29,7 @@ `ifdef NOC_LOCAL_PARAM //TODO: replace it with package - import amba_5_chi_c_pkg::*; + import amba_5_chi_pkg::*; `include "pronoc_conf.svh"